mirror of
https://github.com/brues-code/nampower.git
synced 2026-10-05 21:20:01 +00:00
177 lines
6.5 KiB
C++
177 lines
6.5 KiB
C++
//
|
|
// Created by pmacc on 12/7/2025.
|
|
//
|
|
|
|
#include "auras.hpp"
|
|
#include "offsets.hpp"
|
|
#include "logging.hpp"
|
|
#include "game.hpp"
|
|
|
|
namespace Nampower {
|
|
uint32_t gAuraExpirationTime[MAX_AURA_SLOTS] = {};
|
|
|
|
// Helper function to trigger buff/debuff events
|
|
void TriggerAuraEvent(uintptr_t *unit, uint32_t slot, uint32_t spellId, bool wasAdded) {
|
|
// Determine if the unit is the active player (self) or another unit (other)
|
|
auto unitGuid = game::UnitGetGuid(unit);
|
|
auto playerGuid = game::ClntObjMgrGetActivePlayerGuid();
|
|
bool isSelf = (unitGuid == playerGuid);
|
|
bool isBuff = slot < 32; // slots 0-31 are buffs
|
|
|
|
// Trigger the appropriate event based on buff/debuff, add/remove, and self/other
|
|
game::Events eventToTrigger;
|
|
|
|
int luaUnitSlot = slot + 1; // lua uses 1-based indexing for slots. This is the slot for UnitBuff/UnitDebuff
|
|
|
|
auto *unitFields = *reinterpret_cast<game::UnitFields **>(unit + 68);
|
|
|
|
auto auras = unitFields->aura;
|
|
auto auraLevels = unitFields->auraLevels;
|
|
auto auraStacks = unitFields->auraApplications;
|
|
|
|
auto luaStacks = auraStacks[slot];
|
|
|
|
if (isBuff) {
|
|
// count empty buff slots before slot to adjust luaSlot for actual buff/debuff index
|
|
int emptyCount = 0;
|
|
for (uint32_t i = 0; i < slot; ++i) {
|
|
if (auras[i] == 0) {
|
|
emptyCount++;
|
|
}
|
|
}
|
|
luaUnitSlot = luaUnitSlot - emptyCount;
|
|
|
|
if (wasAdded) {
|
|
luaStacks += 1; // count offset by 1
|
|
|
|
// Buff added
|
|
eventToTrigger = isSelf ? game::BUFF_ADDED_SELF : game::BUFF_ADDED_OTHER;
|
|
} else {
|
|
// Buff removed
|
|
eventToTrigger = isSelf ? game::BUFF_REMOVED_SELF : game::BUFF_REMOVED_OTHER;
|
|
}
|
|
} else {
|
|
luaUnitSlot = luaUnitSlot - 32; // adjust slot for debuffs
|
|
|
|
// count empty debuff slots before slot to adjust luaSlot for actual buff/debuff index
|
|
int emptyCount = 0;
|
|
for (uint32_t i = 32; i < slot; ++i) {
|
|
if (auras[i] == 0) {
|
|
emptyCount++;
|
|
}
|
|
}
|
|
luaUnitSlot = luaUnitSlot - emptyCount;
|
|
|
|
if (wasAdded) {
|
|
luaStacks += 1; // count offset by 1
|
|
|
|
// Debuff added
|
|
eventToTrigger = isSelf ? game::DEBUFF_ADDED_SELF : game::DEBUFF_ADDED_OTHER;
|
|
} else {
|
|
// Debuff removed
|
|
eventToTrigger = isSelf ? game::DEBUFF_REMOVED_SELF : game::DEBUFF_REMOVED_OTHER;
|
|
}
|
|
}
|
|
|
|
static char format[] = "%s%d%d%d%d%d";
|
|
char *guidStr = new char[21]; // 2 for 0x prefix, 18 for the number, and 1 for '\0'
|
|
if (isSelf) {
|
|
std::snprintf(guidStr, 21, "0x%016llX", static_cast<unsigned long long>(playerGuid));
|
|
} else {
|
|
std::snprintf(guidStr, 21, "0x%016llX", static_cast<unsigned long long>(unitGuid));
|
|
}
|
|
|
|
// Trigger the event with spellId as parameter
|
|
((int (__cdecl *)(int, char *, char *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)) Offsets::SignalEventParam)(
|
|
eventToTrigger,
|
|
format,
|
|
guidStr,
|
|
luaUnitSlot,
|
|
spellId,
|
|
luaStacks,
|
|
auraLevels[slot],
|
|
slot);
|
|
|
|
delete[] guidStr;
|
|
}
|
|
|
|
void CGUnit_C_OnAuraRemovedHook(hadesmem::PatchDetourBase *detour, uintptr_t *unit, void *dummy_edx, uint32_t slot,
|
|
uint32_t spellId) {
|
|
auto const onAuraRemoved = detour->GetTrampolineT<CGUnit_C_OnAuraRemovedT>();
|
|
|
|
// Call the original function
|
|
onAuraRemoved(unit, dummy_edx, slot, spellId);
|
|
|
|
TriggerAuraEvent(unit, slot, spellId, false);
|
|
}
|
|
|
|
void CGUnit_C_OnAuraAddedHook(hadesmem::PatchDetourBase *detour, uintptr_t *unit, void *dummy_edx, uint32_t slot,
|
|
uint32_t spellId) {
|
|
auto const onAuraAdded = detour->GetTrampolineT<CGUnit_C_OnAuraAddedT>();
|
|
|
|
// Call the original function
|
|
onAuraAdded(unit, dummy_edx, slot, spellId);
|
|
|
|
TriggerAuraEvent(unit, slot, spellId, true);
|
|
}
|
|
|
|
void CGUnit_C_OnAuraAddedStackHook(hadesmem::PatchDetourBase *detour, uintptr_t *unit, int slot) {
|
|
auto const unitAuraAddedStack = detour->GetTrampolineT<CGUnit_C_OnAuraAddedStackT>();
|
|
|
|
// Call the original function
|
|
unitAuraAddedStack(unit, slot);
|
|
|
|
// Get spell ID from the aura slot
|
|
auto *unitFields = *reinterpret_cast<game::UnitFields **>(unit + 68);
|
|
auto auras = unitFields->aura;
|
|
uint32_t spellId = auras[slot];
|
|
|
|
// Trigger the aura event for stack added
|
|
TriggerAuraEvent(unit, slot, spellId, true);
|
|
}
|
|
|
|
void CGBuffBar_UpdateDurationHook(hadesmem::PatchDetourBase *detour, uint8_t auraSlot, int durationMs) {
|
|
auto const updateDuration = detour->GetTrampolineT<CGBuffBar_UpdateDurationT>();
|
|
|
|
// Call the original function
|
|
updateDuration(auraSlot, durationMs);
|
|
|
|
// Store expiration time indexed by aura slot
|
|
if (auraSlot < MAX_AURA_SLOTS) {
|
|
auto now = static_cast<uint32_t>(GetWowTimeMs() & 0xFFFFFFFF);
|
|
uint32_t expirationTime = durationMs > 0 ? now + durationMs : 0;
|
|
gAuraExpirationTime[auraSlot] = expirationTime;
|
|
|
|
bool isBuff = auraSlot < 32;
|
|
game::Events eventToTrigger = isBuff ? game::BUFF_UPDATE_DURATION_SELF : game::DEBUFF_UPDATE_DURATION_SELF;
|
|
|
|
static char format[] = "%d%d%d";
|
|
((int (__cdecl *)(int, char *, uint32_t, int, uint32_t)) Offsets::SignalEventParam)(
|
|
eventToTrigger,
|
|
format,
|
|
auraSlot,
|
|
durationMs,
|
|
expirationTime);
|
|
}
|
|
}
|
|
|
|
void UnitCombatLogUnitDeadHook(hadesmem::PatchDetourBase *detour, uint64_t guid) {
|
|
auto const unitCombatLogUnitDead = detour->GetTrampolineT<UnitCombatLogUnitDeadT>();
|
|
|
|
// Call the original function
|
|
unitCombatLogUnitDead(guid);
|
|
|
|
// Trigger UNIT_DIED event
|
|
static char format[] = "%s";
|
|
char *guidStr = new char[21]; // 2 for 0x prefix, 18 for the number, and 1 for '\0'
|
|
std::snprintf(guidStr, 21, "0x%016llX", static_cast<unsigned long long>(guid));
|
|
|
|
((int (__cdecl *)(int, char *, char *)) Offsets::SignalEventParam)(
|
|
game::UNIT_DIED,
|
|
format,
|
|
guidStr);
|
|
|
|
delete[] guidStr;
|
|
}
|
|
}
|