docs: add comprehensive weapon system reference
Browse filesDocument the complete weapon system architecture from Ghidra analysis,
wkJellyWorm RE sources, and existing OpenWA code:
- WeaponEntry/WeaponTable structure and initialization
- Ammunition & delay system (TeamArenaState flat indexing)
- Weapon availability rules (per-weapon disable conditions)
- FireWeapon dispatch table (4 types Γ subtypes β 20+ handlers)
- CTaskMissile structure (0x40C bytes, spawn/weapon/render data)
- Projectile creation, explosion, and terrain damage flow
- Weapon panel UI functions
- Complete function address table with port status
- Mermaid diagrams for object relationships and firing sequence
Named 12 FireWeapon dispatch functions in Ghidra during research.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- docs/re-notes/weapon-system.md +478 -0
|
@@ -0,0 +1,478 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Weapon System
|
| 2 |
+
|
| 3 |
+
Comprehensive reference for the Worms Armageddon 3.8.1 weapon system internals.
|
| 4 |
+
|
| 5 |
+
## Overview
|
| 6 |
+
|
| 7 |
+
The weapon system spans multiple subsystems: a **weapon table** defining all 71 weapons, an **ammo/delay tracker** per team/alliance, a **firing dispatch** that routes weapon activation to type-specific handlers, **CTaskMissile** objects for in-flight projectiles, and an **explosion system** for terrain damage.
|
| 8 |
+
|
| 9 |
+
### Object Relationships
|
| 10 |
+
|
| 11 |
+
```mermaid
|
| 12 |
+
graph TD
|
| 13 |
+
DDGame["DDGame (0x98B8 bytes)"]
|
| 14 |
+
WT["WeaponTable<br/>DDGame+0x510"]
|
| 15 |
+
TAS["TeamArenaState<br/>DDGame+0x4628"]
|
| 16 |
+
WP["WeaponPanel<br/>DDGame+0x548"]
|
| 17 |
+
CTW["CTaskWorm<br/>(per-live-worm task)"]
|
| 18 |
+
CTM["CTaskMissile<br/>(per-projectile task)"]
|
| 19 |
+
EXP["CreateExplosion"]
|
| 20 |
+
LAND["PCLandscape"]
|
| 21 |
+
|
| 22 |
+
DDGame --> WT
|
| 23 |
+
DDGame --> TAS
|
| 24 |
+
DDGame --> WP
|
| 25 |
+
CTW -->|"FireWeapon"| CTM
|
| 26 |
+
CTW -->|"GetAmmo/SubtractAmmo"| TAS
|
| 27 |
+
CTM -->|"impact"| EXP
|
| 28 |
+
EXP -->|"terrain damage"| LAND
|
| 29 |
+
WP -->|"reads availability"| WT
|
| 30 |
+
WP -->|"reads ammo"| TAS
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
### Firing Sequence
|
| 34 |
+
|
| 35 |
+
```mermaid
|
| 36 |
+
sequenceDiagram
|
| 37 |
+
participant P as Player Input
|
| 38 |
+
participant W as CTaskWorm
|
| 39 |
+
participant FR as WeaponRelease
|
| 40 |
+
participant FW as FireWeapon
|
| 41 |
+
participant CW as CreateWeaponProjectile
|
| 42 |
+
participant M as CTaskMissile
|
| 43 |
+
participant E as CreateExplosion
|
| 44 |
+
participant L as PCLandscape
|
| 45 |
+
|
| 46 |
+
P->>W: Fire key pressed
|
| 47 |
+
W->>FR: WeaponRelease(0x51C3D0)<br/>position, angle
|
| 48 |
+
FR->>FW: FireWeapon(0x51EE60)<br/>weapon type dispatch
|
| 49 |
+
FW->>CW: CreateWeaponProjectile(0x51E0F0)
|
| 50 |
+
CW->>M: CTaskMissile__Constructor(0x507D10)<br/>allocate 0x40C bytes
|
| 51 |
+
loop Every frame
|
| 52 |
+
M->>M: PhysicsUpdate(0x508C90)<br/>gravity, wind, collision
|
| 53 |
+
end
|
| 54 |
+
M->>E: CreateExplosion(0x548080)
|
| 55 |
+
E->>L: ApplyExplosion(0x57C820)<br/>terrain bitmap damage
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
## WeaponEntry & WeaponTable
|
| 59 |
+
|
| 60 |
+
### WeaponTable (DDGame+0x510)
|
| 61 |
+
|
| 62 |
+
Allocated by `InitWeaponTable` (0x53CAB0, stdcall(wrapper), RET 0x4). Called once
|
| 63 |
+
during `CTaskGameState__vmethod_7` at game start.
|
| 64 |
+
|
| 65 |
+
```
|
| 66 |
+
+0x00 [u8; 0x10] _header Purpose unknown
|
| 67 |
+
+0x10 [WeaponEntry; 71] entries Standard weapons (0..70)
|
| 68 |
+
Total: 0x10 + 71 Γ 0x1D0 = 0x133E0 bytes
|
| 69 |
+
```
|
| 70 |
+
|
| 71 |
+
### WeaponEntry (0x1D0 = 464 bytes per entry)
|
| 72 |
+
|
| 73 |
+
Source: `wkJellyWorm/src/CustomWeapons.h` (WeaponStruct).
|
| 74 |
+
|
| 75 |
+
```
|
| 76 |
+
+0x00 *const c_char name1 Primary weapon name (non-null = defined)
|
| 77 |
+
+0x04 *const c_char name2 Secondary weapon name
|
| 78 |
+
+0x08 i32 panel_row Weapon panel row index (0..12)
|
| 79 |
+
+0x0C i32 unknown_0c Unknown
|
| 80 |
+
+0x10 [u8; 0x1C0] unknown Remaining 113 Γ i32 fields (opaque)
|
| 81 |
+
```
|
| 82 |
+
|
| 83 |
+
**InitWeaponTable sets per-entry:**
|
| 84 |
+
- +0x08 = 0xFFFFFFFF (initial state)
|
| 85 |
+
- +0x24 = 0xFFFFFFFF (availability flag)
|
| 86 |
+
- +0x28 = 1 (enabled)
|
| 87 |
+
|
| 88 |
+
**Rust types:** `WeaponEntry`, `WeaponTable` in `openwa-core/src/game/weapon.rs`.
|
| 89 |
+
|
| 90 |
+
### Weapon Enum (71 entries)
|
| 91 |
+
|
| 92 |
+
Defined in `openwa-core/src/game/weapon.rs`. Key weapon IDs:
|
| 93 |
+
|
| 94 |
+
| ID | Hex | Name | Category |
|
| 95 |
+
|----|-----|------|----------|
|
| 96 |
+
| 0 | 0x00 | None | - |
|
| 97 |
+
| 1 | 0x01 | Bazooka | Projectile |
|
| 98 |
+
| 2 | 0x02 | HomingMissile | Projectile (homing) |
|
| 99 |
+
| 6 | 0x06 | Grenade | Thrown |
|
| 100 |
+
| 10 | 0x0A | Earthquake | Special (net-disabled) |
|
| 101 |
+
| 24 | 0x18 | SuperSheep | Animal (restricted) |
|
| 102 |
+
| 25 | 0x19 | AquaSheep | Animal (restricted) |
|
| 103 |
+
| 37 | 0x25 | NinjaRope | Rope |
|
| 104 |
+
| 40 | 0x28 | Teleport | Utility (immune to sudden death) |
|
| 105 |
+
| 54 | 0x36 | Donkey | Special (disable flag) |
|
| 106 |
+
| 55 | 0x37 | NuclearTest | Special (net-disabled) |
|
| 107 |
+
| 56 | 0x38 | Armageddon | Special (net-disabled) |
|
| 108 |
+
| 59 | 0x3B | SelectWorm | Action (needs >1 alive worm) |
|
| 109 |
+
| 66 | 0x42 | Invisibility | Power-up (mode flag) |
|
| 110 |
+
| 69 | 0x45 | DoubleTurnTime | Power-up (threshold) |
|
| 111 |
+
|
| 112 |
+
## Ammunition & Delay System
|
| 113 |
+
|
| 114 |
+
### Storage: TeamArenaState (DDGame+0x4628)
|
| 115 |
+
|
| 116 |
+
Ammo and delay are stored in a flat array indexed by alliance and weapon ID.
|
| 117 |
+
|
| 118 |
+
```
|
| 119 |
+
Flat index = alliance_id Γ 142 + weapon_id
|
| 120 |
+
|
| 121 |
+
Ammo: TeamArenaState + 0x1EB4 + flat_index Γ 4
|
| 122 |
+
Delay: TeamArenaState + 0x1EB4 + (flat_index + 71) Γ 4
|
| 123 |
+
|
| 124 |
+
Values: -1 = unlimited, 0 = none, >0 = count
|
| 125 |
+
Delay: 0 = available, >0 = turns until available
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
6 alliances Γ 142 entries (71 ammo + 71 delay) = 852 total slots.
|
| 129 |
+
|
| 130 |
+
Alliance ID is read from the team's sentinel worm field at offset +0x80
|
| 131 |
+
(`sentinel_weapon_alliance`).
|
| 132 |
+
|
| 133 |
+
### Functions
|
| 134 |
+
|
| 135 |
+
| Function | Address | Convention | Parameters |
|
| 136 |
+
|----------|---------|------------|------------|
|
| 137 |
+
| GetAmmo | 0x5225E0 | usercall | EAX=team_index, ESI=arena_base, EDX=weapon_id β EAX=ammo |
|
| 138 |
+
| AddAmmo | 0x522640 | usercall | EAX=team_index, EDX=amount, stack(base, weapon_id), RET 0x8 |
|
| 139 |
+
| SubtractAmmo | 0x522680 | usercall | EAX=team_index, ECX=arena_base, stack(weapon_id), RET 0x4 |
|
| 140 |
+
| SubtractAmmo_v2 | 0x558E80 | fastcall | ECX=param1, EDX=CTaskTeam* |
|
| 141 |
+
| CountAliveWorms | 0x5225A0 | usercall | EAX=team_index, ECX=arena_base β EAX=count |
|
| 142 |
+
|
| 143 |
+
**GetAmmo special rules:**
|
| 144 |
+
- Returns 0 if weapon delay > 0 (weapon on cooldown)
|
| 145 |
+
- Sudden death (game_phase β₯ 484): returns 0 for all except Teleport (0x28)
|
| 146 |
+
- SelectWorm (0x3B): returns 0 if team has β€1 alive worm
|
| 147 |
+
- Game mode flag at TeamArenaState+0x2C0C can override delay checks
|
| 148 |
+
|
| 149 |
+
**SubtractAmmo issue:** Our hook at 0x522680 reportedly never triggered during
|
| 150 |
+
gameplay, despite 5 xrefs in Ghidra:
|
| 151 |
+
- `CTaskWorm__HandleMessage` (0x512C27)
|
| 152 |
+
- `CTaskTeam_vt2__vmethod_2` (0x558443)
|
| 153 |
+
- `FUN_0055f8c0` (0x55F995, 0x55FA77, 0x55FD78)
|
| 154 |
+
|
| 155 |
+
The second variant at 0x558E80 has 3 xrefs from `CTaskTeam_vt2__vmethod_2`.
|
| 156 |
+
The hook issue may be a calling convention mismatch in the trampoline rather
|
| 157 |
+
than the function not being called. Needs investigation.
|
| 158 |
+
|
| 159 |
+
**Port status:** All 4 functions ported in `replacements/weapon.rs`.
|
| 160 |
+
|
| 161 |
+
## Weapon Availability
|
| 162 |
+
|
| 163 |
+
### DDGame__CheckWeaponAvail (0x53FFC0)
|
| 164 |
+
|
| 165 |
+
Convention: fastcall(DDGame), ESI=weapon_id. Ported as `check_weapon_avail`
|
| 166 |
+
in `openwa-core/src/engine/game_state_init.rs`.
|
| 167 |
+
|
| 168 |
+
**Per-weapon disable rules:**
|
| 169 |
+
|
| 170 |
+
| Weapon(s) | Condition | Result |
|
| 171 |
+
|-----------|-----------|--------|
|
| 172 |
+
| Earthquake (10), NuclearTest (55), Armageddon (56) | `net_config_2 != 0 && net_weapon_exception == 0` | Disabled in network games |
|
| 173 |
+
| Donkey (54) | `donkey_disabled != 0` | GameInfo+0xD94C flag |
|
| 174 |
+
| Invisibility (66) | `invisibility_mode == 0 && network_ecx == 0` | Needs network or mode flag |
|
| 175 |
+
| DoubleTurnTime (69) | `game_version > 0xD1 && threshold > 0x7FFF` | GameInfo+0xD932 threshold |
|
| 176 |
+
|
| 177 |
+
**General availability path:**
|
| 178 |
+
1. Check weapon table entry: name1 non-null = weapon defined
|
| 179 |
+
2. If `level_width_raw == 0` OR weapon defined: check super weapon rules
|
| 180 |
+
3. `IsSuperWeapon` (0x565960): if super and `super_weapon_allowed == 0`, disable (unless game_version < 0x2A)
|
| 181 |
+
4. `supersheep_restricted` (DDGame+0x7E25): gates SuperSheep/AquaSheep check
|
| 182 |
+
5. `aquasheep_is_supersheep` (GameInfo+0xD956): when set, AquaSheep slot becomes SuperSheep
|
| 183 |
+
|
| 184 |
+
### DDGame__IsSuperWeapon (0x565960)
|
| 185 |
+
|
| 186 |
+
Convention: fastcall(weapon_id). Returns 1 for super weapons:
|
| 187 |
+
|
| 188 |
+
Super weapon IDs: 16, 19, 29-31, 36, 41-42, 45-46, 49-51, 54-56, 60-61
|
| 189 |
+
|
| 190 |
+
## FireWeapon Dispatch (0x51EE60)
|
| 191 |
+
|
| 192 |
+
Convention: thiscall. `in_EAX` = weapon context structure where:
|
| 193 |
+
- +0x30: weapon type (1-4)
|
| 194 |
+
- +0x34: subtype for type 3 and type 4
|
| 195 |
+
- +0x38: subtype for type 1 and type 2
|
| 196 |
+
- +0x3C: parameters base (passed to sub-functions)
|
| 197 |
+
|
| 198 |
+
`param_2` = DDGameWrapper pointer. Sets `param_2[0xF] = 1` on completion.
|
| 199 |
+
|
| 200 |
+
### Type 1: Projectile Weapons
|
| 201 |
+
|
| 202 |
+
| Subtype | Function | Address | Weapons |
|
| 203 |
+
|---------|----------|---------|---------|
|
| 204 |
+
| 1 | FireWeapon__PlacedExplosive | 0x51EC80 | Dynamite, Mine, Petrol Bomb |
|
| 205 |
+
| 2 | FireWeapon__Projectile | 0x51DFB0 | Bazooka, Mortar, Longbow |
|
| 206 |
+
| 3 | CreateWeaponProjectile | 0x51E0F0 | Homing Missile, Homing Pigeon |
|
| 207 |
+
| 4 | FireWeapon__Shotgun | 0x51ED90 | Shotgun, Handgun, Uzi, Minigun |
|
| 208 |
+
|
| 209 |
+
### Type 2: Rope Weapons
|
| 210 |
+
|
| 211 |
+
| Subtype | Function | Address | Weapons |
|
| 212 |
+
|---------|----------|---------|---------|
|
| 213 |
+
| 1 | FireWeapon__RopeType1 | 0x51E1C0 | Ninja Rope (attach) |
|
| 214 |
+
| 2 | CreateWeaponProjectile | 0x51E0F0 | Ninja Rope (projectile mode) |
|
| 215 |
+
| 3 | FireWeapon__RopeType3 | 0x51E240 | Bungee |
|
| 216 |
+
|
| 217 |
+
### Type 3: Thrown Weapons
|
| 218 |
+
|
| 219 |
+
| Subtype | Function | Address | Weapons |
|
| 220 |
+
|---------|----------|---------|---------|
|
| 221 |
+
| (all) | FireWeapon__GrenadeMortar | 0x51E2C0 | Grenade, Cluster Bomb, Banana Bomb, Holy Grenade |
|
| 222 |
+
|
| 223 |
+
### Type 4: Special Weapons
|
| 224 |
+
|
| 225 |
+
| Subtype | Function | Address | Description |
|
| 226 |
+
|---------|----------|---------|-------------|
|
| 227 |
+
| 1 | vtable[0xE](0x6C) | (indirect) | Blowtorch |
|
| 228 |
+
| 2 | FireWeapon__Special_Type2 | 0x51E3E0 | Pneumatic Drill |
|
| 229 |
+
| 3 | FireWeapon__Special_Type3 | 0x51E350 | Girder |
|
| 230 |
+
| 4 | vtable[0xE](0x6D) | (indirect) | Baseball Bat |
|
| 231 |
+
| 5 | vtable[0xE](0x75) | (indirect) | Fire Punch |
|
| 232 |
+
| 6 | vtable[0xE](0x70) | (indirect) | Dragon Ball |
|
| 233 |
+
| 8 | vtable[0xE](0x6E) | (indirect) | Kamikaze |
|
| 234 |
+
| 9 | FireWeapon__Special_Type9 | 0x51E480 | Prod |
|
| 235 |
+
| 10 | FireWeapon__Special_Type10 | 0x51E710 | Air Strike |
|
| 236 |
+
| 11 | vtable[0xE](0x71) | (indirect) | Scales of Justice |
|
| 237 |
+
| 13 | FireWeapon__Special_Type13 | 0x51E5C0 | Napalm Strike |
|
| 238 |
+
| 14 | FireWeapon__Special_Type14 | 0x51E670 | Mail/Mine/Mole Strike |
|
| 239 |
+
| 16 | FUN_0051EB00 (conditional) | 0x51EB00 | Teleport (checks FUN_516930 first) |
|
| 240 |
+
| 17 | FireWeapon__Special_Type17 | 0x51E920 | Freeze |
|
| 241 |
+
| 18 | vtable[0xE](0x72) | (indirect) | Suicide Bomber |
|
| 242 |
+
| 19 | FireWeapon__Special_Type19 | 0x51E8C0 | Skip Go |
|
| 243 |
+
| 20 | FireWeapon__Special_Type20 | 0x51E600 | Surrender |
|
| 244 |
+
| 21 | FireWeapon__Special_Type21 | 0x51EBE0 | Select Worm |
|
| 245 |
+
| 22 | FireWeapon__Special_Type22 | 0x51EC30 | Jet Pack |
|
| 246 |
+
| 23 | vtable[0xE](0x78) | (indirect) | Magic Bullet |
|
| 247 |
+
| 24 | FireWeapon__Special_Type24 | 0x51EA60 | Low Gravity / Fast Walk |
|
| 248 |
+
|
| 249 |
+
## CTaskMissile (0x40C bytes)
|
| 250 |
+
|
| 251 |
+
Extends CGameTask (0xFC base). Represents an in-flight projectile.
|
| 252 |
+
|
| 253 |
+
```
|
| 254 |
+
Constructor: 0x507D10 (stdcall, 4 params)
|
| 255 |
+
Vtable: 0x664438
|
| 256 |
+
Class type: 0x0B
|
| 257 |
+
Allocation: 0x40C bytes via wa_malloc
|
| 258 |
+
```
|
| 259 |
+
|
| 260 |
+
### Structure Layout
|
| 261 |
+
|
| 262 |
+
```
|
| 263 |
+
+0x000 CGameTask base (0xFC bytes)
|
| 264 |
+
+0x084 speed_x Fixed16.16 horizontal velocity
|
| 265 |
+
+0x088 speed_y Fixed16.16 vertical velocity
|
| 266 |
+
+0x090 pos_x Fixed16.16 world X
|
| 267 |
+
+0x094 pos_y Fixed16.16 world Y
|
| 268 |
+
|
| 269 |
+
+0x128 u32 launch_seed Position-derived seed
|
| 270 |
+
+0x12C u32 slot_id Object pool slot index
|
| 271 |
+
|
| 272 |
+
+0x130 spawn_params [11 DWORDs = 44 bytes]
|
| 273 |
+
[0] owner_id Team that fired
|
| 274 |
+
[2-3] spawn_x/y Fixed16.16 launch position
|
| 275 |
+
[4-5] speed_x/y Fixed16.16 initial velocity
|
| 276 |
+
[8] pellet_index Cluster volley index
|
| 277 |
+
|
| 278 |
+
+0x15C weapon_data [94 DWORDs = 376 bytes]
|
| 279 |
+
[0x0F] gravity_pct 100 = 1.0Γ gravity
|
| 280 |
+
[0x10] bounce_pct Bounce coefficient
|
| 281 |
+
[0x12] friction_pct Friction coefficient
|
| 282 |
+
[0x1A] missile_type 2=Standard, 3=Homing, 4=Sheep, 5=Cluster
|
| 283 |
+
[0x1C] render_timer Fuse countdown
|
| 284 |
+
|
| 285 |
+
+0x2D4 render_data [42 DWORDs = 168 bytes]
|
| 286 |
+
Physics parameters (shifted copy of weapon_data)
|
| 287 |
+
|
| 288 |
+
+0x3C8 i32 direction -1 (left) or +1 (right)
|
| 289 |
+
```
|
| 290 |
+
|
| 291 |
+
### Missile Type Enum
|
| 292 |
+
|
| 293 |
+
| Value | Type | Behavior |
|
| 294 |
+
|-------|------|----------|
|
| 295 |
+
| 2 | Standard | Straight trajectory with gravity |
|
| 296 |
+
| 3 | Homing | Tracks target position |
|
| 297 |
+
| 4 | Sheep | Walking behavior on terrain |
|
| 298 |
+
| 5 | Cluster | Splits into sub-munitions on impact |
|
| 299 |
+
|
| 300 |
+
### Key Methods
|
| 301 |
+
|
| 302 |
+
| Method | Address | Description |
|
| 303 |
+
|--------|---------|-------------|
|
| 304 |
+
| Constructor | 0x507D10 | Initialize physics, copy weapon data from scheme |
|
| 305 |
+
| Init | 0x508640 | Reset physics state |
|
| 306 |
+
| PhysicsUpdate | 0x508C90 | Per-frame trajectory, gravity, wind, collision |
|
| 307 |
+
| HandleMessage | 0x50B400 | Event processing (detonation triggers, etc.) |
|
| 308 |
+
| Free | 0x508330 | Cleanup and pool return |
|
| 309 |
+
| vt12 | 0x508C70 | Vtable slot 12 |
|
| 310 |
+
| vt18_GetField130 | 0x50BFA0 | Returns spawn_params pointer |
|
| 311 |
+
|
| 312 |
+
### Missile Count Limit
|
| 313 |
+
|
| 314 |
+
DDGame+0x72A4 tracks active missile count. `CreateWeaponProjectile` checks:
|
| 315 |
+
- If count + 7 < 0x2BD (701): create missile normally
|
| 316 |
+
- If exceeded and game_version < 0x3C: set error code 6 at DDGame+0x4624, load
|
| 317 |
+
string resource 0x70F as error message at DDGame+0x7EF4
|
| 318 |
+
- Otherwise: silently fail
|
| 319 |
+
|
| 320 |
+
## Projectile Creation (0x51E0F0)
|
| 321 |
+
|
| 322 |
+
`CreateWeaponProjectile`: thiscall(this=context, param_2=missile_params, param_3=launch_params).
|
| 323 |
+
|
| 324 |
+
1. Read DDGame via `this+0x2C` (CTask.ddgame field)
|
| 325 |
+
2. Check missile count limit (DDGame+0x72A4 + 7 < 0x2BD)
|
| 326 |
+
3. Call `FUN_004FDF90(this)` β pool slot allocator
|
| 327 |
+
4. `wa_malloc(0x40C)` + `memset(0, 0x3EC)`
|
| 328 |
+
5. `CTaskMissile__Constructor(slot, missile_params, launch_params)`
|
| 329 |
+
6. Return allocated missile pointer
|
| 330 |
+
|
| 331 |
+
## Explosion & Terrain Damage
|
| 332 |
+
|
| 333 |
+
| Function | Address | Convention | Description |
|
| 334 |
+
|----------|---------|------------|-------------|
|
| 335 |
+
| CreateExplosion | 0x548080 | usercall(ESI=context) | Spawns explosion task via pool allocator + vtable dispatch |
|
| 336 |
+
| PCLandscape_ApplyExplosion | 0x57C820 | (unknown) | Modifies terrain bitmap, creates crater |
|
| 337 |
+
|
| 338 |
+
CreateExplosion is a thin wrapper: allocates via `FUN_004FDF90`, then calls
|
| 339 |
+
`vtable[2]()` on the allocated object. The actual explosion logic (radius,
|
| 340 |
+
damage, terrain removal) lives in the explosion task's ProcessFrame.
|
| 341 |
+
|
| 342 |
+
## Weapon Panel UI
|
| 343 |
+
|
| 344 |
+
| Function | Address | Description |
|
| 345 |
+
|----------|---------|-------------|
|
| 346 |
+
| DDGame__InitWeaponPanel_Maybe | 0x567770 | Initialize panel structures and availability grid |
|
| 347 |
+
| PrepareWeaponPanel | 0x568220 | Main panel renderer (~2000 lines). Iterates weapons by row, checks availability, renders tiles |
|
| 348 |
+
| WeaponPanelDrawTile | 0x567AA0 | Render individual weapon tile |
|
| 349 |
+
| WeaponPanelDescription | 0x567F80 | Show ammo/delay info on hover |
|
| 350 |
+
| WeaponPanelCheckClick | 0x5690B0 | Handle weapon selection clicks |
|
| 351 |
+
|
| 352 |
+
**Panel geometry:** 5 columns Γ 13 rows. Each tile is 29px wide.
|
| 353 |
+
Custom weapons (wkJellyWorm): dynamic columns up to 256 weapons.
|
| 354 |
+
|
| 355 |
+
## Weapon Crate System
|
| 356 |
+
|
| 357 |
+
- `CTaskCrate__Constructor` (0x502490): creates a weapon crate in the game world
|
| 358 |
+
- Crate probability per weapon defined in scheme (`WeaponSettings.crate_probability`, 0-100%)
|
| 359 |
+
- Crate drops award random weapons weighted by probability
|
| 360 |
+
|
| 361 |
+
## Scheme Integration
|
| 362 |
+
|
| 363 |
+
Weapon configuration flows from `.wsc` scheme files into GameInfo, then into the
|
| 364 |
+
weapon table and ammo arrays at game start.
|
| 365 |
+
|
| 366 |
+
### WeaponSettings (4 bytes per weapon)
|
| 367 |
+
|
| 368 |
+
```
|
| 369 |
+
+0x00 u8 ammo 0=none, 1-10=count, 0x80+=infinite
|
| 370 |
+
+0x01 u8 power 0-20 (max varies per weapon)
|
| 371 |
+
+0x02 u8 delay Turn cooldown before available
|
| 372 |
+
+0x03 u8 crate_probability 0-100 percentage
|
| 373 |
+
```
|
| 374 |
+
|
| 375 |
+
### Scheme Formats
|
| 376 |
+
|
| 377 |
+
| Version | Payload | Weapons |
|
| 378 |
+
|---------|---------|---------|
|
| 379 |
+
| V1 | 0xD8 bytes | 45 standard weapons |
|
| 380 |
+
| V2 | 0x124 bytes | V1 + 19 super weapons |
|
| 381 |
+
| V3 | 0x192 bytes | V2 + 110 extended options (physics tweaks) |
|
| 382 |
+
|
| 383 |
+
**Port status:** Scheme parsing fully ported in `openwa-core/src/game/scheme.rs`
|
| 384 |
+
(10 hooks in `replacements/scheme.rs`).
|
| 385 |
+
|
| 386 |
+
## Complete Function Address Table
|
| 387 |
+
|
| 388 |
+
### Weapon Table & Initialization
|
| 389 |
+
|
| 390 |
+
| Function | Address | Convention | Port Status |
|
| 391 |
+
|----------|---------|------------|-------------|
|
| 392 |
+
| InitWeaponTable | 0x53CAB0 | stdcall(wrapper), RET 0x4 | Hooked (passthrough) |
|
| 393 |
+
| DDGame__CheckWeaponAvail | 0x53FFC0 | fastcall(DDGame) | **Ported** |
|
| 394 |
+
| DDGame__IsSuperWeapon | 0x565960 | fastcall(weapon_id) | **Ported** |
|
| 395 |
+
| DDGame__LoadHudAndWeaponSprites | 0x53D0E0 | stdcall(wrapper, ...) | Bridge call |
|
| 396 |
+
|
| 397 |
+
### Ammo System
|
| 398 |
+
|
| 399 |
+
| Function | Address | Convention | Port Status |
|
| 400 |
+
|----------|---------|------------|-------------|
|
| 401 |
+
| GetAmmo | 0x5225E0 | usercall(EAX,ESI,EDX) | **Ported** |
|
| 402 |
+
| AddAmmo | 0x522640 | usercall(EAX,EDX,stack), RET 0x8 | **Ported** |
|
| 403 |
+
| SubtractAmmo | 0x522680 | usercall(EAX,ECX,stack), RET 0x4 | **Ported** (may not trigger) |
|
| 404 |
+
| SubtractAmmo_v2 | 0x558E80 | fastcall(ECX,EDX) | Unported |
|
| 405 |
+
| CountAliveWorms | 0x5225A0 | usercall(EAX,ECX) | **Ported** |
|
| 406 |
+
|
| 407 |
+
### Firing & Projectiles
|
| 408 |
+
|
| 409 |
+
| Function | Address | Convention | Port Status |
|
| 410 |
+
|----------|---------|------------|-------------|
|
| 411 |
+
| WeaponRelease | 0x51C3D0 | thiscall(CTaskWorm*, ...) | Unported |
|
| 412 |
+
| FireWeapon | 0x51EE60 | thiscall, EAX=weapon_ctx | Unported |
|
| 413 |
+
| CreateWeaponProjectile | 0x51E0F0 | thiscall(context, params, launch) | Unported |
|
| 414 |
+
| CTaskMissile__Constructor | 0x507D10 | stdcall, 4 params | Unported |
|
| 415 |
+
| CTaskMissile__PhysicsUpdate | 0x508C90 | (unknown) | Unported |
|
| 416 |
+
| CTaskMissile__HandleMessage | 0x50B400 | thiscall | Unported |
|
| 417 |
+
| CreateExplosion | 0x548080 | usercall(ESI=context) | Unported |
|
| 418 |
+
| PCLandscape_ApplyExplosion | 0x57C820 | (unknown) | Unported |
|
| 419 |
+
|
| 420 |
+
### Fire Dispatch Targets
|
| 421 |
+
|
| 422 |
+
| Function | Address | Weapon Category |
|
| 423 |
+
|----------|---------|-----------------|
|
| 424 |
+
| FireWeapon__Projectile | 0x51DFB0 | Bazooka-class |
|
| 425 |
+
| FireWeapon__PlacedExplosive | 0x51EC80 | Dynamite/Mine/Petrol |
|
| 426 |
+
| FireWeapon__Shotgun | 0x51ED90 | Shotgun/Handgun/Uzi |
|
| 427 |
+
| FireWeapon__RopeType1 | 0x51E1C0 | Ninja Rope attach |
|
| 428 |
+
| FireWeapon__RopeType3 | 0x51E240 | Bungee |
|
| 429 |
+
| FireWeapon__GrenadeMortar | 0x51E2C0 | Grenade/Cluster/Banana |
|
| 430 |
+
| FireWeapon__Special_Type2 | 0x51E3E0 | Pneumatic Drill |
|
| 431 |
+
| FireWeapon__Special_Type3 | 0x51E350 | Girder |
|
| 432 |
+
| FireWeapon__Special_Type9 | 0x51E480 | Prod |
|
| 433 |
+
| FireWeapon__Special_Type10 | 0x51E710 | Air Strike |
|
| 434 |
+
| FireWeapon__Special_Type13 | 0x51E5C0 | Napalm Strike |
|
| 435 |
+
| FireWeapon__Special_Type14 | 0x51E670 | Mail/Mine/Mole Strike |
|
| 436 |
+
|
| 437 |
+
### Weapon Panel
|
| 438 |
+
|
| 439 |
+
| Function | Address | Convention | Port Status |
|
| 440 |
+
|----------|---------|------------|-------------|
|
| 441 |
+
| DDGame__InitWeaponPanel_Maybe | 0x567770 | thiscall | Unported |
|
| 442 |
+
| PrepareWeaponPanel | 0x568220 | cdecl | Unported |
|
| 443 |
+
| WeaponPanelDrawTile | 0x567AA0 | (unknown) | Unported |
|
| 444 |
+
| WeaponPanelDescription | 0x567F80 | (unknown) | Unported |
|
| 445 |
+
| WeaponPanelCheckClick | 0x5690B0 | (unknown) | Unported |
|
| 446 |
+
|
| 447 |
+
### Scheme
|
| 448 |
+
|
| 449 |
+
| Function | Address | Convention | Port Status |
|
| 450 |
+
|----------|---------|------------|-------------|
|
| 451 |
+
| Scheme__CheckWeaponLimits | 0x4D50E0 | stdcall | **Ported** |
|
| 452 |
+
| Scheme__ValidateExtendedOptions | 0x4D5110 | stdcall | **Ported** |
|
| 453 |
+
| Scheme__ReadFile | 0x4D3890 | stdcall | **Ported** |
|
| 454 |
+
|
| 455 |
+
## Port Recommendations
|
| 456 |
+
|
| 457 |
+
### Already Done
|
| 458 |
+
- Weapon enum and struct types (`WeaponEntry`, `WeaponTable`)
|
| 459 |
+
- Ammo system (4 hooks: GetAmmo, AddAmmo, SubtractAmmo, CountAliveWorms)
|
| 460 |
+
- Availability checks (2 hooks: CheckWeaponAvail, IsSuperWeapon)
|
| 461 |
+
- Scheme parsing (10 hooks covering all scheme I/O)
|
| 462 |
+
- Team/worm state queries (8 hooks in replacements/team.rs)
|
| 463 |
+
|
| 464 |
+
### Next Priority
|
| 465 |
+
1. **InitWeaponTable internals** β populate WeaponEntry fields from scheme data
|
| 466 |
+
2. **SubtractAmmo investigation** β verify hook triggers, check v2 variant
|
| 467 |
+
3. **Weapon panel init** β DDGame__InitWeaponPanel_Maybe (self-contained)
|
| 468 |
+
|
| 469 |
+
### Medium Term
|
| 470 |
+
4. **FireWeapon dispatch** β the type/subtype routing logic
|
| 471 |
+
5. **CreateWeaponProjectile** β missile allocation and pool management
|
| 472 |
+
6. **WeaponRelease** β coordinate transform and launch logic
|
| 473 |
+
|
| 474 |
+
### Long Term
|
| 475 |
+
7. **CTaskMissile physics** β gravity, wind, collision, homing AI
|
| 476 |
+
8. **Individual weapon behaviors** β each Fire__* handler
|
| 477 |
+
9. **Explosion system** β terrain damage, damage calculation
|
| 478 |
+
10. **Weapon panel rendering** β PrepareWeaponPanel (~2000 lines)
|