mirror of
https://github.com/brues-code/nampower.git
synced 2026-10-26 05:50:50 +00:00
refactor and make DisenchantAll default to ignoring soulbound
This commit is contained in:
+11
-7
@@ -930,13 +930,15 @@ Will stop channeling early on the next tick if you have queue channeling spells
|
|||||||
|
|
||||||
### Utility Functions
|
### Utility Functions
|
||||||
|
|
||||||
#### DisenchantAll(itemIdOrName) or DisenchantAll(quality)
|
#### DisenchantAll(itemIdOrName, [includeSoulbound]) or DisenchantAll(quality, [includeSoulbound])
|
||||||
Automatically disenchants items in your inventory. Can disenchant a specific item by ID/name, or all weapons and armor of a specified quality.
|
Automatically disenchants items in your inventory. Can disenchant a specific item by ID/name, or all weapons and armor of a specified quality.
|
||||||
|
|
||||||
**⚠️ WARNING ⚠️**
|
**⚠️ WARNING ⚠️**
|
||||||
**THIS FUNCTION WILL AUTOMATICALLY DISENCHANT ITEMS WITHOUT CONFIRMATION!**
|
**THIS FUNCTION WILL AUTOMATICALLY DISENCHANT ITEMS WITHOUT CONFIRMATION!**
|
||||||
- **Use at your own risk** - there is no undo for disenchanting
|
- **Use at your own risk** - there is no undo for disenchanting
|
||||||
- Only disenchants items from **player inventory bags (0-4)** - does NOT touch bank items
|
- Only disenchants items from **player inventory bags (0-4)** - does NOT touch bank items
|
||||||
|
- **Quest items are ALWAYS protected** regardless of settings
|
||||||
|
- **Soulbound items are protected by default** (can be overridden with optional parameter)
|
||||||
- Make sure you have the Disenchant spell and the items are disenchantable before using
|
- Make sure you have the Disenchant spell and the items are disenchantable before using
|
||||||
- **Always double-check your bags** before running this command
|
- **Always double-check your bags** before running this command
|
||||||
|
|
||||||
@@ -946,12 +948,14 @@ Automatically disenchants items in your inventory. Can disenchant a specific ite
|
|||||||
- `itemIdOrName` (number|string): Item ID (number) or item name (string)
|
- `itemIdOrName` (number|string): Item ID (number) or item name (string)
|
||||||
- Disenchants all copies of the specified item found in your bags
|
- Disenchants all copies of the specified item found in your bags
|
||||||
- Works on any disenchantable item type (weapons, armor, etc.)
|
- Works on any disenchantable item type (weapons, armor, etc.)
|
||||||
|
- `includeSoulbound` (number, optional): Pass any non-zero value (e.g., `1`) to include soulbound items (defaults to `0`)
|
||||||
|
|
||||||
**Mode 2: Disenchant by Quality** *(weapons and armor only)*
|
**Mode 2: Disenchant by Quality** *(weapons and armor only)*
|
||||||
- `quality` (string): Must be either:
|
- `quality` (string): Must be either:
|
||||||
- `"greens"` - Disenchants all uncommon (green) quality weapons and armor
|
- `"greens"` - Disenchants all uncommon (green) quality weapons and armor
|
||||||
- `"blues"` - Disenchants all rare (blue) quality weapons and armor
|
- `"blues"` - Disenchants all rare (blue) quality weapons and armor
|
||||||
- Only affects **weapons** (class 2) and **armor** (class 4)
|
- Only affects **weapons** (class 2) and **armor** (class 4)
|
||||||
|
- `includeSoulbound` (number, optional): Pass any non-zero value (e.g., `1`) to include soulbound items (defaults to `0`)
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
- `1` if the first disenchant succeeded
|
- `1` if the first disenchant succeeded
|
||||||
@@ -966,17 +970,17 @@ Automatically disenchants items in your inventory. Can disenchant a specific ite
|
|||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
```lua
|
```lua
|
||||||
-- Disenchant all green weapons and armor in your bags
|
-- Disenchant all green weapons and armor in your bags (excluding soulbound)
|
||||||
DisenchantAll("greens")
|
DisenchantAll("greens")
|
||||||
|
|
||||||
-- Disenchant all blue weapons and armor in your bags
|
-- Disenchant all blue weapons and armor including soulbound items
|
||||||
DisenchantAll("blues")
|
DisenchantAll("blues", 1)
|
||||||
|
|
||||||
-- Disenchant a specific item by ID
|
-- Disenchant a specific item by ID (excluding soulbound)
|
||||||
DisenchantAll(12345)
|
DisenchantAll(12345)
|
||||||
|
|
||||||
-- Disenchant a specific item by name
|
-- Disenchant a specific item by name including soulbound items
|
||||||
DisenchantAll("Glowing Brightwood Staff")
|
DisenchantAll("Glowing Brightwood Staff", 1)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important Notes:**
|
**Important Notes:**
|
||||||
|
|||||||
+8690
-8687
File diff suppressed because it is too large
Load Diff
+14
-1
@@ -217,7 +217,7 @@ namespace Nampower {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerItemSearchResult FindPlayerDisenchantItem(int32_t quality) {
|
PlayerItemSearchResult FindPlayerDisenchantItem(int32_t quality, bool includeSoulbound) {
|
||||||
PlayerItemSearchResult result{};
|
PlayerItemSearchResult result{};
|
||||||
|
|
||||||
auto const getBagItem = reinterpret_cast<CGBag_C_GetItemAtSlotT>(Offsets::CGBag_C_GetItemAtSlot);
|
auto const getBagItem = reinterpret_cast<CGBag_C_GetItemAtSlotT>(Offsets::CGBag_C_GetItemAtSlot);
|
||||||
@@ -231,6 +231,9 @@ namespace Nampower {
|
|||||||
|
|
||||||
auto inventory = game::GetPlayerInventoryPtr(playerUnit);
|
auto inventory = game::GetPlayerInventoryPtr(playerUnit);
|
||||||
|
|
||||||
|
auto const itemIsQuestOrSoulbound = reinterpret_cast<CGItem_C_ItemIsQuestOrSoulboundT>(
|
||||||
|
Offsets::CGItem_C_ItemIsQuestOrSoulbound);
|
||||||
|
|
||||||
auto matchesItem = [&](game::CGItem_C *item) {
|
auto matchesItem = [&](game::CGItem_C *item) {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return false;
|
return false;
|
||||||
@@ -242,6 +245,16 @@ namespace Nampower {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always skip quest items (check by class or startQuestID)
|
||||||
|
if (itemStats->m_class == game::ITEM_CLASS_QUEST || itemStats->m_startQuestID > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip soulbound items only if includeSoulbound is false
|
||||||
|
if (!includeSoulbound && itemIsQuestOrSoulbound(item)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if item is weapon or armor
|
// Check if item is weapon or armor
|
||||||
if (itemStats->m_class != game::ITEM_CLASS_WEAPON &&
|
if (itemStats->m_class != game::ITEM_CLASS_WEAPON &&
|
||||||
itemStats->m_class != game::ITEM_CLASS_ARMOR) {
|
itemStats->m_class != game::ITEM_CLASS_ARMOR) {
|
||||||
|
|||||||
+2
-1
@@ -13,6 +13,7 @@ namespace Nampower {
|
|||||||
using DBCache_ItemCacheDBGetRowT = uint32_t * (__thiscall *)(void *this_ptr, uint32_t itemId, uint64_t *guid, TooltipItemStatsCallbackT callback, uintptr_t *userData, bool requestIfMissing);
|
using DBCache_ItemCacheDBGetRowT = uint32_t * (__thiscall *)(void *this_ptr, uint32_t itemId, uint64_t *guid, TooltipItemStatsCallbackT callback, uintptr_t *userData, bool requestIfMissing);
|
||||||
|
|
||||||
using GetInventoryArtT = char * (__fastcall *)(uint32_t displayId);
|
using GetInventoryArtT = char * (__fastcall *)(uint32_t displayId);
|
||||||
|
using CGItem_C_ItemIsQuestOrSoulboundT = uint32_t (__fastcall *)(game::CGItem_C *item);
|
||||||
|
|
||||||
constexpr int32_t EQUIPPED_BAG_INDEX = -3;
|
constexpr int32_t EQUIPPED_BAG_INDEX = -3;
|
||||||
constexpr int32_t BANK_BAG_INDEX = -1;
|
constexpr int32_t BANK_BAG_INDEX = -1;
|
||||||
@@ -100,7 +101,7 @@ namespace Nampower {
|
|||||||
void CacheItemNameToId(const char *itemName, uint32_t itemId);
|
void CacheItemNameToId(const char *itemName, uint32_t itemId);
|
||||||
bool DoesItemMatch(uint32_t itemId, uint32_t searchItemId, const char *searchItemName);
|
bool DoesItemMatch(uint32_t itemId, uint32_t searchItemId, const char *searchItemName);
|
||||||
PlayerItemSearchResult FindPlayerItem(uint32_t searchItemId, const char *searchItemName);
|
PlayerItemSearchResult FindPlayerItem(uint32_t searchItemId, const char *searchItemName);
|
||||||
PlayerItemSearchResult FindPlayerDisenchantItem(int32_t quality);
|
PlayerItemSearchResult FindPlayerDisenchantItem(int32_t quality, bool includeSoulbound = false);
|
||||||
uintptr_t *GetBagPtrFromContainer(uintptr_t *containerPtr);
|
uintptr_t *GetBagPtrFromContainer(uintptr_t *containerPtr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ namespace Nampower {
|
|||||||
|
|
||||||
uint32_t gDisenchantItemId = 0;
|
uint32_t gDisenchantItemId = 0;
|
||||||
int32_t gDisenchantQuality = -1; // -1 = unset
|
int32_t gDisenchantQuality = -1; // -1 = unset
|
||||||
|
bool gDisenchantIncludeSoulbound = false;
|
||||||
uint32_t gNextDisenchantTimeMs = 0;
|
uint32_t gNextDisenchantTimeMs = 0;
|
||||||
|
|
||||||
bool gForceQueueCast;
|
bool gForceQueueCast;
|
||||||
@@ -370,6 +371,13 @@ namespace Nampower {
|
|||||||
gCastData.targetingSpellId = 0;
|
gCastData.targetingSpellId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResetDisenchantState() {
|
||||||
|
gDisenchantItemId = 0;
|
||||||
|
gDisenchantQuality = -1;
|
||||||
|
gDisenchantIncludeSoulbound = false;
|
||||||
|
gNextDisenchantTimeMs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void checkForStopChanneling() {
|
void checkForStopChanneling() {
|
||||||
if (gUserSettings.queueChannelingSpells && IsNonSwingSpellQueued()) {
|
if (gUserSettings.queueChannelingSpells && IsNonSwingSpellQueued()) {
|
||||||
// for channels just end channeling
|
// for channels just end channeling
|
||||||
|
|||||||
+5
-1
@@ -30,7 +30,7 @@ namespace Nampower {
|
|||||||
constexpr uint32_t BUFFER_DECREASE_FREQUENCY = 10000; // time in ms between changes to lower buffer
|
constexpr uint32_t BUFFER_DECREASE_FREQUENCY = 10000; // time in ms between changes to lower buffer
|
||||||
|
|
||||||
constexpr uint32_t MAJOR_VERSION = 2;
|
constexpr uint32_t MAJOR_VERSION = 2;
|
||||||
constexpr uint32_t MINOR_VERSION = 21;
|
constexpr uint32_t MINOR_VERSION = 22;
|
||||||
constexpr uint32_t PATCH_VERSION = 0;
|
constexpr uint32_t PATCH_VERSION = 0;
|
||||||
|
|
||||||
constexpr int32_t LUA_REGISTRYINDEX = -10000;
|
constexpr int32_t LUA_REGISTRYINDEX = -10000;
|
||||||
@@ -44,6 +44,7 @@ namespace Nampower {
|
|||||||
|
|
||||||
extern uint32_t gDisenchantItemId;
|
extern uint32_t gDisenchantItemId;
|
||||||
extern int32_t gDisenchantQuality;
|
extern int32_t gDisenchantQuality;
|
||||||
|
extern bool gDisenchantIncludeSoulbound;
|
||||||
extern uint32_t gNextDisenchantTimeMs;
|
extern uint32_t gNextDisenchantTimeMs;
|
||||||
|
|
||||||
extern bool gForceQueueCast;
|
extern bool gForceQueueCast;
|
||||||
@@ -203,6 +204,8 @@ namespace Nampower {
|
|||||||
|
|
||||||
void ClearQueuedSpells();
|
void ClearQueuedSpells();
|
||||||
|
|
||||||
|
void ResetDisenchantState();
|
||||||
|
|
||||||
bool processQueues();
|
bool processQueues();
|
||||||
|
|
||||||
uint32_t EffectiveCastEndMs();
|
uint32_t EffectiveCastEndMs();
|
||||||
@@ -213,4 +216,5 @@ namespace Nampower {
|
|||||||
|
|
||||||
void SetAttackTarget(uint64_t target);
|
void SetAttackTarget(uint64_t target);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-18
@@ -614,6 +614,7 @@ namespace Nampower {
|
|||||||
bool TryDisenchant() {
|
bool TryDisenchant() {
|
||||||
DEBUG_LOG("Trying disenchant with quality filter " << gDisenchantQuality << " itemId " << gDisenchantItemId);
|
DEBUG_LOG("Trying disenchant with quality filter " << gDisenchantQuality << " itemId " << gDisenchantItemId);
|
||||||
if (gDisenchantQuality < 0 && gDisenchantItemId == 0) {
|
if (gDisenchantQuality < 0 && gDisenchantItemId == 0) {
|
||||||
|
ResetDisenchantState();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,15 +625,13 @@ namespace Nampower {
|
|||||||
itemSearchResult = FindPlayerItem(gDisenchantItemId, nullptr);
|
itemSearchResult = FindPlayerItem(gDisenchantItemId, nullptr);
|
||||||
} else {
|
} else {
|
||||||
// Quality-based disenchanting (weapons and armor only)
|
// Quality-based disenchanting (weapons and armor only)
|
||||||
itemSearchResult = FindPlayerDisenchantItem(gDisenchantQuality);
|
itemSearchResult = FindPlayerDisenchantItem(gDisenchantQuality, gDisenchantIncludeSoulbound);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!itemSearchResult.found()) {
|
if (!itemSearchResult.found()) {
|
||||||
// Item not found, stop disenchanting
|
// Item not found, stop disenchanting
|
||||||
DEBUG_LOG("No disenchantable item found, stopping disenchant");
|
DEBUG_LOG("No disenchantable item found, stopping disenchant");
|
||||||
gDisenchantItemId = 0;
|
ResetDisenchantState();
|
||||||
gDisenchantQuality = -1;
|
|
||||||
gNextDisenchantTimeMs = 0;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,9 +640,7 @@ namespace Nampower {
|
|||||||
if (!item || !item->object.m_obj) {
|
if (!item || !item->object.m_obj) {
|
||||||
// Invalid item, stop disenchanting
|
// Invalid item, stop disenchanting
|
||||||
DEBUG_LOG("Invalid item, stopping disenchant");
|
DEBUG_LOG("Invalid item, stopping disenchant");
|
||||||
gDisenchantItemId = 0;
|
ResetDisenchantState();
|
||||||
gDisenchantQuality = -1;
|
|
||||||
gNextDisenchantTimeMs = 0;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint64_t itemGuid = item->object.m_obj->m_guid;
|
uint64_t itemGuid = item->object.m_obj->m_guid;
|
||||||
@@ -655,9 +652,7 @@ namespace Nampower {
|
|||||||
if (!playerUnit) {
|
if (!playerUnit) {
|
||||||
// No player unit, stop disenchanting
|
// No player unit, stop disenchanting
|
||||||
DEBUG_LOG("No player unit, stopping disenchant");
|
DEBUG_LOG("No player unit, stopping disenchant");
|
||||||
gDisenchantItemId = 0;
|
ResetDisenchantState();
|
||||||
gDisenchantQuality = -1;
|
|
||||||
gNextDisenchantTimeMs = 0;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,9 +667,7 @@ namespace Nampower {
|
|||||||
if (!success) {
|
if (!success) {
|
||||||
// Cast failed, stop disenchanting
|
// Cast failed, stop disenchanting
|
||||||
DEBUG_LOG("Cast failed, stopping disenchant");
|
DEBUG_LOG("Cast failed, stopping disenchant");
|
||||||
gDisenchantItemId = 0;
|
ResetDisenchantState();
|
||||||
gDisenchantQuality = -1;
|
|
||||||
gNextDisenchantTimeMs = 0;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,9 +678,10 @@ namespace Nampower {
|
|||||||
luaState = GetLuaStatePtr();
|
luaState = GetLuaStatePtr();
|
||||||
|
|
||||||
if (!lua_isnumber(luaState, 1) && !lua_isstring(luaState, 1)) {
|
if (!lua_isnumber(luaState, 1) && !lua_isstring(luaState, 1)) {
|
||||||
lua_error(luaState, "Usage: DisenchantAll(itemIdOrName) or DisenchantAll(quality)\n"
|
lua_error(luaState, "Usage: DisenchantAll(itemIdOrName, [includeSoulbound]) or DisenchantAll(quality, [includeSoulbound])\n"
|
||||||
"quality: \"greens\" for uncommon, \"blues\" for rare\n"
|
"quality: \"greens\" for uncommon, \"blues\" for rare\n"
|
||||||
"itemIdOrName: item ID (number) or item name (string)");
|
"itemIdOrName: item ID (number) or item name (string)\n"
|
||||||
|
"includeSoulbound: optional number - pass 1 to include soulbound items (defaults to 0)");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -707,9 +701,8 @@ namespace Nampower {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset both modes
|
// Reset all modes
|
||||||
gDisenchantItemId = 0;
|
ResetDisenchantState();
|
||||||
gDisenchantQuality = -1;
|
|
||||||
|
|
||||||
// Check number first (lua_isstring will also match numbers)
|
// Check number first (lua_isstring will also match numbers)
|
||||||
if (lua_isnumber(luaState, 1)) {
|
if (lua_isnumber(luaState, 1)) {
|
||||||
@@ -743,6 +736,12 @@ namespace Nampower {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse optional includeSoulbound parameter (defaults to false)
|
||||||
|
// Any non-zero integer enables it
|
||||||
|
if (lua_isnumber(luaState, 2)) {
|
||||||
|
gDisenchantIncludeSoulbound = (lua_tonumber(luaState, 2) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Try the first disenchant
|
// Try the first disenchant
|
||||||
bool success = TryDisenchant();
|
bool success = TryDisenchant();
|
||||||
|
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ enum class Offsets : std::uint32_t {
|
|||||||
|
|
||||||
CGItem_C_Use = 0x005D8D00,
|
CGItem_C_Use = 0x005D8D00,
|
||||||
CGItem_C_GetInventoryArt = 0x005D88B0,
|
CGItem_C_GetInventoryArt = 0x005D88B0,
|
||||||
|
CGItem_C_ItemIsQuestOrSoulbound = 0x005DA2C0,
|
||||||
|
|
||||||
DBCache_ItemCacheDBGetRow = 0x0055BA30,
|
DBCache_ItemCacheDBGetRow = 0x0055BA30,
|
||||||
|
|
||||||
|
|||||||
@@ -55,9 +55,7 @@ namespace Nampower {
|
|||||||
// Check for Disenchant (13262) failure and stop the disenchant loop
|
// Check for Disenchant (13262) failure and stop the disenchant loop
|
||||||
if (spellId == 13262) {
|
if (spellId == 13262) {
|
||||||
DEBUG_LOG("Disenchant spell failed with result " << int(spellResult) << ", stopping disenchant loop");
|
DEBUG_LOG("Disenchant spell failed with result " << int(spellResult) << ", stopping disenchant loop");
|
||||||
gDisenchantItemId = 0;
|
ResetDisenchantState();
|
||||||
gDisenchantQuality = -1;
|
|
||||||
gNextDisenchantTimeMs = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore SPELL_FAILED_CANT_DO_THAT_YET for arcane surge gets sent all the time after success
|
// ignore SPELL_FAILED_CANT_DO_THAT_YET for arcane surge gets sent all the time after success
|
||||||
|
|||||||
Reference in New Issue
Block a user