Files
sacred_k/docs/auto-attack.md
T
khallaandClaude Opus 5.5 1fd89524d3 Skills, auto-attack, aura and chain lightning rework, Esc, cache fix
- Skill bar: no art selection; slot 0 is the right-click art, keys 0-6 cast
  slots directly; cooldown labels in exact seconds; slot 0 set apart.
- Arts regenerate on their own (casting no longer refills the group).
- Auto-attack after targeting or casting at a hostile creature, at the speed
  of a held button.
- Auras can be recast while active (renew, no second visual).
- Blicke wie Klingen hits every enemy in range, physical, with life leech.
- Blitzschlag steers the game's own chain: 3 + level/5 hits, 1 + level/10
  chains, re-hits a lone enemy.
- Weapon sets: click selects, drag only from the selected set; the leftmost
  set is clickable (signed hit tests).
- Esc closes open windows before opening the game menu.
- HUD: standalone buttons and texts are centred.
- Record cache sized for widened views (town lag while walking).
- Shared game code: orders, fx events, text drawing, cooldowns, effects.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 00:11:38 +02:00

3.0 KiB

Auto-attack (src/mods/autoattack.cpp)

Goal (user, 2026-10-15): once an enemy was targeted, by a left click or by casting an art at it, the hero keeps attacking it with the weapon between casts. Left click stays the normal attack; right click casts slot 0.

What the game does (order log, 2026-10-15)

Orders logged in cCreature::ReceiveOrder (0x52e400) for the hero, with the hero's fields per tick:

Order Caller Fields
left click on an enemy: cmd 7 0x617abb +0x18 target id, +0x1c / +0x20 its position
art: cmd 0x105 0x6172f9 (SendCreatureOrder) +0x10 target id, +0x18 / +0x1c ground point, +0x28 0x64, +0x2c 1, +0x30 art id
walk: cmd 4 0x6172f9 see docs/wasd.md
hit by an enemy: cmd 5 0x4ea478 +0x8 attacker id, +0x10 the hero, +0x2c 1.0f (every ~0.5 s)

One left click is one swing: hero +0x150 goes 0x10000 (idle) -> 0x10003 (attack) -> 0x20003 -> 0x10000 within about a second; +0xfc 0 -> 4 -> 0x20004 -> 0 at the start. An art: 0x10001 -> 0x10008 -> 0x20008 -> 0 -> 0x10000. Low word of +0x150: current action (0 none, 1 art, 3 attack, 6 dying), high word its phase. cCreature::IsAlive (0x548ef0): +0xfc != 9, +0x150 != 6, health +0x4d8 != 0.

Holding the left button on an enemy (measured): one attack order, then +0x150 stays 0x10003 for as long as the button is held (9 s in the test), no further orders. At the end of each swing (after the hit, 0x4e6584) the attack code calls cMouseCursor::IsButtonHeld (0x655ab0, cursor word bit 8) at 0x4e65c6 (attacker in esi, target creature in ebp; measured: the only caller answered "held" during a held attack): held -> the next swing starts right away, otherwise recovery (+0x152 = 2) and idle. (0x4f665a, a similar check in another creature update, is not reached by the hero.) Re-sending the attack order after the hero went idle took ~1.45 s per swing (0.36 s wind-up, 0.64 s attack, 0.43 s recovery).

The mod

  • An attack order or an art order whose target is hostile (cCreature::IsHostileTo 0x548dd0, faction relation) sets the combat target. (First version: "not an ally", which included NPCs: clicking a trader made auto-attack talk to it again and again, reopening its window with new stock.) any walk order (mouse, WASD, stop) clears it, as does the target's death.
  • Each engine tick, if the hero is idle (+0x150 low word 0), no mouse button is held (engine +0x54 & 0x10), input is not blocked (0x4000) and no skill key is held, it sends the attack order a left click sends. After sending it waits up to 5 ticks for the swing to start.
  • The end-of-swing button check (call at 0x4e65c6) is redirected: it also answers "held" when the hero hits its auto-attack target, the target is alive and no skill key is held. Swings then chain like with a held button; the tick only restarts the attack after casts.
  • Self / ally arts pointed at an enemy lose their target (src/mods/arttarget.cpp) and therefore do not start auto-attack.