From e0da2791d9d82797d522109714010a472601ea4d Mon Sep 17 00:00:00 2001 From: MarcelineVQ Date: Thu, 12 Mar 2026 10:35:44 -0700 Subject: [PATCH] Fix dpslog dynamic slot search and environmental damage params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resize hook now expands event array to 801 slots. Dynamic slot search scans from slot 650 for first empty entry (compatible with SuperWoW). Fixed ProcessEnvironmentalDamage parameter order — Ghidra mislabeled damageSource as damage. Lua chat output now fires only on first subevent. --- src/dpslog/WeirdUtils_DPSLog/DPSLog.lua | 15 +++++----- src/dpslog/dpslog.zig | 37 +++++++++++++++++-------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/dpslog/WeirdUtils_DPSLog/DPSLog.lua b/src/dpslog/WeirdUtils_DPSLog/DPSLog.lua index 8645fee..f0d6302 100644 --- a/src/dpslog/WeirdUtils_DPSLog/DPSLog.lua +++ b/src/dpslog/WeirdUtils_DPSLog/DPSLog.lua @@ -484,17 +484,16 @@ eventFrame:SetScript("OnEvent", function() local subevent = arg1 if not subevent then return end - -- Chat output - local chatHandler = chatHandlers[subevent] - if chatHandler then - chatHandler(arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) - else - DEFAULT_CHAT_FRAME:AddMessage(format("|cffccccccUNHANDLED|r %s", subevent)) - end - -- Tracker update (first encounter only) local idx = subeventIndex[subevent] if idx and not seen[idx] then + -- Chat output (first occurrence only) + local chatHandler = chatHandlers[subevent] + if chatHandler then + chatHandler(arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) + else + DEFAULT_CHAT_FRAME:AddMessage(format("|cffccccccUNHANDLED|r %s", subevent)) + end seen[idx] = true seenCount = seenCount + 1 local formatter = argFormatters[subevent] diff --git a/src/dpslog/dpslog.zig b/src/dpslog/dpslog.zig index 84a793d..2a79398 100644 --- a/src/dpslog/dpslog.zig +++ b/src/dpslog/dpslog.zig @@ -365,15 +365,16 @@ const DupString = fn ([*:0]const u8, [*:0]const u8, u32) callconv(hook.cc.stdcal const DUP_STRING: u32 = 0x64a620; const DUP_STRING_SRC: [*:0]const u8 = "dpslog"; -const OUR_EVENT_SLOT: u32 = 650; -const MIN_EVENT_CAPACITY: u32 = 700; +const PREFERRED_EVENT_SLOT: u32 = 650; +const MAX_EVENT_SLOT: u32 = 800; +const MIN_EVENT_CAPACITY: u32 = MAX_EVENT_SLOT + 1; const INTERNAL_ARRAY_PTR: u32 = 0x00ceef68; const INTERNAL_CAPACITY_PTR: u32 = 0x00ceef64; // ============================================================================= // Hook: resize_lua_event_array (0x7053B0) // __thiscall(ECX=&struct_ceef60, stack=new_count) -// Mirrors SuperWoW's check: if count > 200 (not GlueXML), expand to at least 700. +// If count > 200 (not GlueXML), expand to at least MIN_EVENT_CAPACITY. // ============================================================================= const EVENT_STRUCT: u32 = 0x00ceef60; @@ -396,8 +397,20 @@ fn createEventsDetour(param1: u32, max_event_id: u32) callconv(hook.cc.fastcall) const capacity = hook.readMem(u32, INTERNAL_CAPACITY_PTR); const internal_array = hook.readMem(u32, INTERNAL_ARRAY_PTR); - if (internal_array == 0 or capacity <= OUR_EVENT_SLOT) { - log.fmt("createEventsDetour: capacity {d} too small for slot {d}\n", .{ capacity, OUR_EVENT_SLOT }); + if (internal_array == 0 or capacity <= PREFERRED_EVENT_SLOT) { + log.fmt("createEventsDetour: capacity {d} too small\n", .{capacity}); + return; + } + + // Find an empty slot (name_ptr == 0), starting at preferred slot. + const limit = @min(capacity, MAX_EVENT_SLOT + 1); + var slot: u32 = PREFERRED_EVENT_SLOT; + while (slot < limit) : (slot += 1) { + const name_at_slot = hook.readMem(u32, internal_array + slot * 16); + if (name_at_slot == 0) break; + } + if (slot >= limit) { + log.fmt("createEventsDetour: no empty slot in {d}-{d}\n", .{ PREFERRED_EVENT_SLOT, limit - 1 }); return; } @@ -405,10 +418,10 @@ fn createEventsDetour(param1: u32, max_event_id: u32) callconv(hook.cc.fastcall) const name_ptr = @call(.auto, @as(*const DupString, @ptrFromInt(DUP_STRING)), .{ event_name, DUP_STRING_SRC, 0x51c }); // Write into internal table entry: each entry is 16 bytes, name at +0. - hook.writeMem(internal_array + OUR_EVENT_SLOT * 16, std.mem.asBytes(&name_ptr)); - g_event_combat_log = OUR_EVENT_SLOT; + hook.writeMem(internal_array + slot * 16, std.mem.asBytes(&name_ptr)); + g_event_combat_log = slot; - log.fmt("createEventsDetour: COMBAT_LOG_EVENT at slot {d}, capacity={d}\n", .{ OUR_EVENT_SLOT, capacity }); + log.fmt("createEventsDetour: COMBAT_LOG_EVENT at slot {d}, capacity={d}\n", .{ slot, capacity }); } } @@ -684,7 +697,7 @@ const EnvDmgFn = fn (u32, u32, u32, u32, u32) callconv(hook.cc.fastcall) void; var env_dmg_hook: hook.Detour(EnvDmgFn) = .{}; -fn envDamageDetour(victim_guid_ptr: u32, damage_type: u32, damage_source: u32, base_damage: u32, absorb: u32) callconv(hook.cc.fastcall) void { +fn envDamageDetour(victim_guid_ptr: u32, damage_type: u32, damage: u32, absorb: u32, resist: u32) callconv(hook.cc.fastcall) void { asm volatile ("" ::: .{ .esi = true, .edi = true, .ebx = true }); if (victim_guid_ptr != 0) { @@ -701,13 +714,13 @@ fn envDamageDetour(victim_guid_ptr: u32, damage_type: u32, damage_source: u32, b 3, 5 => 4, // lava, fire → fire else => 1, // exhausted, falling → physical }; - log.fmt("ENVIRONMENTAL_DAMAGE: type={s} dmg={d} absorb={d}\n", .{ std.mem.span(env_str), base_damage, absorb }); - fireEnvDamage(dst_str, env_str, base_damage, school, absorb); + log.fmt("ENVIRONMENTAL_DAMAGE: type={s} dmg={d} absorb={d}\n", .{ std.mem.span(env_str), damage, absorb }); + fireEnvDamage(dst_str, env_str, damage, school, absorb); recordDamage(victim_guid, 0, 0); } } - env_dmg_hook.callOriginal(.{ victim_guid_ptr, damage_type, damage_source, base_damage, absorb }); + env_dmg_hook.callOriginal(.{ victim_guid_ptr, damage_type, damage, absorb, resist }); } // =============================================================================