mirror of
https://github.com/brues-code/nampower.git
synced 2026-10-01 03:00:01 +00:00
fix bugs with getEquippedItems, add randomPropertiesId, add quest functions
This commit is contained in:
+8
-5
@@ -332,8 +332,9 @@ Returns a table reference containing all equipped items for the specified unit.
|
||||
- `unitToken` (string): Can be a standard unit token ("player", "target", "pet", etc.) or a GUID string
|
||||
|
||||
**Returns:**
|
||||
- A Lua table reference with equipment slot indices as keys (0-18) and item info tables as values
|
||||
- A Lua table reference with equipment slot indices as keys (1-19) and item info tables as values. Empty slots are nil.
|
||||
- Returns nil if the unit cannot be found or inspected
|
||||
- Player and non-player calls return separate table references, so results do not overwrite each other
|
||||
|
||||
For the player, item info includes:
|
||||
- `itemId`: The item's ID
|
||||
@@ -341,6 +342,7 @@ For the player, item info includes:
|
||||
- `duration`: Item duration in milliseconds
|
||||
- `spellChargesRemaining`: Remaining spell charges as a single number. It uses the largest absolute value found in the internal 5-slot spell-charge array.
|
||||
- `flags`: Item flags
|
||||
- `randomPropertiesId`: Random property ID (e.g. for randomly enchanted items)
|
||||
- `permanentEnchantId`: Permanent enchantment ID
|
||||
- `tempEnchantId`: Temporary enchantment ID
|
||||
- `tempEnchantmentTimeLeftMs`: Time remaining on temp enchant in milliseconds
|
||||
@@ -350,6 +352,7 @@ For the player, item info includes:
|
||||
|
||||
For other inspected units (limited data):
|
||||
- `itemId`: The item's ID
|
||||
- `randomPropertiesId`: Random property ID
|
||||
- `permanentEnchantId`: Permanent enchantment ID
|
||||
- `tempEnchantId`: Temporary enchantment ID
|
||||
|
||||
@@ -368,8 +371,8 @@ end
|
||||
|
||||
-- Check player's weapon durability
|
||||
local items = GetEquippedItems("player")
|
||||
if items and items[15] then -- slot 15 is main hand
|
||||
local weapon = items[15]
|
||||
if items and items[16] then -- slot 16 is main hand
|
||||
local weapon = items[16]
|
||||
print("Weapon durability: " .. weapon.durability .. "/" .. weapon.maxDurability)
|
||||
end
|
||||
```
|
||||
@@ -379,14 +382,14 @@ Returns item info for a specific equipment slot on the specified unit.
|
||||
|
||||
**Parameters:**
|
||||
- `unitToken` (string): Can be a standard unit token ("player", "target", "pet", etc.) or a GUID string
|
||||
- `slot` (number): Equipment slot number (0-18)
|
||||
- `slot` (number): Equipment slot number (1-19)
|
||||
- 1 = Head, 2 = Neck, 3 = Shoulder, 4 = Shirt, 5 = Chest
|
||||
- 6 = Waist, 7 = Legs, 8 = Feet, 9 = Wrist, 10 = Hands
|
||||
- 11 = Finger 1, 12 = Finger 2, 13 = Trinket 1, 14 = Trinket 2
|
||||
- 15 = Back, 16 = Main Hand, 17 = Off Hand, 18 = Ranged, 19 = Tabard
|
||||
|
||||
**Returns:**
|
||||
- A Lua table reference containing the item info (same fields as GetEquippedItems)
|
||||
- A Lua table reference containing the item info (same fields as GetEquippedItems for the respective unit type)
|
||||
- Returns nil if the slot is empty, unit cannot be found, or unit cannot be inspected
|
||||
|
||||
**Examples:**
|
||||
|
||||
+12662
-12650
File diff suppressed because it is too large
Load Diff
@@ -529,6 +529,12 @@ namespace game {
|
||||
uint32_t itemId;
|
||||
uint32_t permanentEnchantId;
|
||||
uint32_t tempEnchantId;
|
||||
uint32_t unk2;
|
||||
uint32_t unk3;
|
||||
uint32_t unk4;
|
||||
uint32_t unk5;
|
||||
uint32_t unk6;
|
||||
uint32_t randomPropertiesId;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+35
-11
@@ -16,6 +16,7 @@ namespace Nampower {
|
||||
static int basicItemInfoTableRef = LUA_REFNIL;
|
||||
static int itemInfoTableRef = LUA_REFNIL;
|
||||
static int equippedItemsTableRef = LUA_REFNIL;
|
||||
static int targetEquippedItemsTableRef = LUA_REFNIL;
|
||||
static int bagItemsTableRef = LUA_REFNIL;
|
||||
static int trinketsTableRef = LUA_REFNIL;
|
||||
static uint32_t lastTrinketCount = 0;
|
||||
@@ -33,13 +34,21 @@ namespace Nampower {
|
||||
// Item entry table references: 2D matrix [bagIndex][slot] for direct mapping
|
||||
static std::array<std::array<int, MAX_BAG_SLOTS>, MAX_BAGS> itemEntryTableRefs{};
|
||||
|
||||
// Equipped item table references (slots 0-18)
|
||||
// Equipped item table references for player (slots 0-18)
|
||||
static std::array<int, MAX_EQUIPPED_SLOTS> equippedItemTableRefs{};
|
||||
|
||||
// Equipped item table references for non-player (target) inspections (slots 0-18)
|
||||
static std::array<int, MAX_EQUIPPED_SLOTS> targetEquippedItemTableRefs{};
|
||||
|
||||
// Trinket-specific table references (separate from equippedItemTableRefs/itemEntryTableRefs)
|
||||
static std::array<int, MAX_EQUIPPED_SLOTS> equippedTrinketTableRefs{};
|
||||
static std::array<std::array<int, MAX_BAG_SLOTS>, MAX_BAGS> bagTrinketTableRefs{};
|
||||
|
||||
// String keys used when pushing item data to Lua
|
||||
static char itemIdKey[] = "itemId";
|
||||
static char permanentEnchantIdKey[] = "permanentEnchantId";
|
||||
static char tempEnchantIdKey[] = "tempEnchantId";
|
||||
static char randomPropertiesIdKey[] = "randomPropertiesId";
|
||||
static char stackCountKey[] = "stackCount";
|
||||
static char durationKey[] = "duration";
|
||||
static char spellChargesRemainingKey[] = "spellChargesRemaining";
|
||||
@@ -117,6 +126,7 @@ namespace Nampower {
|
||||
PushTableValue(luaState, itemIdKey, cgItem->itemId);
|
||||
PushTableValue(luaState, permanentEnchantIdKey, cgItem->permanentEnchantId);
|
||||
PushTableValue(luaState, tempEnchantIdKey, cgItem->tempEnchantId);
|
||||
PushTableValue(luaState, randomPropertiesIdKey, cgItem->randomPropertiesId);
|
||||
}
|
||||
|
||||
void CreateItemInfoTable(uintptr_t *luaState, game::CGItem_C *item) {
|
||||
@@ -136,6 +146,7 @@ namespace Nampower {
|
||||
PushTableValue(luaState, durationKey, itemFields->duration);
|
||||
PushTableValue(luaState, spellChargesRemainingKey, GetMaxSpellChargesRemaining(itemFields->spellChargesRemaining));
|
||||
PushTableValue(luaState, flagsKey, itemFields->flags);
|
||||
PushTableValue(luaState, randomPropertiesIdKey, itemFields->randomPropertiesId);
|
||||
PushTableValue(luaState, permanentEnchantIdKey, itemFields->permEnchantmentSlot.id);
|
||||
PushTableValue(luaState, tempEnchantIdKey, itemFields->tempEnchantmentSlot.id);
|
||||
PushTableValue(luaState, tempEnchantmentTimeLeftMsKey, itemFields->tempEnchantmentSlot.duration);
|
||||
@@ -203,6 +214,7 @@ namespace Nampower {
|
||||
currentData.duration = itemFields->duration;
|
||||
currentData.spellChargesRemaining = GetMaxSpellChargesRemaining(itemFields->spellChargesRemaining);
|
||||
currentData.flags = itemFields->flags;
|
||||
currentData.randomPropertiesId = itemFields->randomPropertiesId;
|
||||
currentData.permanentEnchantId = itemFields->permEnchantmentSlot.id;
|
||||
currentData.tempEnchantId = itemFields->tempEnchantmentSlot.id;
|
||||
currentData.tempEnchantmentTimeLeftMs = itemFields->tempEnchantmentSlot.duration;
|
||||
@@ -276,6 +288,7 @@ namespace Nampower {
|
||||
PushTableValue(luaState, durationKey, itemFields->duration);
|
||||
PushTableValue(luaState, spellChargesRemainingKey, GetMaxSpellChargesRemaining(itemFields->spellChargesRemaining));
|
||||
PushTableValue(luaState, flagsKey, itemFields->flags);
|
||||
PushTableValue(luaState, randomPropertiesIdKey, itemFields->randomPropertiesId);
|
||||
PushTableValue(luaState, permanentEnchantIdKey, itemFields->permEnchantmentSlot.id);
|
||||
PushTableValue(luaState, tempEnchantIdKey, itemFields->tempEnchantmentSlot.id);
|
||||
PushTableValue(luaState, tempEnchantmentTimeLeftMsKey, itemFields->tempEnchantmentSlot.duration);
|
||||
@@ -571,10 +584,10 @@ namespace Nampower {
|
||||
if (copyTable) {
|
||||
lua_newtable(luaState);
|
||||
} else {
|
||||
// Get table ref based on location (direct 2D mapping)
|
||||
// Use dedicated trinket table refs, separate from GetEquippedItems/GetBagItems refs
|
||||
if (bagIndex == EQUIPPED_BAG_INDEX) {
|
||||
if (slot < MAX_EQUIPPED_SLOTS) {
|
||||
GetTableRef(luaState, equippedItemTableRefs[slot]);
|
||||
GetTableRef(luaState, equippedTrinketTableRefs[slot]);
|
||||
} else {
|
||||
lua_newtable(luaState);
|
||||
}
|
||||
@@ -589,7 +602,7 @@ namespace Nampower {
|
||||
}
|
||||
|
||||
if (adjustedSlot < MAX_BAG_SLOTS) {
|
||||
GetTableRef(luaState, itemEntryTableRefs[cacheIndexForTableRef][adjustedSlot]);
|
||||
GetTableRef(luaState, bagTrinketTableRefs[cacheIndexForTableRef][adjustedSlot]);
|
||||
} else {
|
||||
lua_newtable(luaState);
|
||||
}
|
||||
@@ -612,7 +625,7 @@ namespace Nampower {
|
||||
PushTableValue(luaState, itemLevelKey, itemStats->m_itemLevel);
|
||||
|
||||
// Get texture path using display ID
|
||||
if (itemStats && itemStats->m_displayInfoID > 0) {
|
||||
if (itemStats->m_displayInfoID > 0) {
|
||||
char *texturePath = getInventoryArt(itemStats->m_displayInfoID);
|
||||
if (texturePath && texturePath[0] != '\0') {
|
||||
PushTableValue(luaState, textureKey, texturePath);
|
||||
@@ -707,12 +720,13 @@ namespace Nampower {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get or create reusable table
|
||||
GetTableRef(luaState, equippedItemsTableRef);
|
||||
|
||||
auto playerGuid = game::ClntObjMgrGetActivePlayerGuid();
|
||||
bool isPlayer = (guid == playerGuid);
|
||||
|
||||
// Use separate outer tables for player vs target to avoid cross-contamination
|
||||
GetTableRef(luaState, isPlayer ? equippedItemsTableRef : targetEquippedItemsTableRef);
|
||||
|
||||
|
||||
if (isPlayer) {
|
||||
auto const getBagItem = reinterpret_cast<CGBag_C_GetItemAtSlotT>(Offsets::CGBag_C_GetItemAtSlot);
|
||||
auto inventory = game::GetPlayerInventoryPtr(unit);
|
||||
@@ -721,6 +735,10 @@ namespace Nampower {
|
||||
auto item = getBagItem(inventory, slot);
|
||||
if (item) {
|
||||
PushBagCGItemToTable(luaState, -999, slot, item);
|
||||
} else {
|
||||
lua_pushnumber(luaState, static_cast<double>(slot + 1));
|
||||
lua_pushnil(luaState);
|
||||
lua_settable(luaState, -3);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -729,11 +747,17 @@ namespace Nampower {
|
||||
|
||||
for (uint32_t slot = 0; slot <= 18; slot++) {
|
||||
auto cgItem = getEquippedItem(unit, slot);
|
||||
lua_pushnumber(luaState, static_cast<double>(slot+1)); // lua is 1 indexed
|
||||
if (cgItem) {
|
||||
lua_pushnumber(luaState, static_cast<double>(slot+1)); // lua is 1 indexed
|
||||
CreateBasicItemInfoTable(luaState, cgItem);
|
||||
lua_settable(luaState, -3);
|
||||
GetTableRef(luaState, targetEquippedItemTableRefs[slot]);
|
||||
PushTableValue(luaState, itemIdKey, cgItem->itemId);
|
||||
PushTableValue(luaState, permanentEnchantIdKey, cgItem->permanentEnchantId);
|
||||
PushTableValue(luaState, tempEnchantIdKey, cgItem->tempEnchantId);
|
||||
PushTableValue(luaState, randomPropertiesIdKey, cgItem->randomPropertiesId);
|
||||
} else {
|
||||
lua_pushnil(luaState);
|
||||
}
|
||||
lua_settable(luaState, -3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Nampower {
|
||||
uint32_t duration;
|
||||
int32_t spellChargesRemaining;
|
||||
uint32_t flags;
|
||||
uint32_t randomPropertiesId;
|
||||
uint32_t permanentEnchantId;
|
||||
uint32_t tempEnchantId;
|
||||
uint32_t tempEnchantmentTimeLeftMs;
|
||||
@@ -49,6 +50,7 @@ namespace Nampower {
|
||||
uint32_t maxDurability;
|
||||
|
||||
CachedItemData() : itemId(0), stackCount(0), duration(0), spellChargesRemaining(0), flags(0),
|
||||
randomPropertiesId(0),
|
||||
permanentEnchantId(0), tempEnchantId(0),
|
||||
tempEnchantmentTimeLeftMs(0), tempEnchantmentCharges(0),
|
||||
durability(0), maxDurability(0) {}
|
||||
@@ -59,6 +61,7 @@ namespace Nampower {
|
||||
duration == other.duration &&
|
||||
spellChargesRemaining == other.spellChargesRemaining &&
|
||||
flags == other.flags &&
|
||||
randomPropertiesId == other.randomPropertiesId &&
|
||||
permanentEnchantId == other.permanentEnchantId &&
|
||||
tempEnchantId == other.tempEnchantId &&
|
||||
tempEnchantmentTimeLeftMs == other.tempEnchantmentTimeLeftMs &&
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ namespace Nampower {
|
||||
constexpr uint32_t DISENCHANT_QUALITY_PURPLE = 0x04; // Epic
|
||||
|
||||
constexpr uint32_t MAJOR_VERSION = 4;
|
||||
constexpr uint32_t MINOR_VERSION = 5;
|
||||
constexpr uint32_t MINOR_VERSION = 6;
|
||||
constexpr uint32_t PATCH_VERSION = 0;
|
||||
|
||||
constexpr int32_t LUA_REGISTRYINDEX = -10000;
|
||||
|
||||
+41
-6
@@ -6,9 +6,11 @@
|
||||
|
||||
#include "offsets.hpp"
|
||||
#include "helper.hpp"
|
||||
#include "lua_refs.hpp"
|
||||
|
||||
namespace Nampower {
|
||||
enum class QuestDialogKind : int32_t {
|
||||
enum class QuestDialogKind : uint32_t {
|
||||
UNKNOWN = 0,
|
||||
DETAIL = 1,
|
||||
PROGRESS = 2,
|
||||
COMPLETE = 3,
|
||||
@@ -22,6 +24,8 @@ namespace Nampower {
|
||||
};
|
||||
|
||||
static constexpr uint32_t kQuestLogMaxRows = 256;
|
||||
static int questLogQuestIdsTableRef = LUA_REFNIL;
|
||||
static uint32_t questLogQuestIdsCount = 0;
|
||||
|
||||
static uint32_t *GetQuestLogEntryCountPtr() {
|
||||
return reinterpret_cast<uint32_t *>(Offsets::QuestLogEntryCount);
|
||||
@@ -31,14 +35,18 @@ namespace Nampower {
|
||||
return reinterpret_cast<QuestLogEntryRaw *>(Offsets::QuestLogEntries);
|
||||
}
|
||||
|
||||
static int32_t GetQuestDialogStateCode() {
|
||||
return *reinterpret_cast<int32_t *>(Offsets::QuestDialogState);
|
||||
static QuestDialogKind GetQuestDialogStateCode() {
|
||||
auto const raw = *reinterpret_cast<uint32_t *>(Offsets::QuestDialogState);
|
||||
if (raw == 0 || raw > static_cast<uint32_t>(QuestDialogKind::COMPLETE)) {
|
||||
return QuestDialogKind::UNKNOWN;
|
||||
}
|
||||
|
||||
return static_cast<QuestDialogKind>(raw);
|
||||
}
|
||||
|
||||
static uint32_t GetQuestDialogQuestIdRaw() {
|
||||
auto const state = GetQuestDialogStateCode();
|
||||
if (state < static_cast<int32_t>(QuestDialogKind::DETAIL) ||
|
||||
state > static_cast<int32_t>(QuestDialogKind::COMPLETE)) {
|
||||
if (state == QuestDialogKind::UNKNOWN) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -49,10 +57,27 @@ namespace Nampower {
|
||||
uint32_t Script_GetQuestLogQuestIds(uintptr_t *luaState) {
|
||||
luaState = GetLuaStatePtr();
|
||||
|
||||
lua_newtable(luaState);
|
||||
bool useCopy = false;
|
||||
if (lua_isnumber(luaState, 1)) {
|
||||
useCopy = static_cast<int>(lua_tonumber(luaState, 1)) != 0;
|
||||
}
|
||||
|
||||
if (useCopy) {
|
||||
lua_newtable(luaState);
|
||||
} else {
|
||||
GetTableRef(luaState, questLogQuestIdsTableRef);
|
||||
}
|
||||
|
||||
auto const rowCount = *GetQuestLogEntryCountPtr();
|
||||
if (rowCount == 0 || rowCount > kQuestLogMaxRows) {
|
||||
if (!useCopy && questLogQuestIdsCount != 0) {
|
||||
for (uint32_t i = 1; i <= questLogQuestIdsCount; ++i) {
|
||||
lua_pushnumber(luaState, static_cast<double>(i));
|
||||
lua_pushnil(luaState);
|
||||
lua_settable(luaState, -3);
|
||||
}
|
||||
questLogQuestIdsCount = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -71,6 +96,16 @@ namespace Nampower {
|
||||
++outIndex;
|
||||
}
|
||||
|
||||
auto const currentCount = static_cast<uint32_t>(outIndex - 1);
|
||||
if (!useCopy) {
|
||||
for (uint32_t i = currentCount + 1; i <= questLogQuestIdsCount; ++i) {
|
||||
lua_pushnumber(luaState, static_cast<double>(i));
|
||||
lua_pushnil(luaState);
|
||||
lua_settable(luaState, -3);
|
||||
}
|
||||
questLogQuestIdsCount = currentCount;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user