Files
WeirdUtils/src/offsets.zig
T
MarcelineVQ 56f5c0405d dpslog: WotLK CLEU parity — overkill, overheal, spell names, unit names, GetSpellInfo
Full WotLK 3.3.5 COMBAT_LOG_EVENT_UNFILTERED layout parity:

Event structure:
- Base: subevent, sourceGUID, sourceName, destGUID, destName
- Spell prefix: spellId, spellName, spellSchool
- All suffix field orders match WotLK (blocked before absorbed, etc.)

New fields:
- overkill (-1 if alive) on all _DAMAGE events
- overheal on SPELL_HEAL and SPELL_PERIODIC_HEAL
- sourceName/destName via getNameByGUID (name cache 0x55F080)
- spellName via SpellRec+0x1E0+locale*4 (verified from SuperWoW)
- glancing/crushing as separate booleans (was packed flags)
- amountMissed field (0 — downstream hook lacks amount)

New hooks:
- ProcessStandardPowerGainMessage (0x62CA00) for SPELL_ENERGIZE with
  actual amount and powerType from SMSG_SPELLENERGIZELOG (opcode 0x151)
- Periodic energize: divide by power display factor (rage/10, happiness/1000)

Leech/drain reclassification:
- Drain Life routed through SPELL_PERIODIC_LEECH (aura 53 check in spell DB)
- SPELL_HEAL suppressed for leech spells (covered by leech event)
- Power leech (aura 64): gainMultiplier read as f32, >0 = LEECH, ==0 = DRAIN
- _LEECH/_DRAIN suffix: amount, powerType(-2=health), extraAmount

Lua API:
- GetSpellInfo(spellId) -> name, rank, icon, castTime, minRange, maxRange, spellId
  Matches WotLK returns. DBC addresses verified from nampower + Ghidra:
  SpellRange.dbc (0xC0D79C), SpellIcon.dbc (0xC0D7EC),
  SpellCastTimes.dbc (0xC0D878). SpellRec offsets from nampower struct.

Reference docs:
- WOTLK_CLEU_SPEC.md: full suffix spec from Blizzard_CombatLog.lua + Skada
- WARDEN_CONCERNS.md: hook risk analysis and remaining parity gaps
2026-03-18 00:08:42 -07:00

180 lines
6.6 KiB
Zig

//! Shared WoW 1.12.1 (build 5875) memory addresses and struct offsets.
//!
//! Contains only addresses/offsets duplicated across 2+ modules.
//! Module-specific offsets remain in their own files.
// =============================================================================
// Object Manager
// =============================================================================
/// Pointer to the Object Manager base. Dereference once to get the ObjMgr struct.
pub const OBJECT_MANAGER_PTR: usize = 0x00B41414;
/// ObjMgr + this → first object in the linked list.
pub const OBJECT_LIST_OFFSET: usize = 0xAC;
/// ObjMgr + this → base pointer for the next-object traversal table.
pub const OBJECT_NEXT_OFFSET: usize = 0xA4;
/// ObjMgr + this → local player GUID (8 bytes).
pub const LOCAL_PLAYER_GUID_OFFSET: usize = 0xC0;
// =============================================================================
// Object fields (from object base pointer)
// =============================================================================
pub const OBJECT_TYPE_OFFSET: usize = 0x14;
pub const OBJECT_GUID_OFFSET: usize = 0x30;
/// object + this → pointer to descriptor block (m_data).
pub const UNIT_DESCRIPTOR_OFFSET: usize = 0x110;
/// Alternate descriptor offset used by items/corpses (at +0x08).
pub const OBJECT_DATA_OFFSET: usize = 0x08;
// =============================================================================
// Descriptor field indices (byte offset = index * 4 from descriptor base)
// =============================================================================
/// OBJECT_FIELD_ENTRY (index 0x03)
pub const DESC_ENTRY: usize = 0x03 * 4;
/// UNIT_NPC_FLAGS = OBJECT_END(0x06) + 0x8D = 0x93
pub const DESC_NPC_FLAGS: usize = 0x93 * 4;
/// UNIT_DYNAMIC_FLAGS = OBJECT_END(0x06) + 0x90 = 0x96
pub const DESC_UNIT_DYNAMIC_FLAGS: usize = 0x96 * 4;
/// Bit 0: unit corpse is lootable by the local player.
pub const UNIT_DYNFLAG_LOOTABLE: u32 = 0x01;
/// GAMEOBJECT_TYPE_ID (index 0x15)
pub const DESC_GO_TYPE: usize = 0x15 * 4;
/// UNIT_FIELD_SUMMONEDBY (index 0x0C, GUID = 8 bytes)
pub const DESC_SUMMONEDBY: usize = 0x0C * 4;
/// UNIT_FIELD_BYTES_0: race|class|gender|power (index 0x24)
pub const DESC_BYTES_0: usize = 0x24 * 4;
/// GAMEOBJECT_FLAGS (index 0x09)
pub const DESC_GO_FLAGS: usize = 0x09 * 4;
/// GAMEOBJECT_DYN_FLAGS (index 0x13)
pub const DESC_GO_DYN_FLAGS: usize = 0x13 * 4;
// =============================================================================
// Unit descriptor fields (byte offsets from descriptor base)
// =============================================================================
/// Descriptor + this → unit flags (uint32). Test with UNIT_FLAG_DEAD.
pub const UNIT_FLAGS_OFFSET: usize = 0x224;
/// Bit mask: unit is dead.
pub const UNIT_FLAG_DEAD: u32 = 0x20;
/// Descriptor + this → current HP (int32).
pub const UNIT_HP_OFFSET: usize = 0x40;
// =============================================================================
// Corpse descriptor fields
// =============================================================================
/// Corpse descriptor + this → owner GUID (8 bytes).
pub const CORPSE_FIELD_OWNER: usize = 0x18;
/// Corpse descriptor + this → corpse flags (uint32).
pub const CORPSE_FIELD_FLAGS: usize = 0x8C;
/// Bit mask: corpse is a skeleton (not resurrectable).
pub const CORPSE_FLAG_BONE: u32 = 0x01;
// =============================================================================
// Unit position (movement struct)
// =============================================================================
/// Unit + this → movement struct pointer
pub const UNIT_MOVEMENT_OFFSET: usize = 0x118;
/// Movement struct position offsets
pub const MOVEMENT_POS_X: usize = 0x10;
pub const MOVEMENT_POS_Y: usize = 0x14;
pub const MOVEMENT_POS_Z: usize = 0x18;
// =============================================================================
// Map / Zone identification
// =============================================================================
/// Current zone area ID — numeric, locale-safe zone identifier.
pub const ZONE_AREA_ID: usize = 0x00B4E314;
/// ObjMgr + this → current map ID (u32).
pub const OBJMGR_MAP_ID_OFFSET: usize = 0xCC;
/// Pointer to Map.dbc indexed lookup table.
pub const MAP_DBC_DATA: usize = 0x00C0DAA8;
/// Pointer to Map.dbc max valid index.
pub const MAP_DBC_MAX: usize = 0x00C0DAAC;
/// Map.dbc row + this → mapType (u32). 0=world, 1=instance, 2=raid, 3=battleground.
pub const MAP_DBC_MAP_TYPE_OFFSET: usize = 0x08;
/// MapType value for battleground instances.
pub const MAP_TYPE_BATTLEGROUND: u32 = 3;
// =============================================================================
// Game state
// =============================================================================
/// Non-zero when the player is logged in and in the world.
pub const IS_IN_WORLD: usize = 0xB4B424;
// =============================================================================
// Raid targets
// =============================================================================
/// Static array of 8 GUIDs (64 bytes total). Index 0 = Star, 7 = Skull.
pub const RAID_TARGET_ARRAY: usize = 0x00B71368;
// =============================================================================
// Core function addresses
// =============================================================================
/// __stdcall(guidLo, guidHi) → object pointer. RET 8.
pub const FN_GET_OBJECT_BY_GUID: usize = 0x464870;
/// __fastcall(unitIdStr_ECX) → GUID in EAX:EDX.
pub const FN_UNIT_GUID: usize = 0x515970;
/// __thiscall(localPlayer_ECX, targetUnit_stack) → reaction int. >=4 = friendly.
pub const FN_UNIT_REACTION: usize = 0x6061E0;
/// __fastcall(), no params, returns EAX(low):EDX(high).
pub const FN_GET_PLAYER_GUID: usize = 0x00468550;
/// __fastcall(obj_ECX) → bool. GO interactability check.
pub const FN_CALL_SPELL_CAST_HANDLER: usize = 0x5F8800;
/// CVar lookup: __fastcall(name_ECX) → CVar* or 0.
pub const FN_CVAR_LOOKUP: usize = 0x0063DEC0;
/// SceneEnd: __thiscall(device). Per-frame hook point.
pub const FN_SCENE_END: usize = 0x5A17A0;
/// RetrieveNPCDataFromCache — __thiscall(ECX=cache_obj), 6 stack params, RET 0x18.
/// Returns char* name or 0 on miss.
pub const FN_NAME_CACHE_LOOKUP: usize = 0x0055F080;
/// Name cache object pointer (global at 0xC0E228).
pub const NAME_CACHE_OBJ: usize = 0x00C0E228;
// =============================================================================
// D3D9 / GxDevice
// =============================================================================
/// Game's GxDevice global pointer.
pub const GX_DEVICE_PTR: usize = 0xC0ED38;
/// GxDevice + this → IDirect3DDevice9*.
pub const GX_DEVICE_D3D_OFFSET: usize = 0x38A8;