mirror of
https://github.com/brues-code/nampower.git
synced 2026-09-21 23:26:54 +00:00
fix GetItemStats for non english languages, refactor some item scripts
This commit is contained in:
+4148
-4147
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -452,7 +452,7 @@ namespace game {
|
|||||||
struct __declspec(align(4)) ItemStats_C {
|
struct __declspec(align(4)) ItemStats_C {
|
||||||
ItemClass m_class;
|
ItemClass m_class;
|
||||||
int m_subclass;
|
int m_subclass;
|
||||||
char *m_displayName[4];
|
char *m_displayName[4]; // only index 0 is used and is already localized. Other indexes are all null strings.
|
||||||
int m_displayInfoID;
|
int m_displayInfoID;
|
||||||
int m_quality;
|
int m_quality;
|
||||||
ItemStatsFlags m_flags;
|
ItemStatsFlags m_flags;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "item_scripts.hpp"
|
#include "item_scripts.hpp"
|
||||||
|
|
||||||
|
#include "dbc_fields.hpp"
|
||||||
#include "helper.hpp"
|
#include "helper.hpp"
|
||||||
#include "items.hpp"
|
#include "items.hpp"
|
||||||
#include "logging.hpp"
|
#include "logging.hpp"
|
||||||
@@ -8,6 +9,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace Nampower {
|
namespace Nampower {
|
||||||
// Reusable table references to reduce memory allocations
|
// Reusable table references to reduce memory allocations
|
||||||
@@ -17,6 +19,13 @@ namespace Nampower {
|
|||||||
static int bagItemsTableRef = LUA_REFNIL;
|
static int bagItemsTableRef = LUA_REFNIL;
|
||||||
static int trinketsTableRef = LUA_REFNIL;
|
static int trinketsTableRef = LUA_REFNIL;
|
||||||
static uint32_t lastTrinketCount = 0;
|
static uint32_t lastTrinketCount = 0;
|
||||||
|
static int itemStatsTableRef = LUA_REFNIL;
|
||||||
|
|
||||||
|
// Maps to store separate references for each array field name (for Field functions)
|
||||||
|
static std::unordered_map<std::string, int> itemStatsArrayFieldRefs;
|
||||||
|
|
||||||
|
// Maps to store separate references for nested array fields (for main table functions)
|
||||||
|
static std::unordered_map<std::string, int> itemStatsNestedArrayRefs;
|
||||||
|
|
||||||
// Bag items table references (11 bags: 0-10, plus special indices for -1 bank, -2 keyring)
|
// Bag items table references (11 bags: 0-10, plus special indices for -1 bank, -2 keyring)
|
||||||
static std::array<int, MAX_BAGS> bagTableRefs{};
|
static std::array<int, MAX_BAGS> bagTableRefs{};
|
||||||
@@ -1084,6 +1093,208 @@ namespace Nampower {
|
|||||||
return GetAllBagItems(luaState);
|
return GetAllBagItems(luaState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Script_GetItemLevel(uintptr_t *luaState) {
|
||||||
|
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
||||||
|
|
||||||
|
if (lua_isnumber(luaState, 1)) {
|
||||||
|
auto const itemId = static_cast<uint32_t>(lua_tonumber(luaState, 1));
|
||||||
|
|
||||||
|
// Pointer to ItemDBCache
|
||||||
|
void *itemDbCache = reinterpret_cast<void *>(Offsets::ItemDBCache);
|
||||||
|
|
||||||
|
// Parameters for the DBCache<>::GetRecord function
|
||||||
|
int **param2 = nullptr;
|
||||||
|
int *param3 = nullptr;
|
||||||
|
int *param4 = nullptr;
|
||||||
|
char param5 = 0;
|
||||||
|
|
||||||
|
// Call the DBCache<>::GetRecord function
|
||||||
|
auto getRecord = reinterpret_cast<uintptr_t *(__thiscall *)(void *, uint32_t, int **, int *, int *, char)>(
|
||||||
|
Offsets::DBCacheGetRecord
|
||||||
|
);
|
||||||
|
uintptr_t *itemObject = getRecord(itemDbCache, itemId, param2, param3, param4, param5);
|
||||||
|
if (itemObject == nullptr) {
|
||||||
|
lua_error(luaState, "Item not found in DBCache");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t itemLevel = *reinterpret_cast<uint32_t *>(itemObject + 14);
|
||||||
|
lua_pushnumber(luaState, itemLevel);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
lua_error(luaState, "Usage: GetItemLevel(itemId)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Script_GetItemStats(uintptr_t *luaState) {
|
||||||
|
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
||||||
|
|
||||||
|
if (!lua_isnumber(luaState, 1)) {
|
||||||
|
lua_error(luaState, "Usage: GetItemStats(itemId, [copy])");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t itemId = static_cast<uint32_t>(lua_tonumber(luaState, 1));
|
||||||
|
|
||||||
|
// Check for optional copy parameter
|
||||||
|
bool useCopy = false;
|
||||||
|
if (lua_isnumber(luaState, 2)) {
|
||||||
|
useCopy = static_cast<int>(lua_tonumber(luaState, 2)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get from cache
|
||||||
|
game::ItemStats_C *item = GetItemStats(itemId);
|
||||||
|
if (!item) {
|
||||||
|
lua_pushnil(luaState);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new table or get reusable table based on copy parameter
|
||||||
|
if (useCopy) {
|
||||||
|
lua_newtable(luaState);
|
||||||
|
} else {
|
||||||
|
GetTableRef(luaState, itemStatsTableRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push all simple fields using descriptors
|
||||||
|
PushFieldsToLua(luaState, item, itemStatsFields, itemStatsFieldsCount);
|
||||||
|
|
||||||
|
// Push string fields manually
|
||||||
|
PushTableValue(luaState, const_cast<char *>("displayName"),
|
||||||
|
item->m_displayName[0] ? item->m_displayName[0] : const_cast<char *>(""));
|
||||||
|
PushTableValue(luaState, const_cast<char *>("description"),
|
||||||
|
item->m_description ? item->m_description : const_cast<char *>(""));
|
||||||
|
|
||||||
|
// Push all array fields using descriptors with or without references based on copy parameter
|
||||||
|
if (useCopy) {
|
||||||
|
PushArrayFieldsToLua(luaState, item, itemStatsArrayFields, itemStatsArrayFieldsCount);
|
||||||
|
} else {
|
||||||
|
PushArrayFieldsToLuaWithRefs(luaState, item, itemStatsArrayFields, itemStatsArrayFieldsCount, itemStatsNestedArrayRefs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Return the table
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Script_GetItemStatsField(uintptr_t *luaState) {
|
||||||
|
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
||||||
|
|
||||||
|
if (!lua_isnumber(luaState, 1) || !lua_isstring(luaState, 2)) {
|
||||||
|
lua_error(luaState, "Usage: GetItemStatsField(itemId, fieldName, [copy])");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeFieldMaps();
|
||||||
|
|
||||||
|
uint32_t itemId = static_cast<uint32_t>(lua_tonumber(luaState, 1));
|
||||||
|
const char *fieldName = lua_tostring(luaState, 2);
|
||||||
|
|
||||||
|
// Check for optional copy parameter
|
||||||
|
bool useCopy = false;
|
||||||
|
if (lua_isnumber(luaState, 3)) {
|
||||||
|
useCopy = static_cast<int>(lua_tonumber(luaState, 3)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get from cache
|
||||||
|
game::ItemStats_C *item = GetItemStats(itemId);
|
||||||
|
if (!item) {
|
||||||
|
lua_pushnil(luaState);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) hash table lookup for simple fields
|
||||||
|
auto simpleIt = itemStatsFieldMap.find(fieldName);
|
||||||
|
if (simpleIt != itemStatsFieldMap.end()) {
|
||||||
|
size_t i = simpleIt->second;
|
||||||
|
const char *fieldPtr = reinterpret_cast<const char *>(item) + itemStatsFields[i].offset;
|
||||||
|
|
||||||
|
switch (itemStatsFields[i].type) {
|
||||||
|
case FieldType::INT32:
|
||||||
|
lua_pushnumber(luaState, *reinterpret_cast<const int32_t *>(fieldPtr));
|
||||||
|
return 1;
|
||||||
|
case FieldType::UINT32:
|
||||||
|
lua_pushnumber(luaState, *reinterpret_cast<const uint32_t *>(fieldPtr));
|
||||||
|
return 1;
|
||||||
|
case FieldType::UINT8:
|
||||||
|
lua_pushnumber(luaState, *reinterpret_cast<const uint8_t *>(fieldPtr));
|
||||||
|
return 1;
|
||||||
|
case FieldType::FLOAT:
|
||||||
|
lua_pushnumber(luaState, *reinterpret_cast<const float *>(fieldPtr));
|
||||||
|
return 1;
|
||||||
|
case FieldType::STRING: {
|
||||||
|
const char *str = *reinterpret_cast<const char *const *>(fieldPtr);
|
||||||
|
lua_pushstring(luaState, str ? const_cast<char *>(str) : const_cast<char *>(""));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// O(1) hash table lookup for array fields
|
||||||
|
auto arrayIt = itemStatsArrayFieldMap.find(fieldName);
|
||||||
|
if (arrayIt != itemStatsArrayFieldMap.end()) {
|
||||||
|
size_t i = arrayIt->second;
|
||||||
|
const auto &field = itemStatsArrayFields[i];
|
||||||
|
|
||||||
|
// Create new table or get reusable table based on copy parameter
|
||||||
|
if (useCopy) {
|
||||||
|
lua_newtable(luaState);
|
||||||
|
} else {
|
||||||
|
// Get or create reusable table for this specific field name
|
||||||
|
GetTableRef(luaState, itemStatsArrayFieldRefs[fieldName]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *fieldPtr = reinterpret_cast<const char *>(item) + field.offset;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < field.count; ++j) {
|
||||||
|
lua_pushnumber(luaState, j + 1);
|
||||||
|
|
||||||
|
switch (field.type) {
|
||||||
|
case FieldType::INT32:
|
||||||
|
lua_pushnumber(luaState, reinterpret_cast<const int32_t *>(fieldPtr)[j]);
|
||||||
|
break;
|
||||||
|
case FieldType::UINT32:
|
||||||
|
lua_pushnumber(luaState, reinterpret_cast<const uint32_t *>(fieldPtr)[j]);
|
||||||
|
break;
|
||||||
|
case FieldType::UINT8:
|
||||||
|
lua_pushnumber(luaState, reinterpret_cast<const uint8_t *>(fieldPtr)[j]);
|
||||||
|
break;
|
||||||
|
case FieldType::FLOAT:
|
||||||
|
lua_pushnumber(luaState, reinterpret_cast<const float *>(fieldPtr)[j]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lua_pushnumber(luaState, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lua_settable(luaState, -3);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for special string fields
|
||||||
|
if (strcmp(fieldName, "displayName") == 0) {
|
||||||
|
lua_pushstring(luaState,
|
||||||
|
item->m_displayName[0] ? item->m_displayName[0] : const_cast<char *>(""));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(fieldName, "description") == 0) {
|
||||||
|
lua_pushstring(luaState, item->m_description ? item->m_description : const_cast<char *>(""));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Field not found
|
||||||
|
lua_error(luaState, "Unknown field name");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// won't do anything unless you uncomment line in process queues
|
||||||
|
uint32_t Script_StartItemExport(uintptr_t *luaState) {
|
||||||
|
StartItemExport();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Script_GetAmmo(uintptr_t *luaState) {
|
uint32_t Script_GetAmmo(uintptr_t *luaState) {
|
||||||
luaState = GetLuaStatePtr();
|
luaState = GetLuaStatePtr();
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,10 @@
|
|||||||
#include "main.hpp"
|
#include "main.hpp"
|
||||||
|
|
||||||
namespace Nampower {
|
namespace Nampower {
|
||||||
|
uint32_t Script_GetItemLevel(uintptr_t *luaState);
|
||||||
|
uint32_t Script_GetItemStats(uintptr_t *luaState);
|
||||||
|
uint32_t Script_GetItemStatsField(uintptr_t *luaState);
|
||||||
|
uint32_t Script_StartItemExport(uintptr_t *luaState);
|
||||||
uint32_t Script_FindPlayerItemSlot(uintptr_t *luaState);
|
uint32_t Script_FindPlayerItemSlot(uintptr_t *luaState);
|
||||||
uint32_t Script_UseItemIdOrName(uintptr_t *luaState);
|
uint32_t Script_UseItemIdOrName(uintptr_t *luaState);
|
||||||
uint32_t Script_UseTrinket(uintptr_t *luaState);
|
uint32_t Script_UseTrinket(uintptr_t *luaState);
|
||||||
|
|||||||
+1
-1
@@ -460,7 +460,7 @@ namespace Nampower {
|
|||||||
json << " \"id\": " << itemId << ",\n";
|
json << " \"id\": " << itemId << ",\n";
|
||||||
json << " \"class\": " << item->m_class << ",\n";
|
json << " \"class\": " << item->m_class << ",\n";
|
||||||
json << " \"subclass\": " << item->m_subclass << ",\n";
|
json << " \"subclass\": " << item->m_subclass << ",\n";
|
||||||
json << " \"displayName\": " << escapeJsonString(item->m_displayName[0]) << ",\n";
|
json << " \"displayName\": " << escapeJsonString(item->m_displayName[0] ? item->m_displayName[0] : const_cast<char *>("")) << ",\n";
|
||||||
json << " \"displayInfoID\": " << item->m_displayInfoID << ",\n";
|
json << " \"displayInfoID\": " << item->m_displayInfoID << ",\n";
|
||||||
json << " \"quality\": " << item->m_quality << ",\n";
|
json << " \"quality\": " << item->m_quality << ",\n";
|
||||||
json << " \"flags\": " << static_cast<int>(item->m_flags) << ",\n";
|
json << " \"flags\": " << static_cast<int>(item->m_flags) << ",\n";
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ namespace Nampower {
|
|||||||
|
|
||||||
constexpr uint32_t MAJOR_VERSION = 2;
|
constexpr uint32_t MAJOR_VERSION = 2;
|
||||||
constexpr uint32_t MINOR_VERSION = 38;
|
constexpr uint32_t MINOR_VERSION = 38;
|
||||||
constexpr uint32_t PATCH_VERSION = 0;
|
constexpr uint32_t PATCH_VERSION = 1;
|
||||||
|
|
||||||
constexpr int32_t LUA_REGISTRYINDEX = -10000;
|
constexpr int32_t LUA_REGISTRYINDEX = -10000;
|
||||||
constexpr int32_t LUA_GLOBALSINDEX = -10001;
|
constexpr int32_t LUA_GLOBALSINDEX = -10001;
|
||||||
|
|||||||
@@ -33,15 +33,12 @@ namespace Nampower {
|
|||||||
|
|
||||||
// Reusable table references to reduce memory allocations
|
// Reusable table references to reduce memory allocations
|
||||||
static int castInfoTableRef = LUA_REFNIL;
|
static int castInfoTableRef = LUA_REFNIL;
|
||||||
static int itemStatsTableRef = LUA_REFNIL;
|
|
||||||
static int unitDataTableRef = LUA_REFNIL;
|
static int unitDataTableRef = LUA_REFNIL;
|
||||||
|
|
||||||
// Maps to store separate references for each array field name (for Field functions)
|
// Maps to store separate references for each array field name (for Field functions)
|
||||||
static std::unordered_map<std::string, int> itemStatsArrayFieldRefs;
|
|
||||||
static std::unordered_map<std::string, int> unitFieldsArrayFieldRefs;
|
static std::unordered_map<std::string, int> unitFieldsArrayFieldRefs;
|
||||||
|
|
||||||
// Maps to store separate references for nested array fields (for main table functions)
|
// Maps to store separate references for nested array fields (for main table functions)
|
||||||
static std::unordered_map<std::string, int> itemStatsNestedArrayRefs;
|
|
||||||
static std::unordered_map<std::string, int> unitFieldsNestedArrayRefs;
|
static std::unordered_map<std::string, int> unitFieldsNestedArrayRefs;
|
||||||
|
|
||||||
uint32_t Script_GetCurrentCastingInfo(uintptr_t *luaState) {
|
uint32_t Script_GetCurrentCastingInfo(uintptr_t *luaState) {
|
||||||
@@ -181,41 +178,6 @@ namespace Nampower {
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Script_GetItemLevel(uintptr_t *luaState) {
|
|
||||||
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
|
||||||
|
|
||||||
if (lua_isnumber(luaState, 1)) {
|
|
||||||
auto const itemId = static_cast<uint32_t>(lua_tonumber(luaState, 1));
|
|
||||||
|
|
||||||
// Pointer to ItemDBCache
|
|
||||||
void *itemDbCache = reinterpret_cast<void *>(Offsets::ItemDBCache);
|
|
||||||
|
|
||||||
// Parameters for the DBCache<>::GetRecord function
|
|
||||||
int **param2 = nullptr;
|
|
||||||
int *param3 = nullptr;
|
|
||||||
int *param4 = nullptr;
|
|
||||||
char param5 = 0;
|
|
||||||
|
|
||||||
// Call the DBCache<>::GetRecord function
|
|
||||||
auto getRecord = reinterpret_cast<uintptr_t *(__thiscall *)(void *, uint32_t, int **, int *, int *, char)>(
|
|
||||||
Offsets::DBCacheGetRecord
|
|
||||||
);
|
|
||||||
uintptr_t *itemObject = getRecord(itemDbCache, itemId, param2, param3, param4, param5);
|
|
||||||
if (itemObject == nullptr) {
|
|
||||||
lua_error(luaState, "Item not found in DBCache");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t itemLevel = *reinterpret_cast<uint32_t *>(itemObject + 14);
|
|
||||||
lua_pushnumber(luaState, itemLevel);
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
lua_error(luaState, "Usage: GetItemLevel(itemId)");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Script_QueueScript(uintptr_t *luaState) {
|
uint32_t Script_QueueScript(uintptr_t *luaState) {
|
||||||
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
||||||
|
|
||||||
@@ -394,175 +356,6 @@ namespace Nampower {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Script_GetItemStats(uintptr_t *luaState) {
|
|
||||||
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
|
||||||
|
|
||||||
if (!lua_isnumber(luaState, 1)) {
|
|
||||||
lua_error(luaState, "Usage: GetItemStats(itemId, [copy])");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t itemId = static_cast<uint32_t>(lua_tonumber(luaState, 1));
|
|
||||||
|
|
||||||
// Check for optional copy parameter
|
|
||||||
bool useCopy = false;
|
|
||||||
if (lua_isnumber(luaState, 2)) {
|
|
||||||
useCopy = static_cast<int>(lua_tonumber(luaState, 2)) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get from cache
|
|
||||||
game::ItemStats_C *item = GetItemStats(itemId);
|
|
||||||
if (!item) {
|
|
||||||
lua_pushnil(luaState);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new table or get reusable table based on copy parameter
|
|
||||||
if (useCopy) {
|
|
||||||
lua_newtable(luaState);
|
|
||||||
} else {
|
|
||||||
GetTableRef(luaState, itemStatsTableRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push all simple fields using descriptors
|
|
||||||
PushFieldsToLua(luaState, item, itemStatsFields, itemStatsFieldsCount);
|
|
||||||
|
|
||||||
// Push string fields manually (require language)
|
|
||||||
auto const language = *reinterpret_cast<uint32_t *>(Offsets::Language);
|
|
||||||
PushTableValue(luaState, const_cast<char *>("displayName"),
|
|
||||||
item->m_displayName[language] ? item->m_displayName[language] : const_cast<char *>(""));
|
|
||||||
PushTableValue(luaState, const_cast<char *>("description"),
|
|
||||||
item->m_description ? item->m_description : const_cast<char *>(""));
|
|
||||||
|
|
||||||
// Push all array fields using descriptors with or without references based on copy parameter
|
|
||||||
if (useCopy) {
|
|
||||||
PushArrayFieldsToLua(luaState, item, itemStatsArrayFields, itemStatsArrayFieldsCount);
|
|
||||||
} else {
|
|
||||||
PushArrayFieldsToLuaWithRefs(luaState, item, itemStatsArrayFields, itemStatsArrayFieldsCount, itemStatsNestedArrayRefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1; // Return the table
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Script_GetItemStatsField(uintptr_t *luaState) {
|
|
||||||
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
|
||||||
|
|
||||||
if (!lua_isnumber(luaState, 1) || !lua_isstring(luaState, 2)) {
|
|
||||||
lua_error(luaState, "Usage: GetItemStatsField(itemId, fieldName, [copy])");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitializeFieldMaps();
|
|
||||||
|
|
||||||
uint32_t itemId = static_cast<uint32_t>(lua_tonumber(luaState, 1));
|
|
||||||
const char *fieldName = lua_tostring(luaState, 2);
|
|
||||||
|
|
||||||
// Check for optional copy parameter
|
|
||||||
bool useCopy = false;
|
|
||||||
if (lua_isnumber(luaState, 3)) {
|
|
||||||
useCopy = static_cast<int>(lua_tonumber(luaState, 3)) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get from cache
|
|
||||||
game::ItemStats_C *item = GetItemStats(itemId);
|
|
||||||
if (!item) {
|
|
||||||
lua_pushnil(luaState);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// O(1) hash table lookup for simple fields
|
|
||||||
auto simpleIt = itemStatsFieldMap.find(fieldName);
|
|
||||||
if (simpleIt != itemStatsFieldMap.end()) {
|
|
||||||
size_t i = simpleIt->second;
|
|
||||||
const char *fieldPtr = reinterpret_cast<const char *>(item) + itemStatsFields[i].offset;
|
|
||||||
|
|
||||||
switch (itemStatsFields[i].type) {
|
|
||||||
case FieldType::INT32:
|
|
||||||
lua_pushnumber(luaState, *reinterpret_cast<const int32_t *>(fieldPtr));
|
|
||||||
return 1;
|
|
||||||
case FieldType::UINT32:
|
|
||||||
lua_pushnumber(luaState, *reinterpret_cast<const uint32_t *>(fieldPtr));
|
|
||||||
return 1;
|
|
||||||
case FieldType::UINT8:
|
|
||||||
lua_pushnumber(luaState, *reinterpret_cast<const uint8_t *>(fieldPtr));
|
|
||||||
return 1;
|
|
||||||
case FieldType::FLOAT:
|
|
||||||
lua_pushnumber(luaState, *reinterpret_cast<const float *>(fieldPtr));
|
|
||||||
return 1;
|
|
||||||
case FieldType::STRING: {
|
|
||||||
const char *str = *reinterpret_cast<const char *const *>(fieldPtr);
|
|
||||||
lua_pushstring(luaState, str ? const_cast<char *>(str) : const_cast<char *>(""));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// O(1) hash table lookup for array fields
|
|
||||||
auto arrayIt = itemStatsArrayFieldMap.find(fieldName);
|
|
||||||
if (arrayIt != itemStatsArrayFieldMap.end()) {
|
|
||||||
size_t i = arrayIt->second;
|
|
||||||
const auto &field = itemStatsArrayFields[i];
|
|
||||||
|
|
||||||
// Create new table or get reusable table based on copy parameter
|
|
||||||
if (useCopy) {
|
|
||||||
lua_newtable(luaState);
|
|
||||||
} else {
|
|
||||||
// Get or create reusable table for this specific field name
|
|
||||||
GetTableRef(luaState, itemStatsArrayFieldRefs[fieldName]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *fieldPtr = reinterpret_cast<const char *>(item) + field.offset;
|
|
||||||
|
|
||||||
for (size_t j = 0; j < field.count; ++j) {
|
|
||||||
lua_pushnumber(luaState, j + 1);
|
|
||||||
|
|
||||||
switch (field.type) {
|
|
||||||
case FieldType::INT32:
|
|
||||||
lua_pushnumber(luaState, reinterpret_cast<const int32_t *>(fieldPtr)[j]);
|
|
||||||
break;
|
|
||||||
case FieldType::UINT32:
|
|
||||||
lua_pushnumber(luaState, reinterpret_cast<const uint32_t *>(fieldPtr)[j]);
|
|
||||||
break;
|
|
||||||
case FieldType::UINT8:
|
|
||||||
lua_pushnumber(luaState, reinterpret_cast<const uint8_t *>(fieldPtr)[j]);
|
|
||||||
break;
|
|
||||||
case FieldType::FLOAT:
|
|
||||||
lua_pushnumber(luaState, reinterpret_cast<const float *>(fieldPtr)[j]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
lua_pushnumber(luaState, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lua_settable(luaState, -3);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for special string fields
|
|
||||||
if (strcmp(fieldName, "displayName") == 0) {
|
|
||||||
auto const language = *reinterpret_cast<uint32_t *>(Offsets::Language);
|
|
||||||
lua_pushstring(luaState,
|
|
||||||
item->m_displayName[language] ? item->m_displayName[language] : const_cast<char *>(""));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (strcmp(fieldName, "description") == 0) {
|
|
||||||
lua_pushstring(luaState, item->m_description ? item->m_description : const_cast<char *>(""));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Field not found
|
|
||||||
lua_error(luaState, "Unknown field name");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// won't do anything unless you uncomment line in process queues
|
|
||||||
uint32_t Script_StartItemExport(uintptr_t *luaState) {
|
|
||||||
StartItemExport();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Script_GetUnitData(uintptr_t *luaState) {
|
uint32_t Script_GetUnitData(uintptr_t *luaState) {
|
||||||
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
luaState = GetLuaStatePtr(); // pcall leads to corrupted lua state pointer on added scripts, not sure why
|
||||||
|
|
||||||
|
|||||||
@@ -16,20 +16,12 @@ namespace Nampower {
|
|||||||
|
|
||||||
uint32_t Script_GetNampowerVersion(uintptr_t *luaState);
|
uint32_t Script_GetNampowerVersion(uintptr_t *luaState);
|
||||||
|
|
||||||
uint32_t Script_GetItemLevel(uintptr_t *luaState);
|
|
||||||
|
|
||||||
uint32_t Script_QueueScript(uintptr_t *luaState);
|
uint32_t Script_QueueScript(uintptr_t *luaState);
|
||||||
|
|
||||||
uint32_t Script_GetItemStats(uintptr_t *luaState);
|
|
||||||
|
|
||||||
uint32_t Script_GetItemStatsField(uintptr_t *luaState);
|
|
||||||
|
|
||||||
uint32_t Script_GetUnitData(uintptr_t *luaState);
|
uint32_t Script_GetUnitData(uintptr_t *luaState);
|
||||||
|
|
||||||
uint32_t Script_GetUnitField(uintptr_t *luaState);
|
uint32_t Script_GetUnitField(uintptr_t *luaState);
|
||||||
|
|
||||||
uint32_t Script_StartItemExport(uintptr_t *luaState);
|
|
||||||
|
|
||||||
bool TryDisenchant();
|
bool TryDisenchant();
|
||||||
|
|
||||||
uint32_t Script_DisenchantAll(uintptr_t *luaState);
|
uint32_t Script_DisenchantAll(uintptr_t *luaState);
|
||||||
|
|||||||
Reference in New Issue
Block a user