add CancelPlayerAuraSpellId/CancelPlayerAuraSlot

This commit is contained in:
avitasia
2026-02-12 09:10:14 -08:00
parent a7d2cd4fa6
commit c094fdd5e8
10 changed files with 11003 additions and 10895 deletions
+3 -1
View File
@@ -152,9 +152,11 @@ This includes functions for:
- Cast information (GetCastInfo, GetCurrentCastingInfo)
- Cooldown tracking (GetSpellIdCooldown, GetItemIdCooldown), including item metadata on cooldown detail tables
- Inventory helpers (GetTrinketCooldown, GetTrinkets, GetAmmo)
- Aura duration tracking (GetPlayerAuraDuration)
- Aura duration tracking and cancel helpers (GetPlayerAuraDuration, CancelPlayerAuraSlot, CancelPlayerAuraSpellId)
- Spell lookups and utilities
`CancelPlayerAuraSpellId(spellId, [ignoreMissing])` supports an optional second parameter where `1` skips the aura-slot presence check (useful for buff-capped cases) and `0`/omitted keeps the default check.
Cooldown detail tables now also expose `itemId`, `itemHasActiveSpell`, and `itemActiveSpellId` alongside the existing per-category timing data.
Use `GetTrinkets([copy])` to enumerate equipped trinkets and bagged trinkets (backpack/bags 1-4) with `itemId`, `trinketName`, `texture`, `itemLevel`, `bagIndex` (nil when equipped), and 1-based `slotIndex`. It reuses cached tables by default; pass `1` (or any truthy value) to force a fresh copy.
+10891 -10884
View File
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -147,10 +147,9 @@ namespace Nampower {
bool isBuff = auraSlot < 32;
game::Events eventToTrigger = isBuff ? game::BUFF_UPDATE_DURATION_SELF : game::DEBUFF_UPDATE_DURATION_SELF;
auto playerUnit = game::GetObjectPtr(game::ClntObjMgrGetActivePlayerGuid());
uint32_t spellId = 0;
if (playerUnit) {
auto *unitFields = *reinterpret_cast<game::UnitFields **>(playerUnit + 68);
auto *unitFields = game::GetActivePlayerUnitFields();
if (unitFields) {
spellId = unitFields->aura[auraSlot];
}
+11 -1
View File
@@ -134,6 +134,16 @@ namespace game {
return getActivePlayer();
}
UnitFields *GetActivePlayerUnitFields() {
auto const playerGuid = ClntObjMgrGetActivePlayerGuid();
auto *playerUnit = GetObjectPtr(playerGuid);
if (!playerUnit) {
return nullptr;
}
return *reinterpret_cast<UnitFields **>(playerUnit + 68);
}
std::uint64_t GetCurrentTargetGuid() {
return *reinterpret_cast<uint64_t *>(Offsets::LockedTargetGuid);
}
@@ -267,4 +277,4 @@ namespace game {
return unitFields->mountDisplayId;
}
}
}
+1
View File
@@ -1786,6 +1786,7 @@ namespace game {
const char *GetSpellName(uint32_t spellId);
std::uint64_t ClntObjMgrGetActivePlayerGuid();
UnitFields *GetActivePlayerUnitFields();
std::uint64_t GetCurrentTargetGuid();
+6
View File
@@ -1689,6 +1689,12 @@ namespace Nampower {
char getPlayerAuraDuration[] = "GetPlayerAuraDuration";
RegisterLuaFunction(getPlayerAuraDuration, reinterpret_cast<uintptr_t *>(Script_GetPlayerAuraDuration));
char cancelPlayerAuraSlot[] = "CancelPlayerAuraSlot";
RegisterLuaFunction(cancelPlayerAuraSlot, reinterpret_cast<uintptr_t *>(Script_CancelPlayerAuraSlot));
char cancelPlayerAuraSpellId[] = "CancelPlayerAuraSpellId";
RegisterLuaFunction(cancelPlayerAuraSpellId, reinterpret_cast<uintptr_t *>(Script_CancelPlayerAuraSpellId));
char getSpellPower[] = "GetSpellPower";
RegisterLuaFunction(getSpellPower, reinterpret_cast<uintptr_t *>(Script_GetSpellPower));
+1 -1
View File
@@ -25,7 +25,7 @@ namespace Nampower {
constexpr uint32_t DISENCHANT_QUALITY_PURPLE = 0x04; // Epic
constexpr uint32_t MAJOR_VERSION = 2;
constexpr uint32_t MINOR_VERSION = 33;
constexpr uint32_t MINOR_VERSION = 34;
constexpr uint32_t PATCH_VERSION = 0;
constexpr int32_t LUA_REGISTRYINDEX = -10000;
+85 -5
View File
@@ -857,14 +857,11 @@ namespace Nampower {
}
// Get spellId from player unit fields
auto playerGuid = game::ClntObjMgrGetActivePlayerGuid();
auto *playerUnit = game::GetObjectPtr(playerGuid);
if (!playerUnit) {
auto *unitFields = game::GetActivePlayerUnitFields();
if (!unitFields) {
lua_pushnil(luaState);
return 1;
}
auto *unitFields = *reinterpret_cast<game::UnitFields **>(playerUnit + 68);
uint32_t spellId = unitFields->aura[auraSlot];
uint32_t expirationTime = gAuraExpirationTime[auraSlot];
@@ -877,6 +874,89 @@ namespace Nampower {
return 3;
}
uint32_t Script_CancelPlayerAuraSlot(uintptr_t *luaState) {
constexpr uint32_t kMaxCancelAuraSlots = 32;
luaState = GetLuaStatePtr();
if (!lua_isnumber(luaState, 1)) {
lua_error(luaState, "Usage: CancelPlayerAuraSlot(auraSlot)");
return 0;
}
auto auraSlot = static_cast<uint32_t>(lua_tonumber(luaState, 1));
if (auraSlot >= kMaxCancelAuraSlots) {
lua_pushnumber(luaState, 0);
return 1;
}
auto *unitFields = game::GetActivePlayerUnitFields();
if (!unitFields) {
lua_pushnumber(luaState, 0);
return 1;
}
auto spellId = static_cast<int>(unitFields->aura[auraSlot]);
if (spellId == 0) {
lua_pushnumber(luaState, 0);
return 1;
}
auto const cancelAura = reinterpret_cast<void(__fastcall *)(int)>(Offsets::Spell_C_CancelAura);
cancelAura(spellId);
lua_pushnumber(luaState, 1);
return 1;
}
uint32_t Script_CancelPlayerAuraSpellId(uintptr_t *luaState) {
constexpr uint32_t kMaxCancelAuraSlots = 32;
luaState = GetLuaStatePtr();
if (!lua_isnumber(luaState, 1)) {
lua_error(luaState, "Usage: CancelPlayerAuraSpellId(spellId, [ignoreMissing])");
return 0;
}
auto spellId = static_cast<uint32_t>(lua_tonumber(luaState, 1));
if (spellId == 0) {
lua_pushnumber(luaState, 0);
return 1;
}
// Optional arg2: 1 skips aura-presence check, 0/missing keeps default behavior.
bool ignoreMissing = false;
if (lua_isnumber(luaState, 2)) {
ignoreMissing = (static_cast<int>(lua_tonumber(luaState, 2)) == 1);
}
if (!ignoreMissing) {
auto *unitFields = game::GetActivePlayerUnitFields();
if (!unitFields) {
lua_pushnumber(luaState, 0);
return 1;
}
bool foundSpell = false;
for (uint32_t auraSlot = 0; auraSlot < kMaxCancelAuraSlots; ++auraSlot) {
if (unitFields->aura[auraSlot] == spellId) {
foundSpell = true;
break;
}
}
if (!foundSpell) {
lua_pushnumber(luaState, 0);
return 1;
}
}
auto const cancelAura = reinterpret_cast<void(__fastcall *)(uint32_t)>(Offsets::Spell_C_CancelAura);
cancelAura(spellId);
lua_pushnumber(luaState, 1);
return 1;
}
uint32_t CSimpleFrame_GetNameHook(hadesmem::PatchDetourBase *detour, uintptr_t *luaState) {
luaState = GetLuaStatePtr();
+2
View File
@@ -41,6 +41,8 @@ namespace Nampower {
bool RunQueuedScript(int priority);
uint32_t Script_GetPlayerAuraDuration(uintptr_t *luaState);
uint32_t Script_CancelPlayerAuraSlot(uintptr_t *luaState);
uint32_t Script_CancelPlayerAuraSpellId(uintptr_t *luaState);
uint32_t CSimpleFrame_GetNameHook(hadesmem::PatchDetourBase *detour, uintptr_t *luaState);
}
+1
View File
@@ -117,6 +117,7 @@ enum class Offsets : std::uint32_t {
Spell_C_GetAutoRepeatingSpell = 0x006E9FD0,
Spell_C_HandleSpriteClick = 0x006E5B10,
Spell_C_HandleTerrainClick = 0x006E60F0,
Spell_C_CancelAura = 0x006E7040,
CGWorldFrame_OnLayerTrackTerrain = 0x004820F0,
Spell_C_TargetSpell = 0x006E5250,
Spell_C_GetSpellCooldown = 0X006E2EA0,