refactor: embed TeamArenaState as proper DDGame field
Browse filesReplace 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-
|
| 179 |
-
|
| 180 |
-
///
|
| 181 |
-
///
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 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 |
-
|
| 419 |
-
(*ddgame).
|
|
|
|
|
|
|
| 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 (
|
| 399 |
-
/// 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 |
-
use openwa_core::engine::GameInfo;
|
| 404 |
|
| 405 |
-
let ddgame = (*worm).base.base.ddgame as *
|
| 406 |
-
let
|
| 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 |
-
//
|
| 414 |
-
let flags_ptr =
|
|
|
|
|
|
|
| 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 |
|
|
|
|
| 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 |
|