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

feat: identify weapon_ctx as WeaponEntry pointer, add fire fields

Browse files

Runtime investigation confirmed CTaskWorm+0x36C points to the active
WeaponEntry in the WeaponTable (entry index matches selected_weapon).

Add newly discovered WeaponEntry fields:
- fire_type (+0x30): weapon dispatch type (1-4)
- fire_subtype_34 (+0x34): subtype for types 3/4
- fire_subtype_38 (+0x38): subtype for types 1/2
- fire_complete (+0x3C): completion flag / params base

Type CTaskWorm.active_weapon_entry as *mut WeaponEntry.
Remove incorrect CTaskWorm weapon accessors (they read from the worm's
subclass_data instead of the WeaponEntry).

Verified: headless PASS (byte-identical).

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

crates/openwa-core/src/game/weapon.rs CHANGED
@@ -126,8 +126,20 @@ pub struct WeaponEntry {
126
  pub availability: i32,
127
  /// +0x28: Enabled flag (init: 1).
128
  pub enabled: i32,
129
- /// +0x2C-0x1CF: Unknown fields.
130
- pub _unknown_2c: [u8; 0x1D0 - 0x2C],
 
 
 
 
 
 
 
 
 
 
 
 
131
  }
132
  const _: () = assert!(core::mem::size_of::<WeaponEntry>() == 0x1D0);
133
 
 
126
  pub availability: i32,
127
  /// +0x28: Enabled flag (init: 1).
128
  pub enabled: i32,
129
+ /// +0x2C-0x2F: Unknown.
130
+ pub _unknown_2c: [u8; 4],
131
+ /// +0x30: Weapon fire type (1=projectile, 2=rope, 3=grenade, 4=special).
132
+ /// Read by FireWeapon to dispatch to the correct handler.
133
+ pub fire_type: i32,
134
+ /// +0x34: Fire subtype for weapon types 3 (grenade/mortar) and 4 (special).
135
+ pub fire_subtype_34: i32,
136
+ /// +0x38: Fire subtype for weapon types 1 (projectile) and 2 (rope).
137
+ pub fire_subtype_38: i32,
138
+ /// +0x3C: Fire completion flag / params base.
139
+ /// Set to 0 before dispatch, 1 after. Address also passed to fire handlers.
140
+ pub fire_complete: i32,
141
+ /// +0x40-0x1CF: Unknown fields.
142
+ pub _unknown_40: [u8; 0x1D0 - 0x40],
143
  }
144
  const _: () = assert!(core::mem::size_of::<WeaponEntry>() == 0x1D0);
145
 
crates/openwa-core/src/task/worm.rs CHANGED
@@ -1,5 +1,6 @@
1
  use super::base::CTask;
2
  use super::game_task::CGameTask;
 
3
 
4
  /// Virtual method table for CTaskWorm (vtable at 0x6644C8, 20 slots).
5
  ///
@@ -151,11 +152,10 @@ pub struct CTaskWorm {
151
  pub _unknown_338: [u8; 0x368 - 0x338],
152
  /// 0x368: Animator / controller object (dispatched via vtable for state animations)
153
  pub animator: *mut u8,
154
- /// 0x36C: Weapon context pointer. Points to a separate object containing
155
- /// weapon fire state (type at +0x30, subtypes at +0x34/+0x38, params at +0x3C).
156
- /// NOT a self-pointer — weapon_ctx != worm (confirmed via runtime logging).
157
  /// Used by WeaponRelease: `MOV EAX, [EDI+0x36C]` before calling FireWeapon.
158
- pub weapon_ctx: *mut u8,
159
  /// 0x370–0x3DB: Unknown (rope anchor, weapon-specific data, etc.)
160
  pub _unknown_370: [u8; 0x3DC - 0x370],
161
  /// 0x3DC: Facing direction. -1 = facing left, +1 = facing right.
@@ -186,13 +186,9 @@ impl CTaskWorm {
186
  unsafe { *((self as *const CTaskWorm as *const u8).add(0x44) as *const u32) }
187
  }
188
 
189
- // Weapon fire state lives in the WEAPON CONTEXT object (at CTaskWorm+0x36C),
190
- // NOT in CTaskWorm itself. The weapon_ctx is a separate allocation with:
191
- // +0x30: weapon_fire_type (1=projectile, 2=rope, 3=grenade, 4=special)
192
- // +0x34: weapon_fire_subtype_34 (for types 3/4)
193
- // +0x38: weapon_fire_subtype_38 (for types 1/2)
194
- // +0x3C: weapon_fire_complete (0 before, 1 after dispatch)
195
- // Accessed via raw pointers in the FireWeapon hook (weapon.rs).
196
 
197
  /// Returns a reference to the vtable.
198
  ///
 
1
  use super::base::CTask;
2
  use super::game_task::CGameTask;
3
+ use crate::game::weapon::WeaponEntry;
4
 
5
  /// Virtual method table for CTaskWorm (vtable at 0x6644C8, 20 slots).
6
  ///
 
152
  pub _unknown_338: [u8; 0x368 - 0x338],
153
  /// 0x368: Animator / controller object (dispatched via vtable for state animations)
154
  pub animator: *mut u8,
155
+ /// 0x36C: Active weapon entry pointer. Points to `&WeaponTable.entries[selected_weapon]`.
156
+ /// Contains fire type (+0x30), subtypes (+0x34/+0x38), and completion flag (+0x3C).
 
157
  /// Used by WeaponRelease: `MOV EAX, [EDI+0x36C]` before calling FireWeapon.
158
+ pub active_weapon_entry: *mut WeaponEntry,
159
  /// 0x370–0x3DB: Unknown (rope anchor, weapon-specific data, etc.)
160
  pub _unknown_370: [u8; 0x3DC - 0x370],
161
  /// 0x3DC: Facing direction. -1 = facing left, +1 = facing right.
 
186
  unsafe { *((self as *const CTaskWorm as *const u8).add(0x44) as *const u32) }
187
  }
188
 
189
+ // Weapon fire state lives in the WeaponEntry pointed to by active_weapon_entry
190
+ // (+0x36C), NOT in CTaskWorm itself. See WeaponEntry fields: fire_type (+0x30),
191
+ // fire_subtype_34 (+0x34), fire_subtype_38 (+0x38), fire_complete (+0x3C).
 
 
 
 
192
 
193
  /// Returns a reference to the vtable.
194
  ///
crates/openwa-wormkit/src/replacements/weapon.rs CHANGED
@@ -187,6 +187,9 @@ unsafe extern "cdecl" fn fire_weapon_impl(weapon_ctx: u32, local_struct: u32, wo
187
  let params = weapon_ctx.wrapping_add(0x3C);
188
  let worm_ptr = worm as *mut u8;
189
 
 
 
 
190
  // Log weapon fire
191
  let weapon_id = *(worm_ptr.add(0x170) as *const u32);
192
  let weapon_name = Weapon::try_from(weapon_id)
 
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)