fix GetUnitData/GetUnitField on invisible raid members for some info

This commit is contained in:
avitasia
2026-03-19 10:27:43 -07:00
parent 6d18fbdbbb
commit 56d0952cdc
9 changed files with 12209 additions and 12134 deletions
+10
View File
@@ -744,6 +744,11 @@ Returns a Lua table reference containing all unit fields for the specified unit.
- A Lua table reference containing all unit fields, or nil if the unit cannot be found
- Object-reference GUID fields are returned as hex GUID strings (not numbers) to avoid Lua 64-bit precision issues. This includes fields such as `charm`, `summon`, `charmedBy`, `summonedBy`, `createdBy`, `target`, `persuaded`, and `channelObject`.
**Note — raid members not in your immediate party:** For raid members outside your local 5-man group who are not in your object manager (e.g. not nearby or not visible), only a limited subset of fields are available. All other fields will be zero/default.
- **Player fields:** status flags (online/offline/dead), current and max HP, power type, current and max power, level, zone, auras (up to 32 positive + 16 negative — spell IDs only, no stack count)
- **Pet fields:** GUID, name, model ID, current and max HP, power type, current and max power, auras (same format as player)
- No stats, no buff details beyond spell IDs.
Full field name lists are in [`UNIT_FIELDS.md`](UNIT_FIELDS.md).
**Example:**
@@ -773,6 +778,11 @@ Fast lookup for a single field on a unit. More efficient than GetUnitData when y
- For array fields (like "aura", "resistances"), returns a Lua table with numeric indices
- Object-reference GUID fields are returned as hex GUID strings (not numbers) to avoid Lua 64-bit precision issues. This includes fields such as `charm`, `summon`, `charmedBy`, `summonedBy`, `createdBy`, `target`, `persuaded`, and `channelObject`.
**Note — raid members not in your immediate party:** For raid members outside your local 5-man group who are not in your object manager (e.g. not nearby or not visible), only a limited subset of fields are available. All other fields will be zero/default.
- **Player fields:** status flags (online/offline/dead), current and max HP, power type, current and max power, level, zone, auras (up to 32 positive + 16 negative — spell IDs only, no stack count)
- **Pet fields:** GUID, name, model ID, current and max HP, power type, current and max power, auras (same format as player)
- No stats, no buff details beyond spell IDs.
Full field name lists are in [`UNIT_FIELDS.md`](UNIT_FIELDS.md).
**Examples:**
+12133 -12118
View File
File diff suppressed because it is too large Load Diff
+35 -9
View File
@@ -301,16 +301,42 @@ namespace Nampower {
return 0;
}
std::ofstream out(Utf8ToWide(fullPath), openMode);
if (!out) {
lua_error(luaState, "Failed to open file for writing.");
return 0;
}
// For truncating writes use a temp file + atomic rename so a crash
// during the write doesn't leave the original file empty/corrupt.
if (mode == 'w' || mode == 'b') {
const std::wstring wideFull = Utf8ToWide(fullPath);
const std::wstring wideTemp = wideFull + L".tmp";
out << content;
if (!out) {
lua_error(luaState, "Failed to write file.");
return 0;
{
std::ofstream out(wideTemp, openMode);
if (!out) {
lua_error(luaState, "Failed to open temp file for writing.");
return 0;
}
out << content;
if (!out) {
lua_error(luaState, "Failed to write temp file.");
DeleteFileW(wideTemp.c_str());
return 0;
}
}
if (!MoveFileExW(wideTemp.c_str(), wideFull.c_str(), MOVEFILE_REPLACE_EXISTING)) {
lua_error(luaState, "Failed to rename temp file to destination.");
DeleteFileW(wideTemp.c_str());
return 0;
}
} else {
std::ofstream out(Utf8ToWide(fullPath), openMode);
if (!out) {
lua_error(luaState, "Failed to open file for writing.");
return 0;
}
out << content;
if (!out) {
lua_error(luaState, "Failed to write file.");
return 0;
}
}
return 0;
+1
View File
@@ -65,6 +65,7 @@ namespace game {
return getObjectPtr(guid);
}
uintptr_t *ClntObjMgrObjectPtr(TypeMask typeMask, std::uint64_t guid) {
using ClntObjMgrObjectPtrT = uintptr_t* (__fastcall *)(TypeMask typeMask, const char *debugMessage, unsigned __int64 guid, int debugCode);
auto const clntObjMgrObjectPtr = reinterpret_cast<ClntObjMgrObjectPtrT>(Offsets::ClntObjMgrObjectPtr);
+1 -1
View File
@@ -27,7 +27,7 @@ namespace Nampower {
constexpr uint32_t MAJOR_VERSION = 4;
constexpr uint32_t MINOR_VERSION = 1;
constexpr uint32_t PATCH_VERSION = 1;
constexpr uint32_t PATCH_VERSION = 2;
constexpr int32_t LUA_REGISTRYINDEX = -10000;
constexpr int32_t LUA_GLOBALSINDEX = -10001;
+3 -2
View File
@@ -5,6 +5,7 @@
#include "misc_scripts.hpp"
#include "logging.hpp"
#include "offsets.hpp"
#include "unit.hpp"
#include "items.hpp"
#include "dbc_fields.hpp"
#include "unit_fields.hpp"
@@ -384,7 +385,7 @@ namespace Nampower {
}
// Get unit object pointer
auto unit = game::GetObjectPtr(guid);
auto unit = GetUnitPtr(guid);
if (!unit) {
lua_pushnil(luaState);
return 1;
@@ -469,7 +470,7 @@ namespace Nampower {
}
// Get unit object pointer
auto unit = game::GetObjectPtr(guid);
auto unit = GetUnitPtr(guid);
if (!unit) {
lua_pushnil(luaState);
return 1;
+2
View File
@@ -107,6 +107,8 @@ enum class Offsets : std::uint32_t {
CGGameUI_GetPartyMemberPet = 0X004E81D0,
CGGameUI_GetRaidMember = 0X00491940,
CGGameUI_GetRaidMemberPet = 0X00491960,
CGGameUI_GetPartyOrRaidMember = 0x00496400,
CGGameUI_GetPartyOrRaidPet = 0x00496420,
SpellVisualsHandleCastStart = 0X006EC220,
PlaySpellVisualHandler = 0X006E98D0,
+17
View File
@@ -9,6 +9,23 @@
#include "logging.hpp"
namespace Nampower {
uintptr_t *GetUnitPtr(uint64_t guid) {
if (auto *unit = game::GetObjectPtr(guid)) {
return unit;
}
auto const getPartyOrRaidMember = reinterpret_cast<CGGameUI_GetPartyOrRaidMemberT>(
Offsets::CGGameUI_GetPartyOrRaidMember);
if (auto *unit = getPartyOrRaidMember(&guid)) {
return unit;
}
auto const getPartyOrRaidPet = reinterpret_cast<CGGameUI_GetPartyOrRaidPetT>(
Offsets::CGGameUI_GetPartyOrRaidPet);
auto *unit = getPartyOrRaidPet(&guid);
return unit;
}
UnitNames GetUnitNames(uint64_t *guid) {
UnitNames names;
+7 -4
View File
@@ -59,10 +59,12 @@ namespace Nampower {
}
};
using CGGameUI_GetPartyMemberT = uint64_t (__fastcall *)(uint32_t index);
using CGGameUI_GetPartyMemberPetT = uint64_t (__fastcall *)(uint32_t index);
using CGGameUI_GetRaidMemberT = uint64_t (__fastcall *)(uint32_t index);
using CGGameUI_GetRaidMemberPetT = uint64_t (__fastcall *)(uint32_t index);
using CGGameUI_GetPartyMemberT = uint64_t (__fastcall *)(uint32_t index);
using CGGameUI_GetPartyMemberPetT = uint64_t (__fastcall *)(uint32_t index);
using CGGameUI_GetRaidMemberT = uint64_t (__fastcall *)(uint32_t index);
using CGGameUI_GetRaidMemberPetT = uint64_t (__fastcall *)(uint32_t index);
using CGGameUI_GetPartyOrRaidMemberT = uintptr_t *(__fastcall *)(uint64_t *guid);
using CGGameUI_GetPartyOrRaidPetT = uintptr_t *(__fastcall *)(uint64_t *guid);
using CGUnit_C_HandleEnvironmentDamageT = void (__fastcall *)(uintptr_t *unit, void *dummy_edx, int dmgType, int damage, int absorb, int resist);
using UnitCombatLogDamageShieldT = void (__fastcall *)(uint64_t *victimGuid, uint64_t *unitGuid, uint32_t damage, uint32_t spellSchool);
@@ -72,6 +74,7 @@ namespace Nampower {
using SignalEventParamGuidT = int (__cdecl *)(uint32_t eventCode, const char *format, const char *guid, int isPlayer, int isTarget, int isMouseover, int isPet, int partyIndex, int raidIndex);
using SignalEventParamUnitCombatGuidT = int (__cdecl *)(uint32_t eventCode, const char *format, const char *guid, const char *action, int damage, int school, int hitInfo, int isPet, int partyIndex, int raidIndex);
uintptr_t *GetUnitPtr(uint64_t guid);
UnitNames GetUnitNames(uint64_t *guid);
void FireUnitGuidEvent(const UnitNames &names, uint32_t guidEventCode);
void TriggerUnitEvents(const UnitNames &names, uint32_t eventCode);