paavohtl Claude Opus 4.6 (1M context) commited on
Commit
ccbf111
Β·
1 Parent(s): 586482f

docs: add comprehensive weapon system reference

Browse files

Document 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>

Files changed (1) hide show
  1. docs/re-notes/weapon-system.md +478 -0
docs/re-notes/weapon-system.md ADDED
@@ -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)