- The shot end's button check (0x4def52) answers "held" for the auto-attack target, like the melee swing end. - An art order counts as started when the art's cooldown rises, so bow arts and arts ordered mid-swing hand over to auto-attack. - re/crash.cpp: a watchdog writes sacred_re_hang.dmp when the engine tick stops for 10 s while the game is in front. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
5.9 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::IsHostileTo0x548dd0, 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 (
callat0x4e65c6) 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.
Next target, and auto-attack after arts (2026-10-16)
User requests: when the target dies, go on with the next enemy close by; after a melee art always auto-attack, after a ranged art only with a ranged weapon.
Measured with a temporary log (distance hero → target when the hero started the swing or cast, battlemage with a staff):
- +0x150 low word: 1 walking (also walking up to a target), 3 weapon attack,
4 casting a spell. The "1 art" above was the walk up; 8 (seen after it on
2026-10-15) is presumably a combat move. Names in
game/engine/orders.h. - Weapon swings started at 117..149 after walking up from up to 1382: the
game's contact distance (
0x4dbaa0, mean of both body radii by object type; heroes 110 with a weapon, 80 without). - Spells (Blitzschlag 0x21, art 5) started at once from 647..803: no walk-up. Their cast limit, if any, is beyond that.
Rules (autoattack.cpp):
- Close range =
ContactDistance(hero, hero) + 100(≈ 210) with a melee weapon; 600 with a ranged one (TODO: measure a ranged hero). Ranged weapon = weapon class (0x546df0) 6 throwing, 7 bow, 12 crossbow, 13 pistol. - The target died: the nearest living hostile creature within close range
(
game::NearestHostile) becomes the target, else auto-attack stops. - An art order (not a buff / ally / corpse art) is watched until the hero starts it (action 4 or 8). It is melee if the hero walked first, ranged if it starts farther away than contact distance + 100, else as remembered for that art (default melee). Melee: auto-attack its enemy target, or the nearest enemy close by. Ranged: the same with a ranged weapon; with a melee weapon only an enemy already in close range (the art's target if it is, else the nearest), otherwise auto-attack stops. Until the art starts, no attack orders are sent.
Bow speed and arts that start differently (2026-10-18)
User: auto-attack after spells not fully reliable; with a ranged weapon it does not reach full speed; bow arts (Spinnenpfeil) do not start it.
Measured (order log + a log of every cMouseCursor::IsButtonHeld caller):
- A shot with a bow is action 5. Before the next shot the game checks the
button at
0x4def52(shooter esi, target creature edi): held and the target hostile -> it shoots again. A held button fired 2 s without new orders; auto-attack sent one order per 0.67 s.0x4def89right after retargets to the creature under the cursor when held. - Several arts (0x42f, 0x3ee) never showed action 4 or 8, so the cast watch waited its 5 s and auto-attack stopped. Arts ordered during a swing or cast were taken as started by that action.
Now:
0x4def52is redirected like the melee swing end (SwingContinues): "held" for the auto-attack target.0x4def89is left alone.- An art counts as started when its cooldown rises (
GetArtCooldownremaining above the value at the order, which follows regeneration). Arts without a cooldown entry: the hero went into a new action other than walking or idle.