paavohtl Claude Opus 4.6 (1M context) commited on
Commit
6fb8b23
Β·
1 Parent(s): d088c03

refactor: type FireWeapon params as *const WeaponEntry and *mut CTaskWorm

Browse files

Replace raw u32 parameters with typed pointers:
- entry: *const WeaponEntry (EAX = active weapon table entry)
- worm: *mut CTaskWorm (stack param = worm task)

Read fire_type/subtypes via WeaponEntry fields instead of raw offsets.
Read selected_weapon via CTaskWorm field.

Clarify that completion flag (worm+0x3C) writes to CGameTask.subclass_data,
while params pointer (entry+0x3C) points into WeaponEntry.fire_complete β€”
same relative offset on different objects.

Verified: headless PASS, headful 133+3 / 0 FAIL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

crates/openwa-wormkit/src/replacements/weapon.rs CHANGED
@@ -11,8 +11,10 @@ use core::sync::atomic::{AtomicU32, Ordering};
11
 
12
  use openwa_core::address::va;
13
  use openwa_core::engine::ddgame::{self, TeamArenaRef};
 
14
  use openwa_core::game::Weapon;
15
  use openwa_core::log::log_line;
 
16
 
17
  use crate::hook::{self, usercall_trampoline};
18
 
@@ -179,19 +181,26 @@ unsafe extern "C" fn trampoline_fire_weapon() {
179
  }
180
 
181
  /// Rust implementation of FireWeapon dispatch.
182
- unsafe extern "cdecl" fn fire_weapon_impl(weapon_ctx: u32, local_struct: u32, worm: u32) {
183
- let ctx = weapon_ctx as *const u8;
184
- let weapon_type = *(ctx.add(0x30) as *const i32);
185
- let subtype_34 = *(ctx.add(0x34) as *const i32);
186
- let subtype_38 = *(ctx.add(0x38) as *const i32);
187
- let params = weapon_ctx.wrapping_add(0x3C);
188
- let worm_ptr = worm as *mut u8;
 
 
 
 
189
 
190
- // weapon_ctx = pointer to WeaponEntry in WeaponTable (confirmed via runtime logging).
191
- // CTaskWorm+0x36C stores &WeaponTable.entries[selected_weapon].
 
 
 
192
 
193
  // Log weapon fire
194
- let weapon_id = *(worm_ptr.add(0x170) as *const u32);
195
  let weapon_name = Weapon::try_from(weapon_id)
196
  .map(|w| format!("{:?}", w))
197
  .unwrap_or_else(|id| format!("Unknown({})", id));
@@ -200,37 +209,35 @@ unsafe extern "cdecl" fn fire_weapon_impl(weapon_ctx: u32, local_struct: u32, wo
200
  weapon_name, weapon_id, weapon_type, subtype_34, subtype_38
201
  ));
202
 
203
- // worm+0x3C = completion flag
204
- *(worm_ptr.add(0x3C) as *mut i32) = 0;
205
-
206
- use openwa_core::rebase::rb;
207
 
208
  match weapon_type {
209
  1 => match subtype_38 {
210
- 1 => call_fire_stdcall1(worm, params, rb(0x51EC80)), // PlacedExplosive
211
- 2 => call_fire_stdcall3(worm, params, local_struct, rb(0x51DFB0)), // Projectile
212
- 3 => call_fire_thiscall2(worm, params, local_struct, rb(0x51E0F0)), // CreateWeaponProjectile
213
- 4 => call_fire_stdcall2(worm, params, local_struct, rb(0x51ED90)), // Shotgun
214
  _ => {}
215
  },
216
  2 => match subtype_38 {
217
- 1 => call_fire_stdcall3(worm, params, local_struct, rb(0x51E1C0)), // RopeType1
218
- 2 => call_fire_thiscall2(worm, params, local_struct, rb(0x51E0F0)), // CreateWeaponProjectile
219
- 3 => call_fire_stdcall3(worm, params, local_struct, rb(0x51E240)), // RopeType3
220
  _ => {}
221
  },
222
  3 => {
223
- let params_34 = weapon_ctx.wrapping_add(0x34);
224
- call_fire_stdcall3(worm, params_34, local_struct, rb(0x51E2C0)); // GrenadeMortar
225
  }
226
  4 => {
227
- let params_38 = weapon_ctx.wrapping_add(0x38);
228
- fire_weapon_special(subtype_34, params_38, worm, local_struct);
229
  }
230
  _ => {}
231
  }
232
 
233
- *(worm_ptr.add(0x3C) as *mut i32) = 1;
234
  }
235
 
236
  // ── Sub-function bridges ────────────────────────────────────
 
11
 
12
  use openwa_core::address::va;
13
  use openwa_core::engine::ddgame::{self, TeamArenaRef};
14
+ use openwa_core::game::weapon::WeaponEntry;
15
  use openwa_core::game::Weapon;
16
  use openwa_core::log::log_line;
17
+ use openwa_core::task::worm::CTaskWorm;
18
 
19
  use crate::hook::{self, usercall_trampoline};
20
 
 
181
  }
182
 
183
  /// Rust implementation of FireWeapon dispatch.
184
+ ///
185
+ /// `entry`: EAX = active WeaponEntry pointer (from CTaskWorm+0x36C).
186
+ /// `local_struct`: ECX = stack-local buffer from WeaponRelease.
187
+ /// `worm`: stack param = CTaskWorm pointer (ESI in original).
188
+ ///
189
+ /// Completion flag at worm+0x3C (CGameTask.subclass_data[12]).
190
+ /// Params pointer at entry+0x3C (WeaponEntry.fire_complete) β€” different object, same offset.
191
+ unsafe extern "cdecl" fn fire_weapon_impl(
192
+ entry: *const WeaponEntry, local_struct: u32, worm: *mut CTaskWorm,
193
+ ) {
194
+ use openwa_core::rebase::rb;
195
 
196
+ let weapon_type = (*entry).fire_type;
197
+ let subtype_34 = (*entry).fire_subtype_34;
198
+ let subtype_38 = (*entry).fire_subtype_38;
199
+ let params = &raw const (*entry).fire_complete as u32;
200
+ let worm_u32 = worm as u32;
201
 
202
  // Log weapon fire
203
+ let weapon_id = (*worm).selected_weapon;
204
  let weapon_name = Weapon::try_from(weapon_id)
205
  .map(|w| format!("{:?}", w))
206
  .unwrap_or_else(|id| format!("Unknown({})", id));
 
209
  weapon_name, weapon_id, weapon_type, subtype_34, subtype_38
210
  ));
211
 
212
+ // Completion flag at CGameTask.subclass_data[12] (worm+0x3C), NOT WeaponEntry
213
+ *(worm as *mut u8).add(0x3C).cast::<i32>() = 0;
 
 
214
 
215
  match weapon_type {
216
  1 => match subtype_38 {
217
+ 1 => call_fire_stdcall1(worm_u32, params, rb(0x51EC80)), // PlacedExplosive
218
+ 2 => call_fire_stdcall3(worm_u32, params, local_struct, rb(0x51DFB0)), // Projectile
219
+ 3 => call_fire_thiscall2(worm_u32, params, local_struct, rb(0x51E0F0)), // CreateWeaponProjectile
220
+ 4 => call_fire_stdcall2(worm_u32, params, local_struct, rb(0x51ED90)), // Shotgun
221
  _ => {}
222
  },
223
  2 => match subtype_38 {
224
+ 1 => call_fire_stdcall3(worm_u32, params, local_struct, rb(0x51E1C0)), // RopeType1
225
+ 2 => call_fire_thiscall2(worm_u32, params, local_struct, rb(0x51E0F0)), // CreateWeaponProjectile
226
+ 3 => call_fire_stdcall3(worm_u32, params, local_struct, rb(0x51E240)), // RopeType3
227
  _ => {}
228
  },
229
  3 => {
230
+ let params_34 = &raw const (*entry).fire_subtype_34 as u32;
231
+ call_fire_stdcall3(worm_u32, params_34, local_struct, rb(0x51E2C0)); // GrenadeMortar
232
  }
233
  4 => {
234
+ let params_38 = &raw const (*entry).fire_subtype_38 as u32;
235
+ fire_weapon_special(subtype_34, params_38, worm_u32, local_struct);
236
  }
237
  _ => {}
238
  }
239
 
240
+ *(worm as *mut u8).add(0x3C).cast::<i32>() = 1;
241
  }
242
 
243
  // ── Sub-function bridges ────────────────────────────────────