paavohtl Claude Opus 4.6 (1M context) commited on
Commit
0c8bf83
·
1 Parent(s): 8a9e72a

refactor: embed TeamArenaState as proper DDGame field

Browse files

Replace the opaque _unknown_4620 blob with a proper team_arena field
at DDGame+0x4628. The previously separate init_field_64d8 and
init_field_72a4 were actually team_arena.team_count and
team_arena.weapon_slots[754] respectively — now accessed correctly.

fire_skip_go uses ddgame.team_arena._teams_region directly instead
of raw pointer arithmetic through offsets::TEAM_ARENA_STATE.

Verified: headless PASS (byte-identical).

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

crates/openwa-core/src/engine/ddgame.rs CHANGED
@@ -175,19 +175,14 @@ pub struct DDGame {
175
  /// Initialized to 0x10000 (1.0). Not read by the render method — may be
176
  /// target/previous value for interpolation, or used by update logic.
177
  pub team_health_ratio_2: [i32; 6],
178
- /// 0x4620-0x64D7: Unknown
179
- ///
180
- /// Known landmarks:
181
- /// - 0x64D8: cleared by init
182
- pub _unknown_4620: [u8; 0x64D8 - 0x4620],
183
- /// 0x64D8: Cleared by InitFields. Purpose unknown.
184
- pub init_field_64d8: u32,
185
- /// 0x64DC-0x72A3: Unknown
186
- pub _unknown_64dc: [u8; 0x72A4 - 0x64DC],
187
- /// 0x72A4: Cleared by InitFields. Purpose unknown.
188
- pub init_field_72a4: u32,
189
- /// 0x72A8-0x72D7: Unknown
190
- pub _unknown_72a8: [u8; 0x72D8 - 0x72A8],
191
 
192
  /// 0x72D8: Game speed multiplier (Fixed-point, 0x10000 = 1.0x).
193
  pub game_speed: i32,
@@ -415,8 +410,10 @@ pub unsafe fn ddgame_init_fields(ddgame: *mut DDGame) {
415
  *(base.add(off) as *mut u32) = 0;
416
  }
417
 
418
- (*ddgame).init_field_64d8 = 0;
419
- (*ddgame).init_field_72a4 = 0;
 
 
420
 
421
  // InitRenderIndices — original sets ESI = ddgame + 0x72D8, now uses typed DDGame ptr
422
  ddgame_init_render_indices(ddgame);
 
175
  /// Initialized to 0x10000 (1.0). Not read by the render method — may be
176
  /// target/previous value for interpolation, or used by update logic.
177
  pub team_health_ratio_2: [i32; 6],
178
+ /// 0x4620-0x4627: Unknown
179
+ pub _unknown_4620: [u8; 0x4628 - 0x4620],
180
+ /// 0x4628: Team arena state — per-team data, ammo, delays, alliance tracking.
181
+ /// Note: fields previously named init_field_64d8 (= team_count at arena+0x1EB0)
182
+ /// and init_field_72a4 (= weapon_slots entry at arena+0x2A7C) are inside this struct.
183
+ pub team_arena: TeamArenaState,
184
+ /// 0x7270-0x72D7: Unknown
185
+ pub _unknown_7270: [u8; 0x72D8 - 0x7270],
 
 
 
 
 
186
 
187
  /// 0x72D8: Game speed multiplier (Fixed-point, 0x10000 = 1.0x).
188
  pub game_speed: i32,
 
410
  *(base.add(off) as *mut u32) = 0;
411
  }
412
 
413
+ // init_field_64d8 = TeamArenaState.team_count (arena+0x1EB0)
414
+ (*ddgame).team_arena.team_count = 0;
415
+ // init_field_72a4 = weapon_slots[754] (arena+0x2A7C)
416
+ (*ddgame).team_arena.weapon_slots[754] = 0;
417
 
418
  // InitRenderIndices — original sets ESI = ddgame + 0x72D8, now uses typed DDGame ptr
419
  ddgame_init_render_indices(ddgame);
crates/openwa-wormkit/src/replacements/weapon.rs CHANGED
@@ -395,29 +395,29 @@ unsafe fn fire_weapon_special(
395
 
396
  /// Skip Go (subtype 19) — pure Rust replacement for 0x51E8C0.
397
  ///
398
- /// Toggles a bit in the team's arena state flags (DDGame+0x4628 + team*0x51C).
399
- /// Bit position from weapon entry's fire_params field.
400
  /// If game_version > 0x1C and bit already set: clears it. Otherwise: sets it.
401
  unsafe fn fire_skip_go(worm: *const CTaskWorm, entry: *const WeaponEntry) {
402
  use openwa_core::engine::DDGame;
403
- use openwa_core::engine::GameInfo;
404
 
405
- let ddgame = (*worm).base.base.ddgame as *const DDGame;
406
- let game_info = (*ddgame).game_info as *const GameInfo;
407
- let game_version = (*game_info).game_version;
408
  let team_index = (*worm).team_index as usize;
409
 
410
  let bit_index = (*entry).fire_params._data[0] & 0x1F;
411
  let bit = 1u32 << bit_index;
412
 
413
- // Team arena flags at DDGame+0x4628 + team_index * 0x51C
414
- let flags_ptr = (ddgame as *mut u8).add(0x4628 + team_index * 0x51C) as *mut u32;
 
 
415
  let flags = *flags_ptr;
416
 
417
  if game_version > 0x1C && (flags & bit) != 0 {
418
- *flags_ptr = flags & !bit; // clear
419
  } else {
420
- *flags_ptr = flags | bit; // set
421
  }
422
  }
423
 
 
395
 
396
  /// Skip Go (subtype 19) — pure Rust replacement for 0x51E8C0.
397
  ///
398
+ /// Toggles a bit in the team's arena state flags (first DWORD of each team's
399
+ /// region in TeamArenaState). Bit position from weapon entry's fire_params.
400
  /// If game_version > 0x1C and bit already set: clears it. Otherwise: sets it.
401
  unsafe fn fire_skip_go(worm: *const CTaskWorm, entry: *const WeaponEntry) {
402
  use openwa_core::engine::DDGame;
 
403
 
404
+ let ddgame = &mut *((*worm).base.base.ddgame as *mut DDGame);
405
+ let game_version = (*ddgame.game_info).game_version;
 
406
  let team_index = (*worm).team_index as usize;
407
 
408
  let bit_index = (*entry).fire_params._data[0] & 0x1F;
409
  let bit = 1u32 << bit_index;
410
 
411
+ // First DWORD of each team's region in TeamArenaState (stride 0x51C)
412
+ let flags_ptr = ddgame.team_arena._teams_region
413
+ [team_index * 0x51C..][..4]
414
+ .as_ptr() as *mut u32;
415
  let flags = *flags_ptr;
416
 
417
  if game_version > 0x1C && (flags & bit) != 0 {
418
+ *flags_ptr = flags & !bit;
419
  } else {
420
+ *flags_ptr = flags | bit;
421
  }
422
  }
423