Add logging module with auto-prefix, route all output through Logger
Replace console.zig with logging.zig: per-module Logger with auto [name] prefix, optional file output, and destination routing. Convert all modules from manual [name] prefixes and global con.print to Logger instances. Remove redundant "Module loaded" lines. Replace OutputDebugStringA in outline/tracker with Logger. Add dpslog module with structured combat log events (SPELL_DMG, PERIODIC, HEAL, MELEE). Add clickthrough module and bigcursor D3D9 cursor scaling.
This commit is contained in:
@@ -22,6 +22,14 @@ pub const module_name: [*:0]const u8 = "clickthrough";
|
||||
const ADDR_WorldIntersectionTest: usize = 0x480DF0;
|
||||
const ADDR_GetObjectByGUID: usize = 0x464870;
|
||||
|
||||
// Map identification (Map.dbc lookup)
|
||||
const OBJECT_MANAGER_PTR: usize = 0x00B41414;
|
||||
const OBJMGR_MAP_ID_OFFSET: usize = 0xCC;
|
||||
const MAP_DBC_DATA: usize = 0x00C0DAA8;
|
||||
const MAP_DBC_MAX: usize = 0x00C0DAAC;
|
||||
const MAP_DBC_MAP_TYPE_OFFSET: usize = 0x08;
|
||||
const MAP_TYPE_BATTLEGROUND: u32 = 3;
|
||||
|
||||
// =============================================================================
|
||||
// HitTestResult layout
|
||||
// =============================================================================
|
||||
@@ -34,6 +42,8 @@ const HIT_RESULT_SIZE: usize = 0x34;
|
||||
const OBJ_DESCRIPTOR: usize = 0x08;
|
||||
const OBJ_TYPE_MASK_OFFSET: usize = 0x08; // at *(*(obj+8)+8)
|
||||
|
||||
// Object type + descriptor field offsets
|
||||
|
||||
// Type masks
|
||||
const TYPE_UNIT: u32 = 0x09;
|
||||
const TYPE_PLAYER: u32 = 0x19;
|
||||
@@ -49,14 +59,34 @@ const OBJ_TYPE: usize = 0x14;
|
||||
const OBJ_TYPE_UNIT: u32 = 3;
|
||||
const OBJ_TYPE_GO: u32 = 5;
|
||||
const DESC_NPC_FLAGS: usize = 0x93 * 4; // UNIT_NPC_FLAGS = OBJECT_END(0x06) + 0x8D = 0x93
|
||||
const DESC_ENTRY: usize = 0x03 * 4; // OBJECT_FIELD_ENTRY
|
||||
const ADDR_CallSpellCastHandler: usize = 0x5F8800;
|
||||
|
||||
// =============================================================================
|
||||
// Battleground detection
|
||||
// =============================================================================
|
||||
|
||||
/// Check if the current map is a battleground by reading Map.dbc mapType.
|
||||
fn isInBattleground() bool {
|
||||
const obj_mgr = hook.readMem(u32, OBJECT_MANAGER_PTR);
|
||||
if (obj_mgr == 0) return false;
|
||||
const map_id = hook.readMem(u32, obj_mgr + OBJMGR_MAP_ID_OFFSET);
|
||||
const dbc_max = hook.readMem(u32, MAP_DBC_MAX);
|
||||
if (map_id > dbc_max) return false;
|
||||
const table_base = hook.readMem(u32, MAP_DBC_DATA);
|
||||
if (table_base == 0) return false;
|
||||
const row = hook.readMem(u32, table_base + map_id * 4);
|
||||
if (row == 0) return false;
|
||||
const map_type = hook.readMem(u32, row + MAP_DBC_MAP_TYPE_OFFSET);
|
||||
return map_type == MAP_TYPE_BATTLEGROUND;
|
||||
}
|
||||
|
||||
fn getObjectByGUID(guid_lo: u32, guid_hi: u32) u32 {
|
||||
if (guid_lo == 0 and guid_hi == 0) return 0;
|
||||
return hook.call(fn (u32, u32) callconv(hook.cc.stdcall) u32, ADDR_GetObjectByGUID, .{ guid_lo, guid_hi });
|
||||
}
|
||||
|
||||
/// Check if the GUID refers to an interactable GO (mailbox, soulwell, etc.)
|
||||
/// Check if the GUID refers to an interactable GO.
|
||||
fn isInteractableGO(guid_lo: u32, guid_hi: u32) bool {
|
||||
const obj = getObjectByGUID(guid_lo, guid_hi);
|
||||
if (obj == 0) return false;
|
||||
@@ -109,7 +139,8 @@ fn worldIntersectDetour(world_frame: u32, ray_start: u32, ray_end: u32, flags: u
|
||||
// Call original with caller's flags
|
||||
const hit_type = wit_hook.callOriginal(.{ world_frame, ray_start, ray_end, flags, hit_result });
|
||||
|
||||
if (!g_is_hook_owner or hit_result == 0 or hit_type != 2) return hit_type;
|
||||
// No click-through in battlegrounds
|
||||
if (!g_is_hook_owner or hit_result == 0 or hit_type != 2 or isInBattleground()) return hit_type;
|
||||
|
||||
// hitType 2 = object hit. Check if it's a unit/player.
|
||||
const buf_lo = hook.readMem(u32, hit_result + HIT_GUID_LO);
|
||||
@@ -161,7 +192,6 @@ pub fn isActive() bool {
|
||||
}
|
||||
|
||||
pub fn installHooks() void {
|
||||
logging.print("[clickthrough] Module loaded\n");
|
||||
|
||||
const result = mod_mutex.acquire(module_name);
|
||||
g_mutex = result.handle;
|
||||
@@ -171,7 +201,7 @@ pub fn installHooks() void {
|
||||
log = logging.Logger.open(module_name, .both);
|
||||
_ = wit_hook.attach(ADDR_WorldIntersectionTest, &worldIntersectDetour);
|
||||
|
||||
log.fmt("[clickthrough] WorldIntersectionTest hooked at 0x{x}\n", .{ADDR_WorldIntersectionTest});
|
||||
log.fmt("WorldIntersectionTest hooked at 0x{x}\n", .{ADDR_WorldIntersectionTest});
|
||||
}
|
||||
|
||||
pub fn removeHooks() void {
|
||||
|
||||
Reference in New Issue
Block a user