Combat Handlers API
The combat system uses specialized handlers for each attack type, with shared utilities for common validation logic.Attack Handlers
MagicAttackHandler
Handles magic combat for both players and mobs.- Validates spell selection and rune requirements
- Consumes runes (accounting for elemental staff infinite runes)
- Applies equipment bonuses (magic attack, magic defense)
- Grants XP: base spell XP + (2 × damage)
- Resolves spell from
npcData.combat.spellId - No rune consumption (infinite resources)
- Uses mob’s
magicstat for damage - No equipment bonuses
- No XP granted
RangedAttackHandler
Handles ranged combat for both players and mobs.- Validates bow and arrow equipment
- Consumes 1 arrow per shot
- Applies equipment bonuses (ranged attack, ranged strength)
- Grants XP: 4 per damage to Ranged, 1.33 to Constitution
- Resolves arrow from
npcData.combat.arrowId - No arrow consumption (infinite resources)
- Uses mob’s
rangedstat for damage - No equipment bonuses
- No XP granted
MeleeAttackHandler
Handles melee combat for both players and mobs.- Per-style attack bonuses (stab, slash, crush)
- Per-style defense bonuses
- Combat style bonuses (accurate, aggressive, defensive, controlled)
- Prayer multipliers for both attacker and defender
Shared Utilities
prepareMobAttack()
Shared validation and preparation for mob projectile attacks (magic and ranged).ctx- Combat attack context with access to systems and servicesdata- Attack data with entity IDs and typescombatRange- Fallback range if NPC manifest omitscombatRangeanimationType- Animation to play (“melee”, “ranged”, or “magic”)fallbackAttackSpeed- Fallback attack speed if NPC manifest omitsattackSpeedTickspreResolved- Optional pre-resolved mob entity and NPC data (avoids double lookup)
MobAttackContextwith validated state if all checks passnullif any validation fails (attack aborted)
- Entity resolution (or use
preResolved) - Alive check for both entities
- NPC data lookup via
getNPCById() - Range validation via
checkProjectileRange() - Position validation via
getEntityPosition() - Cooldown check
- Cooldown claim (set
nextAttackTicks) - Face target via
rotationManager - Play animation via
animationManager
checkProjectileRange()
Shared range validation for ranged and magic attacks.ctx- Combat attack contextattackerId- Attacker entity IDtargetId- Target entity IDattacker- Attacker entitytarget- Target entityattackRange- Maximum attack range in tiles
- Chebyshev distance if in range
-1if out of range (emitsCOMBAT_ATTACK_FAILEDevent)
- Converts positions to tiles via
tilePool - Calculates Chebyshev distance
- Checks
distance > attackRangeordistance === 0(same tile) - Emits failure event if out of range
Combat Attack Context
TheCombatAttackContext interface provides handlers with access to combat systems and services.
Type Guards
getMobAttackType()
Get mob attack type from entity config safely.- Mob’s configured
attackTypefromentity.config.attackType undefinedif not a mob or not configured
Projectile Service
createProjectile()
Create a projectile for damage application at a future tick.- Schedules damage application at calculated hit delay tick
- Stores projectile data for visual synchronization
- Emits
COMBAT_PROJECTILE_LAUNCHEDevent for client rendering
Animation Manager
setCombatEmote()
Set combat animation for an entity.- Players: Sets combat emote via player system
- Mobs: Sets server emote based on attack type
attackType === "magic"→Emotes.SPELL_CASTattackType === "ranged"→Emotes.RANGE- Default →
Emotes.COMBAT
- Holds combat pose until 1 tick before next attack
Rotation Manager
rotateTowardsTarget()
Rotate entity to face target.- Emits
COMBAT_FACE_TARGETevent for players - Updates mob rotation directly for mobs
- Essential for stationary ranged/magic attacks