# Dwarf arts: Kanonenschuss and Mörsergranate ## Requests (2026-10-25 / 2026-10-26) - Kanonenschuss (art 0x43f, `gui_spells_kanone`): "remove the knockback, instead it can be just a stun" (chosen: no push, only a stun); the range increased for the wider view; the stun particles not on targets that avoided the stun. The game's stun resistance stays (2026-10-26: "we dont ignore anything, the skill is fine for now"). - Mörsergranate (art 0x43e, `gui_spells_moerser`): "the radius of the explosion should increase every 5 skill levels". ## Measured - The cannon's code is the combat move function `0x5145d0`, case 0x43f. Its ray: `cmp edi,19h` at `0x517389`, 25 steps of 40 = 1000 range. Hostile targets get `cEvent_creature` 5 from `0x51768d`. - Stun chance `0x4fc810(level, creature)` = level × 5 / creature level × 100 (`UI_STAT_STUNNCHANCE`). On a successful roll: `0x5936e0(MOTION_HIT_A 0xaf, 3.0, 0.25)` at `0x517709` (pushes from `0x5176f8`), then the stun order `cEvent_creature` 3 with +0x14 = 100, sent by `call [eax+18h]` at `0x5177aa` (returns to `0x5177ad`). - The stun *is* the knockback. `cCreature::ReceiveOrder` `0x52e400` case 3: first the resistance `vf24(0x50)` (`0x55d0a0`: flag +0x4f0 & 0x1000 resists 2 in 3, effect 0x35d a percentage); otherwise push left +0x24d = 100, flag +0x200 |= 0x20000, attacker +0x259, ResetToIdle. `cCreature::Update` branch `0x594c82` moves a creature with that flag away from the attacker and lowers the push left by each step (`0x594deb`), measured about 100 units in 0.3 s; at 0 the flag is cleared. - The impact effect `TYPE_FX_DWARF_SHOOT_IMPACT` (0x47f) is created on every hit target by `CreateAt` at `0x517855` (target in ebx), resisted or not. - Mörsergranate: the grenade (type 0x3fa) lands and creates `TYPE_FX_GRENADEIMPACT` (0x3fc), which gathers its targets with `cObjectManager 0x5ff820` (called from `0x5ab400` at `0x5ab63d`): a creature is hit when its distance is below the impact's size (150, type table `0x428bb0`) plus its own type's size. ## The mod (`src/mods/dwarfarts.cpp`) - The HIT_A motion is jumped over (`0x5176f8`: `jmp` past the call). - The push step at `0x594deb` calls `PushStepThunk`: creatures the cannon stunned (order 3 from `0x5177ad`, kept with an end time) move by 0 and keep their push left above 0 for 1.5 s, so they stand still, then carry on. - The impact effect is created only on targets in the stun state. - The ray gets 45 steps (1800); confirmed to reach across the widened view. - The impact's gather call gets a radius of size × (1 + 0.1 × (level / 5)), with the owner's Mörsergranate level (`game::ArtLevel`). The growth 0.1 per step is our choice; not yet seen in the game (Borf's level is 2). ## Mörsergranate impact marker (asked 2026-10-25, done 2026-10-26) "Show exactly where the grenade will land and its explosion radius, a red circle with low alpha on the ground." Measured: - The landing point is decided at launch (`0x5145d0` case 0x43e): the target's position, or, closer than 200, a point 200 from the dwarf with a +-15 jitter. It goes to the new grenade (type 0x3fa) in cEventFX 0x96, constructed at `0x5169fa` (`cEventFX::Construct` 0x41e0a0, thiscall, ret 0x44: code, owner id, target id, position area / x / y / level, ...). - The impact gathers its targets at exactly that point, on several frames. The grenade object stays about 30 s after the explosion. - Ground -> screen: `0x622700` (world units -> world pixels, the isometric plane), then (pixel - camera +0x14/+0x18) / zoom +0xb60 + screen centre (floating texts 0x41e546). Checked with the hero: the screen centre. - The world view draws the ground (`0x62d530`, ground quad list), then the objects. Mod: the construct call notes grenade, owner, landing point and radius (`ImpactRadius`, shared with the hit check); after `0x62d530` a disc (alpha 0x40) with a 2 px rim (alpha 0xa0) is drawn there, without depth test, until the impact of that owner's grenade at that point gathers its targets. Tooltip (2026-10-26, "the skills tooltip does not show the current radius"): a game::Art tooltip filter adds "Explosionsradius: N" after the last value line of each level section (current level, and the next level's in the skill book), in that line's colour, from the same `ImpactRadiusAt(level)` as the hit check and the marker.