COMBAT · CREEP ATTACK

How to Use Creep.attack() for a Melee Creep

CURATED PATH

These links are maintained for a concrete prerequisite, failure mode, debugging step, or next lesson instead of generic topic similarity.

Defense / Combat

Recommended next steps

Diagnose melee range failuresRange failureConfirm active ATTACK and MOVE body partsPrerequisite conceptVerify accepted combat on the next tickRuntime evidenceCoordinate Creep combat with room Tower defenseDefense system
Verification statusArticle origin: Original English guide — no translated source article · Official API docs: Checked — Creep.attack() target types, range 1, Rampart behavior, automatic hit-back, ATTACK requirement, and documented return codes · Body-part reference: Checked — one unboosted active ATTACK part has 30 melee attack power; boosts can modify that value

VERIFICATION

Evidence and test status

Article origin
Original English guide — no translated source article
Official API docs
Checked — Creep.attack() target types, range 1, Rampart behavior, automatic hit-back, ATTACK requirement, and documented return codes
Body-part reference
Checked — one unboosted active ATTACK part has 30 melee attack power; boosts can modify that value
Code review
Passed — 4 JavaScript blocks syntax checked and the bounded melee helper reviewed
Deterministic helper cases
Passed — validation, movement, attack-failure, and scheduled branches exercised with mocks
Screeps Console test
Pending — no Console execution is claimed
Live shard combat test
Pending — no live combat execution is claimed
Last verified
August 30, 2026

Quick answer

Creep.attack(target) schedules a short-range melee attack from one of your Creeps. The target must be adjacent, and the attacker needs at least one active ATTACK body part.

The safest beginner pattern is small: choose one hostile, move toward it until range 1, call attack(), preserve the return code, then inspect later state only after the tick has been processed. An OK return means the operation was scheduled successfully; it is not itself proof that the target already lost hits.

Start with the minimal move-and-attack loop

This loop is enough to teach the API boundary without hiding it behind a combat system:

const attacker = Game.creeps.Guard1;

if (attacker) {
  const target = attacker.pos.findClosestByRange(FIND_HOSTILE_CREEPS);

  if (target) {
    const attackResult = attacker.attack(target);

    if (attackResult === ERR_NOT_IN_RANGE) {
      const moveResult = attacker.moveTo(target);

      if (moveResult !== OK) {
        console.log(JSON.stringify({ stage: 'move', moveResult }));
      }
    } else if (attackResult !== OK) {
      console.log(JSON.stringify({ stage: 'attack', attackResult }));
    }
  }
}

The first attack() call is useful because its return value tells you whether range is the current blocker. When it returns ERR_NOT_IN_RANGE, moveTo() schedules movement instead; the loop tries the attack again on a later tick.

If movement itself is accepted but the Creep still does not make progress, keep that as a separate movement problem and use the moveTo() debugging guide.

Treat melee range as exactly one square

The current official API requires the target to be on an adjacent square. In Screeps terms, that is range 1. You can inspect the distance before submitting the attack:

const range = attacker.pos.getRangeTo(target);

if (range > 1) {
  const moveResult = attacker.moveTo(target);
  console.log(JSON.stringify({ range, moveResult }));
} else {
  const attackResult = attacker.attack(target);
  console.log(JSON.stringify({ range, attackResult }));
}

This version does not intentionally generate ERR_NOT_IN_RANGE; it uses the position check to choose between movement and attack. Both styles are valid. The important part is that you do not treat melee as a range-3 action or repeatedly call attack() from across the room.

For a broader explanation of action distance and ERR_NOT_IN_RANGE, see Use the Correct Action Range.

Read every documented return code

The current official Creep.attack() table documents six outcomes:

ReturnMeaningWhat to inspect next
OKThe attack operation was scheduled successfully.Wait for processed state before making a damage claim.
ERR_NOT_OWNERYou do not own the attacking Creep.Check which object your code resolved as the attacker.
ERR_BUSYThe attacker is still being spawned.Do not run active combat logic until spawning is complete.
ERR_INVALID_TARGETThe object is not a valid attackable target.Check the resolved object type and whether your target reference is still current.
ERR_NOT_IN_RANGEThe target is farther than the adjacent melee range.Move toward the target and retry on a later tick.
ERR_NO_BODYPARTThe attacker has no usable ATTACK body part.Inspect the current body, including destroyed parts.

Do not collapse these into a single falsey result. The return code tells you which boundary failed now, while later game state tells you what was actually processed.

Check active ATTACK parts before combat

The body reference lists an unboosted ATTACK part at 30 melee attack power. Boosts can modify that value, and destroyed body parts no longer contribute. For a simple readiness check, use getActiveBodyparts(ATTACK):

const activeAttackParts = attacker.getActiveBodyparts(ATTACK);

if (activeAttackParts === 0) {
  console.log(JSON.stringify({
    name: attacker.name,
    reason: 'no-active-attack-parts'
  }));
}

This check is useful before target selection because it separates “this Creep cannot currently perform melee attacks” from range and target problems. It is not a full damage calculator; boosted parts, target mitigation, Ramparts, healing, and other combat effects belong to a larger combat model.

Remember Ramparts and automatic hit-back

Two official mechanics can make a simple melee exchange look surprising:

  • Rampart protection changes what is hit. If the target is inside a Rampart, the API says the Rampart is attacked instead.
  • An attacked melee Creep can hit back automatically. If the target is a Creep with ATTACK parts and is not inside a Rampart, it automatically hits back at the attacker.

That means “my call returned OK” does not imply “only the enemy lost hits.” Inspect both sides of a melee contact when survival matters.

Use a bounded helper without building a combat framework

A small helper can keep the decision order explicit: validate the attacker, select one hostile Creep, move when outside range 1, and attack only when adjacent.

function scheduleMeleeAttack(attacker) {
  if (!attacker || !attacker.my) {
    return { ok: false, stage: 'validate', reason: 'invalid-attacker' };
  }

  if (attacker.spawning) {
    return { ok: false, stage: 'validate', reason: 'spawning' };
  }

  if (attacker.getActiveBodyparts(ATTACK) === 0) {
    return { ok: false, stage: 'validate', reason: 'no-attack-part' };
  }

  const target = attacker.pos.findClosestByRange(FIND_HOSTILE_CREEPS);
  if (!target) {
    return { ok: false, stage: 'select', reason: 'no-hostile-creep' };
  }

  const range = attacker.pos.getRangeTo(target);

  if (range > 1) {
    const moveResult = attacker.moveTo(target);
    return {
      ok: moveResult === OK,
      stage: 'move',
      code: moveResult,
      targetId: target.id,
      range
    };
  }

  const attackResult = attacker.attack(target);

  return {
    ok: attackResult === OK,
    stage: 'attack',
    code: attackResult,
    targetId: target.id,
    range
  };
}

This helper deliberately owns only one melee decision. It does not choose military objectives, path through multiple rooms, coordinate healers, estimate boosted damage, or decide whether a fight is strategically good.

Separate scheduled intent from observed damage

OK is current-tick command evidence. Damage is processed game state. If you need to know whether an exact attack was processed, keep the attacker and target identity plus the tick, then inspect the next available state rather than treating the return code as a completed outcome.

A lower target.hits value on a later tick proves that the target lost hits, but it may not prove that your one melee attack was the only cause. Towers, ranged Creeps, other melee Creeps, and other damage can share the same interval. When exact action attribution matters, use the room event log and match the relevant attack event rather than inferring causality from net hits alone. The dedicated Room.getEventLog() guide covers that evidence boundary.

Debug a melee attacker in the right order

  1. Resolve the attacker. Confirm the Creep exists, is yours, and is no longer spawning.
  2. Check active ATTACK parts. Zero means the Creep cannot currently perform this melee action.
  3. Resolve one valid target. Start with FIND_HOSTILE_CREEPS when learning the API instead of mixing hostile structures and Creeps into one selector.
  4. Check range. If it is greater than 1, solve movement first.
  5. Preserve the exact attack() return code. Do not replace six distinct outcomes with a boolean.
  6. Inspect Rampart and hit-back behavior. The object losing hits may not be the object you first expected.
  7. Verify processed state later. Use event evidence when exact attribution matters.

Know what this guide does not own

This page is specifically about one Creep's melee attack() action. It does not replace:

  • Tower.attack() room-defense automation;
  • ranged Creep combat with rangedAttack() or rangedMassAttack();
  • boost planning, damage simulation, healer coordination, or squad pathing;
  • room-level target priorities and military strategy.

Keeping those concerns separate makes a failed melee call much easier to diagnose.

FAQ

Can Creep.attack() target structures?

Yes. The documented target types are Creep, PowerCreep, and Structure. This guide uses hostile Creeps in its minimal selector so the first example stays focused.

Can I call attack() before moveTo()?

Yes. The official example calls attack() first and reacts to ERR_NOT_IN_RANGE by calling moveTo(). A pre-range-check pattern is also valid when you want to avoid intentionally generating that return code.

Does one ATTACK part always deal 30 damage?

An unboosted active ATTACK part has 30 melee attack power in the current body-part reference. Boosts can increase attack power, and the target's protection or other combat mechanics can affect the observed result.

Official documentation

SOURCE AND SCOPE

Review the evidence or continue the system

This is an original English guide. Its verification record separates documentation-reviewed claims from Console or live-shard observations that have not been performed.