add new texture functions, fix tooltip/description missing on spellrec

This commit is contained in:
avitasia
2026-02-02 08:49:30 -08:00
parent 701b0a3c98
commit 4e25ef66a2
12 changed files with 11081 additions and 10887 deletions
+8
View File
@@ -75,6 +75,7 @@ Related structs live in `nampower/game.hpp` (notably `SpellRec` and `ItemStats_C
- `castingTimeIndex` - `castingTimeIndex`
- `channelInterruptFlags` - `channelInterruptFlags`
- `dispel` - `dispel`
- `description` (string, defaults to current language)
- `dmgClass` - `dmgClass`
- `durationIndex` - `durationIndex`
- `equippedItemClass` - `equippedItemClass`
@@ -87,6 +88,7 @@ Related structs live in `nampower/game.hpp` (notably `SpellRec` and `ItemStats_C
- `manaCostPerlevel` - `manaCostPerlevel`
- `manaPerSecond` - `manaPerSecond`
- `manaPerSecondPerLevel` - `manaPerSecondPerLevel`
- `name` (string, defaults to current language)
- `maxAffectedTargets` - `maxAffectedTargets`
- `maxLevel` - `maxLevel`
- `maxTargetLevel` - `maxTargetLevel`
@@ -100,6 +102,7 @@ Related structs live in `nampower/game.hpp` (notably `SpellRec` and `ItemStats_C
- `procCharges` - `procCharges`
- `procFlags` - `procFlags`
- `rangeIndex` - `rangeIndex`
- `rank` (string, defaults to current language)
- `recoveryTime` - `recoveryTime`
- `requiredAuraVision` - `requiredAuraVision`
- `school` - `school`
@@ -118,8 +121,10 @@ Related structs live in `nampower/game.hpp` (notably `SpellRec` and `ItemStats_C
- `targetAuraState` - `targetAuraState`
- `targetCreatureType` - `targetCreatureType`
- `targets` - `targets`
- `tooltip` (string, defaults to current language)
### SpellRec Array Fields (alphabetical) ### SpellRec Array Fields (alphabetical)
- `description` (char* x8, one per language)
- `dmgMultiplier` - `dmgMultiplier`
- `effect` - `effect`
- `effectAmplitude` - `effectAmplitude`
@@ -139,6 +144,9 @@ Related structs live in `nampower/game.hpp` (notably `SpellRec` and `ItemStats_C
- `effectRadiusIndex` - `effectRadiusIndex`
- `effectRealPointsPerLevel` - `effectRealPointsPerLevel`
- `effectTriggerSpell` - `effectTriggerSpell`
- `name` (char* x8, one per language)
- `rank` (char* x8, one per language)
- `reagent` - `reagent`
- `reagentCount` - `reagentCount`
- `tooltip` (char* x8, one per language)
- `totem` - `totem`
+44
View File
@@ -26,6 +26,8 @@ For installation, configuration, and general usage information, see the main [RE
- [GetSpellSlotTypeIdForName](#getspellslottypeidfornamenspellname) - [GetSpellSlotTypeIdForName](#getspellslottypeidfornamenspellname)
- [GetNampowerVersion](#getnampowerversion) - [GetNampowerVersion](#getnampowerversion)
- [GetItemLevel](#getitemlevelitemid) - [GetItemLevel](#getitemlevelitemid)
- [GetItemTexture](#getitemtexturedisplayinfoid)
- [GetSpellTexture](#getspelltexturespelliconid)
- [Spell Casting and Queuing](#spell-casting-and-queuing) - [Spell Casting and Queuing](#spell-casting-and-queuing)
- [QueueSpellByName](#queuespellbynamespellname) - [QueueSpellByName](#queuespellbynamespellname)
- [CastSpellByNameNoQueue](#castspellbynamenoqueuespellname) - [CastSpellByNameNoQueue](#castspellbynamenoqueuespellname)
@@ -929,6 +931,48 @@ Examples:
should print 90 for atiesh should print 90 for atiesh
``` ```
#### GetItemTexture(displayInfoId)
Returns the texture path for an item given its display info ID. Returns nil if the texture is not found or is the question mark placeholder texture.
**Parameters:**
- `displayInfoId` (number): The item's display info ID (can be obtained from `GetItemStatsField(itemId, "displayInfoID")`)
**Returns:**
- The texture path string (e.g., "Interface\\Icons\\INV_Sword_04"), or nil if not found
**Examples:**
```lua
-- Get texture for an item
local displayInfoId = GetItemStatsField(19019, "displayInfoID")
local texture = GetItemTexture(displayInfoId)
if texture then
print("Texture: " .. texture)
else
print("No texture found")
end
```
#### GetSpellTexture(spellIconId)
Returns the texture path for a spell given its spell icon ID. Returns nil if the texture is not found or is the question mark placeholder texture.
**Parameters:**
- `spellIconId` (number): The spell's icon ID (can be obtained from `GetSpellRecField(spellId, "spellIconID")`)
**Returns:**
- The texture path string with `Interface\Icons\` prefix (e.g., "Interface\\Icons\\Spell_Frost_FrostBolt02"), or nil if not found
**Examples:**
```lua
-- Get texture for Frostbolt
local spellIconId = GetSpellRecField(116, "spellIconID")
local texture = GetSpellTexture(spellIconId)
if texture then
print("Texture: " .. texture)
else
print("No texture found")
end
```
#### ChannelStopCastingNextTick() #### ChannelStopCastingNextTick()
Will stop channeling early on the next tick if you have queue channeling spells enabled and try to cast a spell before the next tick (didn't know how to cancel channels without casting another spell). Uses your ChannelLatencyReductionPercentage to determine when to stop the channel. Will stop channeling early on the next tick if you have queue channeling spells enabled and try to cast a spell before the next tick (didn't know how to cancel channels without casting another spell). Uses your ChannelLatencyReductionPercentage to determine when to stop the channel.
+10923 -10863
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -124,7 +124,7 @@ namespace game {
auto const language = *reinterpret_cast<std::uint32_t *>(Offsets::Language); auto const language = *reinterpret_cast<std::uint32_t *>(Offsets::Language);
return spell->SpellName[language]; return spell->Name[language];
} }
std::uint64_t ClntObjMgrGetActivePlayerGuid() { std::uint64_t ClntObjMgrGetActivePlayerGuid() {
+4 -4
View File
@@ -192,13 +192,13 @@ namespace game {
unsigned int SpellIconID; unsigned int SpellIconID;
unsigned int activeIconID; unsigned int activeIconID;
unsigned int spellPriority; unsigned int spellPriority;
const char *SpellName[8]; const char *Name[8];
unsigned int SpellNameFlag; unsigned int SpellNameFlag;
unsigned int Rank[8]; const char *Rank[8];
unsigned int RankFlags; unsigned int RankFlags;
unsigned int Description[8]; const char *Description[8];
unsigned int DescriptionFlags; unsigned int DescriptionFlags;
unsigned int ToolTip[8]; const char *ToolTip[8];
unsigned int ToolTipFlags; unsigned int ToolTipFlags;
unsigned int ManaCostPercentage; unsigned int ManaCostPercentage;
unsigned int StartRecoveryCategory; unsigned int StartRecoveryCategory;
+1 -1
View File
@@ -74,7 +74,7 @@ namespace Nampower {
} }
auto const language = *reinterpret_cast<uint32_t *>(Offsets::Language); auto const language = *reinterpret_cast<uint32_t *>(Offsets::Language);
auto const actualName = reinterpret_cast<const char *>(spell->SpellName[language]); auto const actualName = reinterpret_cast<const char *>(spell->Name[language]);
if (!actualName) { if (!actualName) {
return false; return false;
} }
+6
View File
@@ -1646,6 +1646,12 @@ namespace Nampower {
char disenchantAll[] = "DisenchantAll"; char disenchantAll[] = "DisenchantAll";
RegisterLuaFunction(disenchantAll, reinterpret_cast<uintptr_t *>(Script_DisenchantAll)); RegisterLuaFunction(disenchantAll, reinterpret_cast<uintptr_t *>(Script_DisenchantAll));
char getItemTexture[] = "GetItemTexture";
RegisterLuaFunction(getItemTexture, reinterpret_cast<uintptr_t *>(Script_GetItemTexture));
char getSpellTexture[] = "GetSpellTexture";
RegisterLuaFunction(getSpellTexture, reinterpret_cast<uintptr_t *>(Script_GetSpellTexture));
} }
void load() { void load() {
+1 -1
View File
@@ -35,7 +35,7 @@ namespace Nampower {
constexpr uint32_t DISENCHANT_QUALITY_PURPLE = 0x04; // Epic constexpr uint32_t DISENCHANT_QUALITY_PURPLE = 0x04; // Epic
constexpr uint32_t MAJOR_VERSION = 2; constexpr uint32_t MAJOR_VERSION = 2;
constexpr uint32_t MINOR_VERSION = 26; constexpr uint32_t MINOR_VERSION = 27;
constexpr uint32_t PATCH_VERSION = 0; constexpr uint32_t PATCH_VERSION = 0;
constexpr int32_t LUA_REGISTRYINDEX = -10000; constexpr int32_t LUA_REGISTRYINDEX = -10000;
+59 -3
View File
@@ -660,9 +660,9 @@ namespace Nampower {
// Display which item is being disenchanted // Display which item is being disenchanted
char luaCode[256]; char luaCode[256];
snprintf(luaCode, sizeof(luaCode), snprintf(luaCode, sizeof(luaCode),
"local itemLink = GetContainerItemLink(%d, %d); " "local itemLink = GetContainerItemLink(%d, %d); "
"if itemLink then DEFAULT_CHAT_FRAME:AddMessage(\"Disenchanting \" .. itemLink .. \" move during cast to cancel.\") end", "if itemLink then DEFAULT_CHAT_FRAME:AddMessage(\"Disenchanting \" .. itemLink .. \" move during cast to cancel.\") end",
itemSearchResult.bagIndex, itemSearchResult.slot + 1); // Lua slots are 1-indexed itemSearchResult.bagIndex, itemSearchResult.slot + 1); // Lua slots are 1-indexed
LuaCall(luaCode); LuaCall(luaCode);
// Set timer for next disenchant attempt (5 seconds to allow time for inventory to update) // Set timer for next disenchant attempt (5 seconds to allow time for inventory to update)
@@ -785,4 +785,60 @@ namespace Nampower {
return 1; return 1;
} }
uint32_t Script_GetItemTexture(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: GetItemTexture(displayInfoId)");
return 0;
}
uint32_t displayInfoId = static_cast<uint32_t>(lua_tonumber(luaState, 1));
auto const getInventoryArt = reinterpret_cast<GetInventoryArtT>(Offsets::CGItem_C_GetInventoryArt);
char *texturePath = getInventoryArt(displayInfoId);
if (texturePath && texturePath[0] != '\0' && !strstr(texturePath, "QuestionMark")) {
lua_pushstring(luaState, texturePath);
} else {
lua_pushnil(luaState);
}
return 1;
}
uint32_t Script_GetSpellTexture(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: GetSpellTexture(spellIconId)");
return 0;
}
int32_t iconId = static_cast<int32_t>(lua_tonumber(luaState, 1));
int32_t maxIconId = *reinterpret_cast<int32_t *>(Offsets::SpellIconDBMaxId);
uintptr_t *iconArray = *reinterpret_cast<uintptr_t **>(Offsets::SpellIconDBArray);
if (iconId < 0 || iconId > maxIconId) {
lua_pushnil(luaState);
return 1;
}
uintptr_t iconEntry = reinterpret_cast<uintptr_t *>(iconArray)[iconId];
if (iconEntry == 0) {
lua_pushnil(luaState);
return 1;
}
char *texturePath = *reinterpret_cast<char **>(iconEntry + 4);
if (texturePath && texturePath[0] != '\0' && !strstr(texturePath, "QuestionMark")) {
lua_pushstring(luaState, texturePath);
} else {
lua_pushnil(luaState);
}
return 1;
}
} }
+4
View File
@@ -34,5 +34,9 @@ namespace Nampower {
uint32_t Script_DisenchantAll(uintptr_t *luaState); uint32_t Script_DisenchantAll(uintptr_t *luaState);
uint32_t Script_GetItemTexture(uintptr_t *luaState);
uint32_t Script_GetSpellTexture(uintptr_t *luaState);
bool RunQueuedScript(int priority); bool RunQueuedScript(int priority);
} }
+3
View File
@@ -215,6 +215,9 @@ enum class Offsets : std::uint32_t {
CGItem_C_GetInventoryArt = 0x005D88B0, CGItem_C_GetInventoryArt = 0x005D88B0,
CGItem_C_ItemIsQuestOrSoulbound = 0x005DA2C0, CGItem_C_ItemIsQuestOrSoulbound = 0x005DA2C0,
SpellIconDBMaxId = 0x00c0d7f0,
SpellIconDBArray = 0x00c0d7ec,
DBCache_ItemCacheDBGetRow = 0x0055BA30, DBCache_ItemCacheDBGetRow = 0x0055BA30,
InvalidFunctionPtrCheck = 0x0042A320, InvalidFunctionPtrCheck = 0x0042A320,
+27 -14
View File
@@ -204,7 +204,7 @@ namespace Nampower {
if (spell) { if (spell) {
auto const language = *reinterpret_cast<std::uint32_t *>(Offsets::Language); auto const language = *reinterpret_cast<std::uint32_t *>(Offsets::Language);
lua_pushstring(luaState, (char *) spell->SpellName[language]); lua_pushstring(luaState, (char *) spell->Name[language]);
lua_pushstring(luaState, (char *) spell->Rank[language]); lua_pushstring(luaState, (char *) spell->Rank[language]);
return 2; return 2;
} else { } else {
@@ -306,12 +306,17 @@ namespace Nampower {
// Push string fields manually (require language) // Push string fields manually (require language)
auto const language = *reinterpret_cast<uint32_t *>(Offsets::Language); auto const language = *reinterpret_cast<uint32_t *>(Offsets::Language);
PushTableValue(luaState, const_cast<char *>("name"), PushTableValue(luaState, const_cast<char *>("name"),
spell->SpellName[language] ? const_cast<char *>(spell->SpellName[language]) spell->Name[language] ? const_cast<char *>(spell->Name[language])
: const_cast<char *>("")); : const_cast<char *>(""));
PushTableValue(luaState, const_cast<char *>("rank"), PushTableValue(luaState, const_cast<char *>("rank"),
reinterpret_cast<const char *>(spell->Rank[language]) spell->Rank[language] ? const_cast<char *>(spell->Rank[language])
? const_cast<char *>(reinterpret_cast<const char *>(spell->Rank[language])) : const_cast<char *>(""));
: const_cast<char *>("")); PushTableValue(luaState, const_cast<char *>("description"),
spell->Description[language] ? const_cast<char *>(spell->Description[language])
: const_cast<char *>(""));
PushTableValue(luaState, const_cast<char *>("tooltip"),
spell->ToolTip[language] ? const_cast<char *>(spell->ToolTip[language])
: const_cast<char *>(""));
// Push all array fields using descriptors with or without references based on copy parameter // Push all array fields using descriptors with or without references based on copy parameter
if (useCopy) { if (useCopy) {
@@ -420,18 +425,26 @@ namespace Nampower {
return 1; return 1;
} }
// Check for special string fields // Check for special string fields (localized, need language index)
auto const language = *reinterpret_cast<uint32_t *>(Offsets::Language);
if (strcmp(fieldName, "name") == 0) { if (strcmp(fieldName, "name") == 0) {
auto const language = *reinterpret_cast<uint32_t *>(Offsets::Language); lua_pushstring(luaState, spell->Name[language] ? const_cast<char *>(spell->Name[language])
lua_pushstring(luaState, spell->SpellName[language] ? const_cast<char *>(spell->SpellName[language]) : const_cast<char *>(""));
: const_cast<char *>(""));
return 1; return 1;
} }
if (strcmp(fieldName, "rank") == 0) { if (strcmp(fieldName, "rank") == 0) {
auto const language = *reinterpret_cast<uint32_t *>(Offsets::Language); lua_pushstring(luaState, spell->Rank[language] ? const_cast<char *>(spell->Rank[language])
lua_pushstring(luaState, reinterpret_cast<const char *>(spell->Rank[language]) : const_cast<char *>(""));
? const_cast<char *>(reinterpret_cast<const char *>(spell->Rank[language])) return 1;
: const_cast<char *>("")); }
if (strcmp(fieldName, "description") == 0) {
lua_pushstring(luaState, spell->Description[language] ? const_cast<char *>(spell->Description[language])
: const_cast<char *>(""));
return 1;
}
if (strcmp(fieldName, "tooltip") == 0) {
lua_pushstring(luaState, spell->ToolTip[language] ? const_cast<char *>(spell->ToolTip[language])
: const_cast<char *>(""));
return 1; return 1;
} }