mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-10-06 14:30:01 +00:00
v1.0.4
This commit is contained in:
+116
-96
@@ -446,6 +446,120 @@ local function AB_ResolveAmmoByName(name)
|
||||
return row.itemId, row.subtype
|
||||
end
|
||||
|
||||
local function AB_GetInventoryBagSlotByContainerId(containerId)
|
||||
local toInv = _G and _G["ContainerIDToInventoryID"] or nil
|
||||
if type(toInv) == "function" then
|
||||
local invSlot = tonumber(toInv(containerId))
|
||||
if invSlot and invSlot > 0 then
|
||||
return invSlot
|
||||
end
|
||||
end
|
||||
local bag = tonumber(containerId)
|
||||
if bag and bag >= 1 and bag <= 4 then
|
||||
return bag + 19
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function AB_GetSpecialAmmoBagTargets()
|
||||
local targets = {
|
||||
arrow = {},
|
||||
bullet = {},
|
||||
}
|
||||
local getInvLink = _G and _G["GetInventoryItemLink"] or nil
|
||||
if type(getInvLink) ~= "function" then
|
||||
return targets
|
||||
end
|
||||
for bag = 1, 4 do
|
||||
local invSlot = AB_GetInventoryBagSlotByContainerId(bag)
|
||||
if invSlot then
|
||||
local bagLink = getInvLink("player", invSlot)
|
||||
local bagItemId = AB_ParseItemIdFromLink(bagLink)
|
||||
local bagRow = (MTH_DS_BagItems and bagItemId) and MTH_DS_BagItems[tonumber(bagItemId) or bagItemId] or nil
|
||||
local bagSubtype = bagRow and string.lower(tostring(bagRow.subtype or "")) or ""
|
||||
if bagSubtype == "quiver" then
|
||||
table.insert(targets.arrow, { bag = bag, invSlot = invSlot, itemId = bagItemId, subtype = bagSubtype })
|
||||
elseif bagSubtype == "ammo pouch" then
|
||||
table.insert(targets.bullet, { bag = bag, invSlot = invSlot, itemId = bagItemId, subtype = bagSubtype })
|
||||
end
|
||||
end
|
||||
end
|
||||
return targets
|
||||
end
|
||||
|
||||
local function AB_MoveAmmoStacksToSpecialBags(maxMoves)
|
||||
local getSlots = _G and _G["GetContainerNumSlots"] or nil
|
||||
local getLink = _G and _G["GetContainerItemLink"] or nil
|
||||
local pick = _G and _G["PickupContainerItem"] or nil
|
||||
local putInBag = _G and _G["PutItemInBag"] or nil
|
||||
local hasCursor = _G and _G["CursorHasItem"] or nil
|
||||
local clearCursor = _G and _G["ClearCursor"] or nil
|
||||
if type(getSlots) ~= "function" or type(getLink) ~= "function"
|
||||
or type(pick) ~= "function" or type(putInBag) ~= "function"
|
||||
or type(hasCursor) ~= "function" or type(clearCursor) ~= "function" then
|
||||
return 0
|
||||
end
|
||||
|
||||
local targets = AB_GetSpecialAmmoBagTargets()
|
||||
local arrowTargets = targets.arrow or {}
|
||||
local bulletTargets = targets.bullet or {}
|
||||
if table.getn(arrowTargets) == 0 and table.getn(bulletTargets) == 0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
local moves = 0
|
||||
local moveLimit = math.floor(tonumber(maxMoves) or 200)
|
||||
if moveLimit < 1 then moveLimit = 200 end
|
||||
local isTargetBag = {}
|
||||
for i = 1, table.getn(arrowTargets) do
|
||||
local bagId = tonumber(arrowTargets[i].bag)
|
||||
if bagId then
|
||||
isTargetBag[bagId] = true
|
||||
end
|
||||
end
|
||||
for i = 1, table.getn(bulletTargets) do
|
||||
local bagId = tonumber(bulletTargets[i].bag)
|
||||
if bagId then
|
||||
isTargetBag[bagId] = true
|
||||
end
|
||||
end
|
||||
|
||||
for sourceBag = 0, 4 do
|
||||
local isSpecialSource = isTargetBag[tonumber(sourceBag)] and true or false
|
||||
if not isSpecialSource then
|
||||
local slots = tonumber(getSlots(sourceBag)) or 0
|
||||
for sourceSlot = 1, slots do
|
||||
local link = getLink(sourceBag, sourceSlot)
|
||||
local itemId = AB_ParseItemIdFromLink(link)
|
||||
local ammoSubtype = itemId and AB_GetAmmoSubtypeByItemId(itemId) or nil
|
||||
if ammoSubtype then
|
||||
local destinationTargets = ammoSubtype == "arrow" and arrowTargets or bulletTargets
|
||||
if table.getn(destinationTargets) > 0 then
|
||||
pick(sourceBag, sourceSlot)
|
||||
if hasCursor() then
|
||||
for i = 1, table.getn(destinationTargets) do
|
||||
putInBag(destinationTargets[i].invSlot)
|
||||
if not hasCursor() then
|
||||
moves = moves + 1
|
||||
break
|
||||
end
|
||||
end
|
||||
if hasCursor() then
|
||||
clearCursor()
|
||||
end
|
||||
if moves >= moveLimit then
|
||||
return moves
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return moves
|
||||
end
|
||||
|
||||
local function AB_DefaultRule()
|
||||
return {
|
||||
enabled = false,
|
||||
@@ -475,16 +589,6 @@ local function AB_EnsureRuleList(bucket)
|
||||
return bucket
|
||||
end
|
||||
|
||||
local function AB_Log(message, severity)
|
||||
if type(MTH_Log) == "function" then
|
||||
MTH_Log("[AutoBuy] " .. tostring(message or ""), severity)
|
||||
end
|
||||
end
|
||||
|
||||
local function AB_Trace(message)
|
||||
return
|
||||
end
|
||||
|
||||
function Engine:GetConfigStore()
|
||||
if MTH and MTH.GetModuleSavedVariables then
|
||||
local store = MTH:GetModuleSavedVariables("autobuy")
|
||||
@@ -501,9 +605,6 @@ function Engine:EnsureDefaults()
|
||||
if store.enabled == nil then
|
||||
store.enabled = true
|
||||
end
|
||||
if store.debug == nil then
|
||||
store.debug = false
|
||||
end
|
||||
if type(store.food) ~= "table" then
|
||||
store.food = {}
|
||||
end
|
||||
@@ -607,30 +708,8 @@ function Engine:IsEnabled()
|
||||
return store.enabled and true or false
|
||||
end
|
||||
|
||||
function Engine:IsDebugEnabled()
|
||||
local store = self:EnsureDefaults()
|
||||
return store.debug and true or false
|
||||
end
|
||||
|
||||
function Engine:IsTraceEnabled()
|
||||
if self:IsDebugEnabled() then
|
||||
return true
|
||||
end
|
||||
if MTH and MTH.debug then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Engine:Debug(message)
|
||||
if self:IsTraceEnabled() then
|
||||
AB_Log(message, "debug")
|
||||
end
|
||||
end
|
||||
|
||||
function Engine:Init()
|
||||
self:EnsureDefaults()
|
||||
self:Debug("engine initialized")
|
||||
end
|
||||
|
||||
function Engine:ScanMerchant()
|
||||
@@ -1152,92 +1231,34 @@ end
|
||||
function Engine:OnMerchantEvent(eventName)
|
||||
if eventName == "MERCHANT_SHOW" then
|
||||
self._merchantSessionExecuted = false
|
||||
AB_Trace("merchant session reset on MERCHANT_SHOW")
|
||||
elseif eventName == "MERCHANT_UPDATE" and self._merchantSessionExecuted then
|
||||
AB_Trace("skip MERCHANT_UPDATE: session already executed")
|
||||
return
|
||||
end
|
||||
|
||||
self:Debug("OnMerchantEvent enter event=" .. tostring(eventName))
|
||||
AB_Trace("OnMerchantEvent " .. tostring(eventName))
|
||||
if not self:IsEnabled() then
|
||||
self:Debug("OnMerchantEvent abort: engine store disabled")
|
||||
local store = self:EnsureDefaults()
|
||||
AB_Trace("abort: store.enabled=" .. tostring(store and store.enabled)
|
||||
.. " projectiles.enabled=" .. tostring(store and store.projectiles and store.projectiles.enabled))
|
||||
return
|
||||
end
|
||||
|
||||
local snapshot = self:ScanMerchant()
|
||||
self:Debug("snapshot count=" .. tostring(snapshot and snapshot.count or 0))
|
||||
AB_Trace("merchant item count=" .. tostring(snapshot and snapshot.count or 0))
|
||||
local foodPlan = self:BuildFoodPlan(snapshot)
|
||||
local ammoPlan = self:BuildAmmoPlan(snapshot)
|
||||
|
||||
self:Debug(tostring(eventName) .. " merchant items=" .. tostring(snapshot.count)
|
||||
.. " foodActions=" .. tostring(table.getn(foodPlan.actions or {}))
|
||||
.. " ammoActions=" .. tostring(table.getn(ammoPlan.actions or {})))
|
||||
self:Debug("ammoPlan reason=" .. tostring(ammoPlan.reason or ""))
|
||||
AB_Trace("ammoPlan reason=" .. tostring(ammoPlan.reason or "")
|
||||
.. " actions=" .. tostring(table.getn(ammoPlan.actions or {})))
|
||||
AB_Trace("foodPlan reason=" .. tostring(foodPlan.reason or "")
|
||||
.. " actions=" .. tostring(table.getn(foodPlan.actions or {})))
|
||||
for i = 1, table.getn(foodPlan.debugLines or {}) do
|
||||
self:Debug("foodPlan " .. tostring(foodPlan.debugLines[i]))
|
||||
end
|
||||
for i = 1, table.getn(ammoPlan.debugLines or {}) do
|
||||
self:Debug("ammoPlan " .. tostring(ammoPlan.debugLines[i]))
|
||||
end
|
||||
|
||||
local totalRequestedStacks = 0
|
||||
if table.getn(foodPlan.actions or {}) > 0 then
|
||||
for i = 1, table.getn(foodPlan.actions or {}) do
|
||||
local action = foodPlan.actions[i]
|
||||
self:Debug("food action#" .. tostring(i)
|
||||
.. " idx=" .. tostring(action.index)
|
||||
.. " item=" .. tostring(action.itemId)
|
||||
.. " diet=" .. tostring(action.diet)
|
||||
.. " qtyStacks=" .. tostring(action.quantityStacks)
|
||||
.. " targetStacks=" .. tostring(action.targetStacks)
|
||||
.. " ownedStacks=" .. tostring(action.ownedStacks)
|
||||
.. " deficit=" .. tostring(action.deficit)
|
||||
.. " pets=" .. tostring(action.petCount)
|
||||
.. " families=" .. tostring(action.familyCount))
|
||||
end
|
||||
local _, requestedStacks = self:ExecutePlan(foodPlan)
|
||||
totalRequestedStacks = totalRequestedStacks + requestedStacks
|
||||
AB_Trace("executed food requestedStacks=" .. tostring(requestedStacks))
|
||||
if requestedStacks > 0 then
|
||||
AB_AnnouncePurchases(foodPlan.actions)
|
||||
end
|
||||
else
|
||||
self:Debug("no food actions to execute")
|
||||
AB_Trace("no food actions to execute")
|
||||
end
|
||||
|
||||
if table.getn(ammoPlan.actions or {}) > 0 then
|
||||
for i = 1, table.getn(ammoPlan.actions or {}) do
|
||||
local action = ammoPlan.actions[i]
|
||||
self:Debug("action#" .. tostring(i)
|
||||
.. " idx=" .. tostring(action.index)
|
||||
.. " item=" .. tostring(action.itemId)
|
||||
.. " qtyStacks=" .. tostring(action.quantityStacks)
|
||||
.. " qtyItems=" .. tostring(action.quantityItems)
|
||||
.. " desiredStacks=" .. tostring(action.desiredStacks)
|
||||
.. " ownedStacks=" .. tostring(action.ownedStacks)
|
||||
.. " deficit=" .. tostring(action.deficit)
|
||||
.. " stackCount=" .. tostring(action.stackCount))
|
||||
end
|
||||
local executedActions, requestedStacks = self:ExecutePlan(ammoPlan)
|
||||
local _, requestedStacks = self:ExecutePlan(ammoPlan)
|
||||
totalRequestedStacks = totalRequestedStacks + requestedStacks
|
||||
AB_Trace("executed actions=" .. tostring(executedActions) .. " requestedStacks=" .. tostring(requestedStacks))
|
||||
if requestedStacks > 0 then
|
||||
AB_MoveAmmoStacksToSpecialBags(300)
|
||||
AB_AnnouncePurchases(ammoPlan.actions)
|
||||
end
|
||||
self:Debug("executed ammo actions=" .. tostring(table.getn(ammoPlan.actions or {})))
|
||||
else
|
||||
self:Debug("no ammo actions to execute")
|
||||
AB_Trace("no actions to execute")
|
||||
end
|
||||
|
||||
if totalRequestedStacks > 0 then
|
||||
@@ -1247,7 +1268,6 @@ end
|
||||
|
||||
function Engine:OnMerchantClosed()
|
||||
self._merchantSessionExecuted = false
|
||||
AB_Trace("merchant session reset on MERCHANT_CLOSED")
|
||||
end
|
||||
|
||||
function MTH_AutoBuy_GetMerchantSnapshot()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
local MTH_AutoBuy = {
|
||||
name = "autobuy",
|
||||
enabled = false,
|
||||
version = "1.0.3",
|
||||
version = "1.0.4",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"MERCHANT_SHOW",
|
||||
|
||||
@@ -47,6 +47,13 @@ function MTH_ChronometerHunterInstallData(engine)
|
||||
engine:AddTimer(engine.EVENT, BS["Piercing Shot"], 8, 1, 0, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\Ability_Hunter_DisarmingShot" })
|
||||
engine:AddTimer(engine.EVENT, BS["Quick Shots"], 12, 0, 1, 1, { a = 1, cr = "MAROON", tx = "Interface\\Icons\\Ability_Hunter_Quickshot" })
|
||||
engine:AddTimer(engine.EVENT, BS["Scorpid Poison"], 10, 1, 0, 0, { gr = 3, cr = "PURPLE", a = 1, dn = 1 })
|
||||
engine:AddTimer(engine.EVENT, BS["Devilsaur Fury"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Devilsaur Eye"], tx = "Interface\\Icons\\Ability_Hunter_Pet_Raptor" })
|
||||
engine:AddTimer(engine.EVENT, BS["Restless Strength"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", xn = BS["Zandalarian Hero Medallion"], tx = "Interface\\Icons\\INV_Jewelry_Necklace_13" })
|
||||
engine:AddTimer(engine.EVENT, BS["Earthstrike"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\Spell_Nature_AbolishMagic" })
|
||||
engine:AddTimer(engine.EVENT, BS["Badge of the Swarmguard"], 30, 0, 1, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\INV_Misc_AhnQirajTrinket_04" })
|
||||
engine:AddTimer(engine.EVENT, BS["Jom Gabbar"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\Ability_Poisons" })
|
||||
engine:AddTimer(engine.EVENT, BS["Kiss of the Spider"], 15, 0, 1, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\INV_Trinket_Naxxramas04" })
|
||||
engine:AddTimer(engine.EVENT, BS["Slayer's Crest"], 20, 0, 1, 1, { a = 1, cr = "PURPLE", tx = "Interface\\Icons\\INV_Trinket_Naxxramas03" })
|
||||
end
|
||||
|
||||
local _, race = UnitRace("player")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
local MTH_ChronometerModule = {
|
||||
name = "chronometer",
|
||||
enabled = true,
|
||||
version = "1.0.3",
|
||||
version = "1.0.4",
|
||||
events = {},
|
||||
initialized = false,
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
FOM_VERSION = "11200.2";
|
||||
------------------------------------------------------
|
||||
|
||||
-- TODO: if you don't auto-feed, have an option to make the need to feed more noticeable (e.g., pulsing halo around the pet-happiness icon).
|
||||
|
||||
-- constants
|
||||
FOM_WARNING_INTERVAL = 10; -- don't warn more than once per this many seconds
|
||||
MAX_QUALITY = 35 * 60 + 1; -- We store a notion of a food's "quality": its best happiness-per-tick multiplied by the pet's level as of when that tick occurred. We use "best" because a pet that's closer to "sated" (maximum happiness) will receive less happiness per tick than he would from the same food if he were hungrier. (So, a food that gives 35 happiness per tick to a level 60 pet is "better" than a food that's worth 35 happiness per tick to a level 30 pet.) Foods whose quality hasn't been observed yet are given this value when sorting, so we can prioritize the discovery of new foods' quality ratings.
|
||||
@@ -366,9 +364,7 @@ function MTH_GetMerchantFoodsByDiet()
|
||||
end
|
||||
|
||||
local function FOM_DebugLog(message)
|
||||
if (type(MTH_Log) == "function") then
|
||||
MTH_Log("[FeedOMatic] " .. tostring(message or ""), "debug");
|
||||
end
|
||||
return;
|
||||
end
|
||||
|
||||
local function FOM_DebugLogMerchantFoods(sourceEvent)
|
||||
@@ -1551,8 +1547,10 @@ function FOM_CheckHappiness()
|
||||
else
|
||||
msg = FOM_PET_VERY_HUNGRY;
|
||||
end
|
||||
GFWUtils.Print(string.format(msg, pet));
|
||||
GFWUtils.Note(string.format(msg, pet));
|
||||
if (not (MTH and MTH.IsMessageEnabled) or MTH:IsMessageEnabled("petHungry", false)) then
|
||||
GFWUtils.Print(string.format(msg, pet));
|
||||
GFWUtils.Note(string.format(msg, pet));
|
||||
end
|
||||
end
|
||||
FOM_PlayHungrySound();
|
||||
FOM_LastWarning = GetTime();
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
local MTH_FeedOMatic = {
|
||||
name = "feedomatic",
|
||||
enabled = false,
|
||||
version = "1.0.3",
|
||||
version = "1.0.4",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"MERCHANT_SHOW",
|
||||
|
||||
+146
-44
@@ -15,7 +15,10 @@ local function MTHSmartAmmo_IsSmartEnabled()
|
||||
return moduleStore.smartEnabled and true or false
|
||||
end
|
||||
local saved = MTHSmartAmmo_GetSaved()
|
||||
return saved["enabled"]
|
||||
if saved["enabled"] == nil then
|
||||
return true
|
||||
end
|
||||
return saved["enabled"] and true or false
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_IsReloadEnabled()
|
||||
@@ -30,6 +33,18 @@ local function MTHSmartAmmo_IsReloadEnabled()
|
||||
return saved["reload"] and true or false
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_IsWeaponSwapEnabled()
|
||||
local moduleStore = MTHSmartAmmo_GetModuleStore()
|
||||
if type(moduleStore) == "table" and moduleStore.weaponSwapEnabled ~= nil then
|
||||
return moduleStore.weaponSwapEnabled and true or false
|
||||
end
|
||||
local saved = MTHSmartAmmo_GetSaved()
|
||||
if saved["weaponSwap"] == nil then
|
||||
return true
|
||||
end
|
||||
return saved["weaponSwap"] and true or false
|
||||
end
|
||||
|
||||
local MTHSmartAmmo_InitializeHooks
|
||||
MTHSmartAmmo_EnsureHooks = nil
|
||||
|
||||
@@ -83,8 +98,24 @@ function MTHSmartAmmo_GetReloadEnabled()
|
||||
return MTHSmartAmmo_IsReloadEnabled() and true or false
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_Log(msg)
|
||||
return
|
||||
function MTHSmartAmmo_SetWeaponSwapEnabled(enabled, silent)
|
||||
local saved = MTHSmartAmmo_GetSaved()
|
||||
if enabled then
|
||||
saved["weaponSwap"] = 1
|
||||
else
|
||||
saved["weaponSwap"] = false
|
||||
end
|
||||
local moduleStore = MTHSmartAmmo_GetModuleStore()
|
||||
if type(moduleStore) == "table" then
|
||||
moduleStore.weaponSwapEnabled = enabled and true or false
|
||||
end
|
||||
if not silent and DEFAULT_CHAT_FRAME then
|
||||
MTH_SA_Print("Smart Ammo weapon-swap auto-equip " .. (enabled and "Enabled." or "Disabled."))
|
||||
end
|
||||
end
|
||||
|
||||
function MTHSmartAmmo_GetWeaponSwapEnabled()
|
||||
return MTHSmartAmmo_IsWeaponSwapEnabled() and true or false
|
||||
end
|
||||
|
||||
local MTHSmartAmmo_CastSpell_Hook
|
||||
@@ -142,6 +173,10 @@ MTH_SA_Quantity = 0
|
||||
MTH_SA_LastFallbackAttempt = 0
|
||||
MTH_SA_LastKnownEquippedName = nil
|
||||
MTH_SA_LastFallbackNotice = { key = nil, time = 0 }
|
||||
MTH_SA_LastKnownWeaponAmmoType = nil
|
||||
MTH_SA_LastWeaponCheck = 0
|
||||
MTH_SA_StartupProtectUntil = (GetTime() or 0) + 2.0
|
||||
MTH_SA_StartupPrimed = nil
|
||||
|
||||
local function MTHSmartAmmo_RefreshAmmoButtonDisplay()
|
||||
local createButtons = getglobal("zButtonAmmo_CreateButtons")
|
||||
@@ -211,6 +246,10 @@ local function MTHSmartAmmo_HandleFallbackResult(previousAmmo)
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_TryFallbackEquip(reason)
|
||||
local now = GetTime() or 0
|
||||
if now < (MTH_SA_StartupProtectUntil or 0) then
|
||||
return
|
||||
end
|
||||
if not MTH_SA_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
@@ -224,20 +263,107 @@ local function MTHSmartAmmo_TryFallbackEquip(reason)
|
||||
return
|
||||
end
|
||||
|
||||
local now = GetTime() or 0
|
||||
now = GetTime() or 0
|
||||
if MTH_SA_LastFallbackAttempt and (now - MTH_SA_LastFallbackAttempt) < 0.5 then
|
||||
return
|
||||
end
|
||||
MTH_SA_LastFallbackAttempt = now
|
||||
local previousAmmo = MTH_SA_GetEquippedAmmoName() or MTH_SA_LastKnownEquippedName
|
||||
|
||||
MTHSmartAmmo_Log("Fallback equip attempt reason=" .. tostring(reason or "unknown"))
|
||||
if MTH_SA_Check() or MTH_SA_FindAmmo() then
|
||||
MTH_SA_EquipAmmo()
|
||||
MTHSmartAmmo_HandleFallbackResult(previousAmmo)
|
||||
end
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_FindBestAmmoForType(ammoType)
|
||||
if not ammoType then
|
||||
return nil
|
||||
end
|
||||
local rankMap = (ammoType == "Bullets" and MTH_AMMO_BULLET_RANK) or MTH_AMMO_ARROW_RANK or {}
|
||||
local best = nil
|
||||
for bag = 4, 0, -1 do
|
||||
for slot = GetContainerNumSlots(bag), 1, -1 do
|
||||
local itemName = MTH_SA_GetContainerItemName(bag, slot)
|
||||
if itemName then
|
||||
local value = rankMap[itemName]
|
||||
if value and (not best or value > best.value) then
|
||||
best = {
|
||||
name = itemName,
|
||||
value = value,
|
||||
bag = bag,
|
||||
slot = slot,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return best
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_EquipAmmoFromSlot(bag, slot)
|
||||
if not bag or not slot then
|
||||
return false
|
||||
end
|
||||
PickupContainerItem(bag, slot)
|
||||
if CursorHasItem and CursorHasItem() then
|
||||
EquipCursorItem(0)
|
||||
end
|
||||
if CursorHasItem and CursorHasItem() then
|
||||
if ClearCursor then
|
||||
ClearCursor()
|
||||
end
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_HandleWeaponSwapAutoEquip(reason)
|
||||
local now = GetTime() or 0
|
||||
if now < (MTH_SA_StartupProtectUntil or 0) then
|
||||
return
|
||||
end
|
||||
if not MTH_SA_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
if not MTHSmartAmmo_IsWeaponSwapEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local weaponAmmoType = MTH_SA_GetEquippedWeaponAmmoType()
|
||||
if not weaponAmmoType then
|
||||
MTH_SA_LastKnownWeaponAmmoType = nil
|
||||
MTH_SA_StartupPrimed = true
|
||||
return
|
||||
end
|
||||
|
||||
if not MTH_SA_StartupPrimed then
|
||||
MTH_SA_LastKnownWeaponAmmoType = weaponAmmoType
|
||||
MTH_SA_StartupPrimed = true
|
||||
return
|
||||
end
|
||||
|
||||
if MTH_SA_LastKnownWeaponAmmoType == weaponAmmoType then
|
||||
return
|
||||
end
|
||||
MTH_SA_LastKnownWeaponAmmoType = weaponAmmoType
|
||||
|
||||
local bestAmmo = MTHSmartAmmo_FindBestAmmoForType(weaponAmmoType)
|
||||
if not bestAmmo then
|
||||
return
|
||||
end
|
||||
|
||||
local equippedNow = MTH_SA_GetEquippedAmmoName()
|
||||
if equippedNow and equippedNow == bestAmmo.name then
|
||||
return
|
||||
end
|
||||
|
||||
if MTHSmartAmmo_EquipAmmoFromSlot(bestAmmo.bag, bestAmmo.slot) then
|
||||
MTH_SA_LastKnownEquippedName = bestAmmo.name
|
||||
MTHSmartAmmo_RefreshAmmoButtonDisplay()
|
||||
end
|
||||
end
|
||||
|
||||
local frame = CreateFrame("Frame")
|
||||
frame:RegisterEvent("START_AUTOREPEAT_SPELL")
|
||||
frame:RegisterEvent("STOP_AUTOREPEAT_SPELL")
|
||||
@@ -245,6 +371,7 @@ frame:RegisterEvent("SPELLCAST_INTERRUPTED")
|
||||
frame:RegisterEvent("SPELLCAST_FAILED")
|
||||
frame:RegisterEvent("SPELLCAST_STOP")
|
||||
frame:RegisterEvent("SPELLCAST_DELAYED")
|
||||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
|
||||
|
||||
frame:SetScript("OnEvent", function()
|
||||
@@ -252,28 +379,28 @@ frame:SetScript("OnEvent", function()
|
||||
if MTHSmartAmmo_EnsureHooks then
|
||||
MTHSmartAmmo_EnsureHooks("EVENT:START_AUTOREPEAT_SPELL")
|
||||
end
|
||||
local castHook, actionHook, byNameHook = MTHSmartAmmo_AreHooksInstalled()
|
||||
MTHSmartAmmo_Log("EVENT START_AUTOREPEAT_SPELL smart=" .. tostring(MTHSmartAmmo_IsSmartEnabled()) .. " module=" .. tostring(MTH_SA_IsModuleEnabled()) .. " hooks=" .. tostring(castHook) .. "/" .. tostring(actionHook) .. "/" .. tostring(byNameHook))
|
||||
MTH_SA_AutoShot = 1
|
||||
MTHSmartAmmo_TryFallbackEquip("START_AUTOREPEAT_SPELL")
|
||||
elseif event == "STOP_AUTOREPEAT_SPELL" then
|
||||
MTHSmartAmmo_Log("EVENT STOP_AUTOREPEAT_SPELL")
|
||||
MTH_SA_AutoShot = nil
|
||||
|
||||
elseif event == "PLAYER_ENTERING_WORLD" then
|
||||
local now = GetTime() or 0
|
||||
MTH_SA_StartupProtectUntil = now + 2.0
|
||||
MTH_SA_StartupPrimed = nil
|
||||
MTH_SA_LastKnownWeaponAmmoType = MTH_SA_GetEquippedWeaponAmmoType()
|
||||
MTH_SA_LastKnownEquippedName = MTH_SA_GetEquippedAmmoName()
|
||||
MTH_SA_LastWeaponCheck = now
|
||||
|
||||
elseif event == "SPELLCAST_START" then
|
||||
--DEFAULT_CHAT_FRAME:AddMessage("SPELLCAST_START ", 0, 1, 1)
|
||||
|
||||
elseif event == "SPELLCAST_STOP" or event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED" or event == "SPELLCAST_DELAYED" then
|
||||
local castHook, actionHook, byNameHook = MTHSmartAmmo_AreHooksInstalled()
|
||||
MTHSmartAmmo_Log("EVENT " .. tostring(event) .. " waitJunk=" .. tostring(MTH_SA_IsWaitingSwapJunk) .. " waitGood=" .. tostring(MTH_SA_IsWaitingSwapGood) .. " lastSpell=" .. tostring(MTH_SA_LastSpell) .. " smart=" .. tostring(MTHSmartAmmo_IsSmartEnabled()) .. " module=" .. tostring(MTH_SA_IsModuleEnabled()) .. " hooks=" .. tostring(castHook) .. "/" .. tostring(actionHook) .. "/" .. tostring(byNameHook))
|
||||
if MTH_SA_IsWaitingSwapJunk then
|
||||
MTHSmartAmmo_Log("EVENT swap request -> JUNK equipped=" .. tostring(MTH_SA_GetEquippedAmmoName()) .. " current=" .. tostring(MTH_SA.curname))
|
||||
MTH_SA_EquipAmmo(1)
|
||||
elseif MTH_SA_IsWaitingSwapGood then
|
||||
MTHSmartAmmo_Log("EVENT swap request -> GOOD equipped=" .. tostring(MTH_SA_GetEquippedAmmoName()) .. " current=" .. tostring(MTH_SA.curname))
|
||||
MTH_SA_EquipAmmo()
|
||||
end
|
||||
MTHSmartAmmo_Log("EVENT clear pending flags")
|
||||
MTH_SA_IsWaitingSwapJunk = nil
|
||||
MTH_SA_IsWaitingSwapGood = nil
|
||||
MTH_SA_LastSpell = nil
|
||||
@@ -298,19 +425,21 @@ frame:SetScript("OnUpdate", function(self, elapsed)
|
||||
end
|
||||
|
||||
if MTH_SA_AmmoLastSwitch and (GetTime()-MTH_SA_AmmoLastSwitch > 0.5) and (MTH_SA_IsWaitingSwapJunk or MTH_SA_IsWaitingSwapGood) then
|
||||
MTHSmartAmmo_Log("OnUpdate pending swap elapsed>0.5 equipped=" .. tostring(MTH_SA_GetEquippedAmmoName()) .. " waitJunk=" .. tostring(MTH_SA_IsWaitingSwapJunk) .. " waitGood=" .. tostring(MTH_SA_IsWaitingSwapGood))
|
||||
if MTH_SA_IsWaitingSwapJunk then
|
||||
MTHSmartAmmo_Log("OnUpdate swap request -> JUNK")
|
||||
MTH_SA_EquipAmmo(1)
|
||||
elseif MTH_SA_IsWaitingSwapGood then
|
||||
MTHSmartAmmo_Log("OnUpdate swap request -> GOOD")
|
||||
MTH_SA_EquipAmmo()
|
||||
end
|
||||
MTHSmartAmmo_Log("OnUpdate clear pending flags")
|
||||
MTH_SA_IsWaitingSwapJunk = nil
|
||||
MTH_SA_IsWaitingSwapGood = nil
|
||||
MTH_SA_LastSpell = nil
|
||||
end
|
||||
|
||||
local now = GetTime() or 0
|
||||
if (now - (MTH_SA_LastWeaponCheck or 0)) >= 0.25 then
|
||||
MTH_SA_LastWeaponCheck = now
|
||||
MTHSmartAmmo_HandleWeaponSwapAutoEquip("OnUpdate-weapon-check")
|
||||
end
|
||||
end)
|
||||
|
||||
function MTH_SA_CountEquippedAmmo()
|
||||
@@ -358,12 +487,9 @@ function MTH_SA_GetContainerItemName(bag, slot)
|
||||
end
|
||||
|
||||
function MTH_SA_EquipAmmo(junk)
|
||||
MTHSmartAmmo_Log("EquipAmmo enter junk=" .. tostring(junk) .. " equipped=" .. tostring(MTH_SA_GetEquippedAmmoName()) .. " cur=" .. tostring(MTH_SA.curname) .. " junk=" .. tostring(MTH_SA.junkname))
|
||||
|
||||
if not MTH_SA_AmmoLastSwitch then MTH_SA_AmmoLastSwitch = GetTime() end
|
||||
|
||||
if not (MTH_SA_Check() or MTH_SA_FindAmmo()) then
|
||||
MTHSmartAmmo_Log("EquipAmmo abort: cache invalid and FindAmmo failed")
|
||||
return
|
||||
end
|
||||
local bag, slot
|
||||
@@ -377,15 +503,12 @@ function MTH_SA_EquipAmmo(junk)
|
||||
|
||||
if MTH_SA_GetEquippedAmmoName() ~= MTH_SA.curname and GetTime()-MTH_SA_AmmoLastSwitch > 0.5 then
|
||||
if not MTH_SA_FindAmmo() then
|
||||
MTHSmartAmmo_Log("EquipAmmo abort: AMMO NOT FOUND during junk swap")
|
||||
return
|
||||
end
|
||||
end
|
||||
bag, slot = MTH_SA.junkbag, MTH_SA.junkslot
|
||||
MTHSmartAmmo_Log("Swap GOOD->JUNK bag=" .. tostring(bag) .. " slot=" .. tostring(slot) .. " cur=" .. tostring(MTH_SA.curname) .. " curSlot=" .. tostring(MTH_SA.curslot) .. " junk=" .. tostring(MTH_SA.junkname) .. " junkSlot=" .. tostring(MTH_SA.junkslot))
|
||||
else
|
||||
bag, slot = MTH_SA.curbag, MTH_SA.curslot
|
||||
MTHSmartAmmo_Log("Swap JUNK->GOOD bag=" .. tostring(bag) .. " slot=" .. tostring(slot) .. " cur=" .. tostring(MTH_SA.curname) .. " curSlot=" .. tostring(MTH_SA.curslot) .. " junk=" .. tostring(MTH_SA.junkname) .. " junkSlot=" .. tostring(MTH_SA.junkslot))
|
||||
end
|
||||
|
||||
|
||||
@@ -393,7 +516,6 @@ function MTH_SA_EquipAmmo(junk)
|
||||
--UseContainerItem(bag, slot)
|
||||
PickupContainerItem(bag,slot)
|
||||
EquipCursorItem(0)
|
||||
MTHSmartAmmo_Log("EquipCursorItem applied bag=" .. tostring(bag) .. " slot=" .. tostring(slot))
|
||||
if junk then
|
||||
MTH_SA_IsWaitingSwapJunk = nil
|
||||
MTH_SA_IsWaitingSwapGood = 1
|
||||
@@ -401,7 +523,6 @@ function MTH_SA_EquipAmmo(junk)
|
||||
MTH_SA_IsWaitingSwapJunk = nil
|
||||
MTH_SA_IsWaitingSwapGood = nil
|
||||
end
|
||||
MTHSmartAmmo_Log("Pending flags set waitJunk=" .. tostring(MTH_SA_IsWaitingSwapJunk) .. " waitGood=" .. tostring(MTH_SA_IsWaitingSwapGood))
|
||||
--PickupInventoryItem(0)
|
||||
--AutoEquipCursorItem()
|
||||
--EquipCursorItem(0)
|
||||
@@ -410,20 +531,16 @@ function MTH_SA_EquipAmmo(junk)
|
||||
end
|
||||
|
||||
function MTH_SA_FindAmmo()
|
||||
MTHSmartAmmo_Log("FindAmmo start")
|
||||
MTH_SA = {}
|
||||
MTH_SA_List = {}
|
||||
local ammotype = MTH_SA_GetEquippedWeaponAmmoType()
|
||||
if not ammotype then
|
||||
MTHSmartAmmo_Log("FindAmmo abort: no ranged weapon ammo type")
|
||||
return
|
||||
end
|
||||
local curammo = MTH_SA_GetEquippedAmmoName()
|
||||
if not curammo and not MTHSmartAmmo_IsReloadEnabled() then
|
||||
MTHSmartAmmo_Log("FindAmmo abort: no equipped ammo and reload disabled")
|
||||
return
|
||||
end
|
||||
MTHSmartAmmo_Log("FindAmmo type=" .. tostring(ammotype) .. " equipped=" .. tostring(curammo))
|
||||
local ammolist = (ammotype == "Bullets" and MTH_AMMO_BULLET_RANK) or MTH_AMMO_ARROW_RANK or {}
|
||||
MTH_SA_List = ammolist
|
||||
local item, value
|
||||
@@ -473,11 +590,9 @@ function MTH_SA_FindAmmo()
|
||||
end
|
||||
end
|
||||
if not goodvalue or junkvalue > goodvalue then
|
||||
MTHSmartAmmo_Log("FindAmmo failed: goodvalue=" .. tostring(goodvalue) .. " junkvalue=" .. tostring(junkvalue))
|
||||
MTH_SA.error = 1
|
||||
return
|
||||
end
|
||||
MTHSmartAmmo_Log("FindAmmo selected cur=" .. tostring(MTH_SA.curname) .. " junk=" .. tostring(MTH_SA.junkname) .. " curValue=" .. tostring(MTH_SA.curvalue) .. " junkValue=" .. tostring(junkvalue))
|
||||
return 1
|
||||
end
|
||||
|
||||
@@ -502,11 +617,8 @@ MTHSmartAmmo_CastSpell_Hook = function(spell, tab)
|
||||
if MTHSmartAmmo_IsSmartEnabled() then
|
||||
local name = GetSpellName(spell, tab)
|
||||
MTH_SA_LastSpell = name
|
||||
MTHSmartAmmo_Log("HOOK CastSpell name=" .. tostring(name))
|
||||
if name and MTH_AMMO_JUNKSHOT_SET and MTH_AMMO_JUNKSHOT_SET[name] then
|
||||
MTHSmartAmmo_Log("HOOK CastSpell junk-shot detected name=" .. tostring(name))
|
||||
if MTH_SA_Check() or MTH_SA_FindAmmo() then
|
||||
MTHSmartAmmo_Log("HOOK CastSpell pre-swap -> junk")
|
||||
MTH_SA_EquipAmmo(1)
|
||||
end
|
||||
end
|
||||
@@ -539,11 +651,8 @@ MTHSmartAmmo_UseAction_Hook = function(slot, checkCursor, onSelf)
|
||||
MTH_SA_Tooltip:SetAction(slot)
|
||||
local name = MTH_SA_TooltipTextLeft1:GetText()
|
||||
MTH_SA_LastSpell = name
|
||||
MTHSmartAmmo_Log("HOOK UseAction slot=" .. tostring(slot) .. " name=" .. tostring(name))
|
||||
if name and MTH_AMMO_JUNKSHOT_SET and MTH_AMMO_JUNKSHOT_SET[name] then
|
||||
MTHSmartAmmo_Log("HOOK UseAction junk-shot detected name=" .. tostring(name))
|
||||
if MTH_SA_Check() or MTH_SA_FindAmmo() then
|
||||
MTHSmartAmmo_Log("HOOK UseAction pre-swap -> junk")
|
||||
MTH_SA_EquipAmmo(1)
|
||||
end
|
||||
end
|
||||
@@ -573,11 +682,8 @@ MTHSmartAmmo_CastSpellByName_Hook = function(spell, onSelf)
|
||||
|
||||
local _, _, name = string.find(spell or "", "([%w%'%s]+)")
|
||||
MTH_SA_LastSpell = name
|
||||
MTHSmartAmmo_Log("HOOK CastSpellByName name=" .. tostring(name))
|
||||
if name and MTHSmartAmmo_IsSmartEnabled() and MTH_AMMO_JUNKSHOT_SET and MTH_AMMO_JUNKSHOT_SET[name] then
|
||||
MTHSmartAmmo_Log("HOOK CastSpellByName junk-shot detected name=" .. tostring(name))
|
||||
if MTH_SA_Check() or MTH_SA_FindAmmo() then
|
||||
MTHSmartAmmo_Log("HOOK CastSpellByName pre-swap -> junk")
|
||||
MTH_SA_EquipAmmo(1)
|
||||
end
|
||||
end
|
||||
@@ -598,26 +704,22 @@ end
|
||||
-- Defer hooking until after tables are initialized
|
||||
MTHSmartAmmo_InitializeHooks = function()
|
||||
if not MTH_SA_IsModuleEnabled() then
|
||||
MTHSmartAmmo_Log("InitializeHooks skip: module disabled")
|
||||
return
|
||||
end
|
||||
|
||||
if CastSpell ~= MTHSmartAmmo_CastSpell_Hook then
|
||||
MTH_SA_CastSpell = CastSpell
|
||||
CastSpell = MTHSmartAmmo_CastSpell_Hook
|
||||
MTHSmartAmmo_Log("InitializeHooks: CastSpell hook installed")
|
||||
end
|
||||
|
||||
if UseAction ~= MTHSmartAmmo_UseAction_Hook then
|
||||
MTH_SA_UseAction = UseAction
|
||||
UseAction = MTHSmartAmmo_UseAction_Hook
|
||||
MTHSmartAmmo_Log("InitializeHooks: UseAction hook installed")
|
||||
end
|
||||
|
||||
if CastSpellByName ~= MTHSmartAmmo_CastSpellByName_Hook then
|
||||
MTH_SA_CastSpellByName = CastSpellByName
|
||||
CastSpellByName = MTHSmartAmmo_CastSpellByName_Hook
|
||||
MTHSmartAmmo_Log("InitializeHooks: CastSpellByName hook installed")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ MTH_SA_MANAGED_HOOKS = true
|
||||
local MTH_SmartAmmo = {
|
||||
name = "smartammo",
|
||||
enabled = true,
|
||||
version = "1.0.3",
|
||||
version = "1.0.4",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"PLAYER_ENTERING_WORLD",
|
||||
@@ -80,6 +80,9 @@ local function MTH_SA_ApplySavedState()
|
||||
if moduleStore.reloadEnabled ~= nil then
|
||||
saved["reload"] = moduleStore.reloadEnabled and 1 or false
|
||||
end
|
||||
if moduleStore.weaponSwapEnabled ~= nil then
|
||||
saved["weaponSwap"] = moduleStore.weaponSwapEnabled and 1 or false
|
||||
end
|
||||
end
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = 1
|
||||
@@ -90,11 +93,22 @@ local function MTH_SA_ApplySavedState()
|
||||
if saved["reload"] == nil and type(moduleStore) == "table" then
|
||||
moduleStore.reloadEnabled = saved["reload"] ~= false
|
||||
end
|
||||
if saved["weaponSwap"] == nil then
|
||||
saved["weaponSwap"] = 1
|
||||
if type(moduleStore) == "table" then
|
||||
moduleStore.weaponSwapEnabled = true
|
||||
end
|
||||
elseif type(moduleStore) == "table" and moduleStore.weaponSwapEnabled == nil then
|
||||
moduleStore.weaponSwapEnabled = saved["weaponSwap"] ~= false
|
||||
end
|
||||
|
||||
MTHSmartAmmo_SetSmartEnabled(saved["enabled"] and 1 or nil, 1)
|
||||
if type(MTHSmartAmmo_SetReloadEnabled) == "function" then
|
||||
MTHSmartAmmo_SetReloadEnabled(saved["reload"] ~= false and 1 or nil, 1)
|
||||
end
|
||||
if type(MTHSmartAmmo_SetWeaponSwapEnabled) == "function" then
|
||||
MTHSmartAmmo_SetWeaponSwapEnabled(saved["weaponSwap"] ~= false and 1 or nil, 1)
|
||||
end
|
||||
if type(MTHSmartAmmo_EnsureHooks) == "function" then
|
||||
MTHSmartAmmo_EnsureHooks("module-apply")
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
local MTH_Tooltips = {
|
||||
name = "tooltips",
|
||||
enabled = true,
|
||||
version = "1.0.3",
|
||||
version = "1.0.4",
|
||||
events = {
|
||||
"UPDATE_MOUSEOVER_UNIT",
|
||||
"UNIT_NAME_UPDATE",
|
||||
|
||||
@@ -64,6 +64,8 @@ local function ZHunterMod_EnsureButtonFrame(buttonName)
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
||||
elseif buttonName == "zButtonTrap" then
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", 60, 0)
|
||||
elseif buttonName == "zButtonRanged" then
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", 120, 0)
|
||||
elseif buttonName == "zButtonPet" then
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", 0, 60)
|
||||
elseif buttonName == "zButtonMounts" then
|
||||
@@ -86,6 +88,7 @@ function ZHunterMod_DeferredInit()
|
||||
local aspect = ZHunterMod_EnsureButtonFrame("zButtonAspect")
|
||||
local track = ZHunterMod_EnsureButtonFrame("zButtonTrack")
|
||||
local trap = ZHunterMod_EnsureButtonFrame("zButtonTrap")
|
||||
local ranged = ZHunterMod_EnsureButtonFrame("zButtonRanged")
|
||||
local ammo = ZHunterMod_EnsureButtonFrame("zButtonAmmo")
|
||||
local mounts = ZHunterMod_EnsureButtonFrame("zButtonMounts")
|
||||
local companions = ZHunterMod_EnsureButtonFrame("zButtonCompanions")
|
||||
@@ -95,6 +98,7 @@ function ZHunterMod_DeferredInit()
|
||||
ZHunterMod_LogDeferred("DeferredInit: Aspect=" .. tostring(aspect ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Track=" .. tostring(track ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Trap=" .. tostring(trap ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Ranged=" .. tostring(ranged ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Ammo=" .. tostring(ammo ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Mounts=" .. tostring(mounts ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Companions=" .. tostring(companions ~= nil))
|
||||
@@ -106,6 +110,7 @@ function ZHunterMod_DeferredInit()
|
||||
if not aspect then table.insert(missing, "Aspect") end
|
||||
if not track then table.insert(missing, "Track") end
|
||||
if not trap then table.insert(missing, "Trap") end
|
||||
if not ranged then table.insert(missing, "Ranged") end
|
||||
if not ammo then table.insert(missing, "Ammo") end
|
||||
if not mounts then table.insert(missing, "Mounts") end
|
||||
if not companions then table.insert(missing, "Companions") end
|
||||
@@ -115,7 +120,7 @@ function ZHunterMod_DeferredInit()
|
||||
MTH_ZH_Print("[ZHUNTER] Warning: missing frames: " .. table.concat(missing, ", ") .. ". Continuing with available buttons.", "error")
|
||||
end
|
||||
|
||||
if not (pet or aspect or track or trap or ammo or mounts or companions or toys) then
|
||||
if not (pet or aspect or track or trap or ranged or ammo or mounts or companions or toys) then
|
||||
MTH_ZH_Print("zhunter buttons not created - check for addon conflicts!", "error")
|
||||
return
|
||||
end
|
||||
@@ -159,6 +164,12 @@ function ZHunterMod_DeferredInit()
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if ranged and zButtonRanged_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(ranged, zButtonRanged_OnEvent, "zButtonRanged") then
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if ammo and zButtonAmmo_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(ammo, zButtonAmmo_OnEvent, "zButtonAmmo") then
|
||||
|
||||
@@ -189,11 +189,17 @@ function ZSpellButton_SetSize(parent, size, setChildren)
|
||||
local button
|
||||
for i=1, parent.count do
|
||||
button = getglobal(parent.name..i)
|
||||
button:SetHeight(size)
|
||||
button:SetWidth(size)
|
||||
button.background:SetWidth(size * bgscale)
|
||||
button.background:SetHeight(size * bgscale)
|
||||
button.cooldown:SetModelScale(size * cdscale)
|
||||
if button then
|
||||
button:SetHeight(size)
|
||||
button:SetWidth(size)
|
||||
if button.background then
|
||||
button.background:SetWidth(size * bgscale)
|
||||
button.background:SetHeight(size * bgscale)
|
||||
end
|
||||
if button.cooldown then
|
||||
button.cooldown:SetModelScale(size * cdscale)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local cscale = 100/36
|
||||
@@ -208,16 +214,22 @@ function ZSpellButton_SetSize(parent, size, setChildren)
|
||||
end
|
||||
parent:SetHeight(size)
|
||||
parent:SetWidth(size)
|
||||
parent.background:SetWidth(size * bgscale)
|
||||
parent.background:SetHeight(size * bgscale)
|
||||
parent.cooldown:SetModelScale(size * cdscale)
|
||||
parent.circle:SetWidth(size * cscale)
|
||||
parent.circle:SetHeight(size * cscale)
|
||||
parent.circle:SetPoint("CENTER", size * cxscale, size * cyscale)
|
||||
if circleVisible then
|
||||
parent.circle:Show()
|
||||
else
|
||||
parent.circle:Hide()
|
||||
if parent.background then
|
||||
parent.background:SetWidth(size * bgscale)
|
||||
parent.background:SetHeight(size * bgscale)
|
||||
end
|
||||
if parent.cooldown then
|
||||
parent.cooldown:SetModelScale(size * cdscale)
|
||||
end
|
||||
if parent.circle then
|
||||
parent.circle:SetWidth(size * cscale)
|
||||
parent.circle:SetHeight(size * cscale)
|
||||
parent.circle:SetPoint("CENTER", size * cxscale, size * cyscale)
|
||||
if circleVisible then
|
||||
parent.circle:Show()
|
||||
else
|
||||
parent.circle:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -253,6 +265,13 @@ end
|
||||
|
||||
function ZSpellButton_CreateChildren(parent, name, count)
|
||||
if not (parent and name and count) then return end
|
||||
if parent.children and parent.count and parent.name == name then
|
||||
parent.count = count
|
||||
if type(ZSpellButton_ApplyChildrenExpanded) == "function" then
|
||||
ZSpellButton_ApplyChildrenExpanded(parent)
|
||||
end
|
||||
return
|
||||
end
|
||||
parent.children = CreateFrame("Frame", parent:GetName().."Children", UIParent)
|
||||
parent.count = count
|
||||
parent.name = name
|
||||
@@ -309,6 +328,7 @@ function ZSpellButton_GetChildrenExpanded(parent)
|
||||
return expanded
|
||||
end
|
||||
|
||||
|
||||
function ZSpellButton_SetChildrenExpanded(parent, expanded)
|
||||
if not (parent and parent.name) then
|
||||
return
|
||||
@@ -322,11 +342,31 @@ function ZSpellButton_SetChildrenExpanded(parent, expanded)
|
||||
if parent.children then
|
||||
parent.children:Show()
|
||||
end
|
||||
if parent.count then
|
||||
for i = 1, parent.count do
|
||||
local child = getglobal(parent.name .. i)
|
||||
if child then
|
||||
if child.id then
|
||||
child:Show()
|
||||
else
|
||||
child:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
saved["children"]["expanded"] = 0
|
||||
if parent.children then
|
||||
parent.children:Hide()
|
||||
end
|
||||
if parent.count then
|
||||
for i = 1, parent.count do
|
||||
local child = getglobal(parent.name .. i)
|
||||
if child then
|
||||
child:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -334,11 +374,7 @@ function ZSpellButton_ApplyChildrenExpanded(parent)
|
||||
if not (parent and parent.children) then
|
||||
return
|
||||
end
|
||||
if ZSpellButton_GetChildrenExpanded(parent) then
|
||||
parent.children:Show()
|
||||
else
|
||||
parent.children:Hide()
|
||||
end
|
||||
ZSpellButton_SetChildrenExpanded(parent, ZSpellButton_GetChildrenExpanded(parent))
|
||||
end
|
||||
|
||||
function ZSpellButton_OnEnter()
|
||||
|
||||
@@ -16,6 +16,7 @@ Loads all zhunter addon code and wraps it in the MTH module system
|
||||
<Include file="zButtonAspect.xml"/>
|
||||
<Include file="zButtonTrack.xml"/>
|
||||
<Include file="zButtonTrap.xml"/>
|
||||
<Include file="zButtonRanged.xml"/>
|
||||
<Include file="zButtonAmmo.xml"/>
|
||||
<Include file="zButtonPet.xml"/>
|
||||
<Include file="zButtonMounts.xml"/>
|
||||
@@ -34,6 +35,8 @@ Loads all zhunter addon code and wraps it in the MTH module system
|
||||
<Include file="zButtonTrack.lua"/>
|
||||
|
||||
<Include file="zButtonTrap.lua"/>
|
||||
|
||||
<Include file="zButtonRanged.lua"/>
|
||||
|
||||
<Include file="zButtonAmmo.lua"/>
|
||||
|
||||
|
||||
+35
-13
@@ -8,7 +8,7 @@ MTH_ZH_MANAGED_HOOKS = true
|
||||
local MTH_ZHunter = {
|
||||
name = "zhunter",
|
||||
enabled = true,
|
||||
version = "1.0.3",
|
||||
version = "1.0.4",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"PLAYER_ENTERING_WORLD",
|
||||
@@ -18,6 +18,7 @@ local MTH_ZHunter = {
|
||||
aspect = true,
|
||||
tracking = true,
|
||||
traps = true,
|
||||
ranged = true,
|
||||
ammo = true,
|
||||
pet = true,
|
||||
}
|
||||
@@ -60,6 +61,7 @@ local function MTH_ZH_ApplyDefaultWidgetSpawnLayoutOnce()
|
||||
"zButtonAmmo",
|
||||
"zButtonTrack",
|
||||
"zButtonTrap",
|
||||
"zButtonRanged",
|
||||
"zButtonPet",
|
||||
"zButtonMounts",
|
||||
"zButtonCompanions",
|
||||
@@ -195,6 +197,7 @@ MTH_ZH_SetButtonsVisible = function(visible)
|
||||
"zButtonAspect",
|
||||
"zButtonTrack",
|
||||
"zButtonTrap",
|
||||
"zButtonRanged",
|
||||
"zButtonAmmo",
|
||||
"zButtonPet",
|
||||
"zButtonMounts",
|
||||
@@ -207,13 +210,34 @@ MTH_ZH_SetButtonsVisible = function(visible)
|
||||
return
|
||||
end
|
||||
|
||||
local showChildren = false
|
||||
if show then
|
||||
if type(ZSpellButton_GetChildrenExpanded) == "function" then
|
||||
showChildren = ZSpellButton_GetChildrenExpanded(parentButton)
|
||||
else
|
||||
showChildren = true
|
||||
if not show then
|
||||
if parentButton.children then
|
||||
parentButton.children:Hide()
|
||||
end
|
||||
|
||||
if not parentButton.count then
|
||||
return
|
||||
end
|
||||
|
||||
local hideBaseName = parentButton.name or parentName
|
||||
if not hideBaseName then
|
||||
return
|
||||
end
|
||||
|
||||
for index = 1, parentButton.count do
|
||||
local child = getglobal(hideBaseName .. index)
|
||||
if child then
|
||||
child:Hide()
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local showChildren = false
|
||||
if type(ZSpellButton_GetChildrenExpanded) == "function" then
|
||||
showChildren = ZSpellButton_GetChildrenExpanded(parentButton)
|
||||
else
|
||||
showChildren = true
|
||||
end
|
||||
|
||||
if parentButton.children then
|
||||
@@ -233,17 +257,15 @@ MTH_ZH_SetButtonsVisible = function(visible)
|
||||
return
|
||||
end
|
||||
|
||||
for index = 1, parentButton.count do
|
||||
local child = getglobal(baseName .. index)
|
||||
if child then
|
||||
if showChildren then
|
||||
if showChildren then
|
||||
for index = 1, parentButton.count do
|
||||
local child = getglobal(baseName .. index)
|
||||
if child then
|
||||
if child.id then
|
||||
child:Show()
|
||||
else
|
||||
child:Hide()
|
||||
end
|
||||
else
|
||||
child:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+46
-156
@@ -22,13 +22,13 @@ if not root["zButtonAmmo"] then
|
||||
root["zButtonAmmo"]["children"]["hideonclick"] = 1
|
||||
root["zButtonAmmo"]["showammoname"] = 1
|
||||
root["zButtonAmmo"]["lastEquipped"] = nil
|
||||
root["zButtonAmmo"]["debug"] = false
|
||||
end
|
||||
|
||||
ZHunterMod_Ammo_Buttons = nil
|
||||
|
||||
local ZHUNTER_AMMO_MAX_COUNT = math.max(table.getn(MTH_AMMO_ARROWS or {}), table.getn(MTH_AMMO_BULLETS or {}))
|
||||
local zButtonAmmo_Cache = {}
|
||||
local zButtonAmmo_LastCacheSignature = nil
|
||||
|
||||
local function zButtonAmmo_GetSaved()
|
||||
local currentRoot = zButtonAmmo_GetRoot()
|
||||
@@ -257,6 +257,17 @@ local function zButtonAmmo_AssignButtonFromAmmoInfo(button, ammoInfo)
|
||||
return true
|
||||
end
|
||||
|
||||
local function zButtonAmmo_GetCacheSignature()
|
||||
local names = {}
|
||||
for ammoName, ammoInfo in pairs(zButtonAmmo_Cache or {}) do
|
||||
if ammoName and ammoInfo and (tonumber(ammoInfo.count) or 0) > 0 then
|
||||
table.insert(names, tostring(ammoName))
|
||||
end
|
||||
end
|
||||
table.sort(names)
|
||||
return table.concat(names, "|")
|
||||
end
|
||||
|
||||
local function zButtonAmmo_GetEquippedAmmoInfo()
|
||||
local ammoLink = zButtonAmmo_GetEquippedAmmoLink()
|
||||
if not ammoLink then
|
||||
@@ -350,6 +361,26 @@ end
|
||||
|
||||
function zButtonAmmo_SetButtons(parent, ammoList)
|
||||
zButtonAmmo_RebuildCache()
|
||||
local previousByName = {}
|
||||
for i = 1, parent.count do
|
||||
local previous = getglobal(parent.name .. i)
|
||||
if previous and previous.ammoname and not previous.isspell then
|
||||
previousByName[previous.ammoname] = {
|
||||
ammo = previous.ammoname,
|
||||
brol = previous.ammobrol,
|
||||
quality = previous.ammoqual,
|
||||
lvl = previous.ammolvl,
|
||||
type = previous.ammotype,
|
||||
bag = nil,
|
||||
slot = nil,
|
||||
id = previous.ammoid or previous.id,
|
||||
link = previous.ammolink,
|
||||
icon = previous.icon,
|
||||
count = 0,
|
||||
equip = nil,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, parent.count do
|
||||
local button = getglobal(parent.name .. i)
|
||||
@@ -375,21 +406,12 @@ function zButtonAmmo_SetButtons(parent, ammoList)
|
||||
end
|
||||
local ammoName = ammoList[i]
|
||||
local ammoInfo = ammoName and zButtonAmmo_Cache[ammoName] or nil
|
||||
if not ammoInfo and ammoName then
|
||||
ammoInfo = previousByName[ammoName]
|
||||
end
|
||||
if ammoInfo then
|
||||
local button = getglobal(parent.name .. count)
|
||||
button.id = ammoInfo.id
|
||||
button.icon = ammoInfo.icon
|
||||
button.isspell = nil
|
||||
button.ammoname = ammoInfo.ammo
|
||||
button.ammobrol = ammoInfo.brol
|
||||
button.ammoqual = ammoInfo.quality
|
||||
button.ammolvl = ammoInfo.lvl
|
||||
button.ammotype = ammoInfo.type
|
||||
button.ammobag = ammoInfo.bag
|
||||
button.ammoslot = ammoInfo.slot
|
||||
button.ammoid = ammoInfo.id
|
||||
button.ammolink = ammoInfo.link
|
||||
button.ammocount = ammoInfo.count
|
||||
zButtonAmmo_AssignButtonFromAmmoInfo(button, ammoInfo)
|
||||
zButtonAmmo_UpdateButton(button)
|
||||
button:Show()
|
||||
|
||||
@@ -439,6 +461,7 @@ function zButtonAmmo_SetButtons(parent, ammoList)
|
||||
else
|
||||
parent:Show()
|
||||
end
|
||||
zButtonAmmo_LastCacheSignature = zButtonAmmo_GetCacheSignature()
|
||||
return count - 1
|
||||
end
|
||||
|
||||
@@ -553,21 +576,6 @@ local function zButtonAmmo_GetEquippedAmmoName()
|
||||
return ammoLink
|
||||
end
|
||||
|
||||
local function zButtonAmmo_IsDebugEnabled()
|
||||
local saved = zButtonAmmo_GetSaved()
|
||||
return saved["debug"]
|
||||
end
|
||||
|
||||
local function zButtonAmmo_LogInit(msg)
|
||||
if not zButtonAmmo_IsDebugEnabled() then
|
||||
return
|
||||
end
|
||||
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
||||
MTH_ZH_Print("[AMMO INIT] " .. tostring(msg), "debug")
|
||||
end
|
||||
MTH_ZH_Print("[AMMO INIT] " .. tostring(msg), "debug")
|
||||
end
|
||||
|
||||
local zButtonAmmo_EquipFromButton
|
||||
|
||||
local function zButtonAmmo_DeferredStartupSync()
|
||||
@@ -590,26 +598,11 @@ local function zButtonAmmo_DeferredStartupSync()
|
||||
syncFrame:SetScript("OnUpdate", nil)
|
||||
local equippedNow = zButtonAmmo_GetEquippedAmmoName()
|
||||
local saved = zButtonAmmo_GetSaved()
|
||||
zButtonAmmo_LogInit("deferred sync equippedNow=" .. tostring(equippedNow) .. " saved.lastEquipped=" .. tostring(saved and saved["lastEquipped"]))
|
||||
|
||||
zButtonAmmo_RebuildCache()
|
||||
|
||||
if equippedNow and (not saved["lastEquipped"] or saved["lastEquipped"] == "") then
|
||||
zButtonAmmo_SaveEquippedAmmo(equippedNow)
|
||||
zButtonAmmo_LogInit("deferred sync seeded lastEquipped=" .. tostring(equippedNow))
|
||||
return
|
||||
end
|
||||
|
||||
if saved["lastEquipped"] and equippedNow and saved["lastEquipped"] ~= equippedNow and zButtonAmmo_Cache[saved["lastEquipped"]] then
|
||||
local restored = false
|
||||
for i = 1, zButtonAmmo.count do
|
||||
local child = getglobal("zButtonAmmo" .. i)
|
||||
if child and child.ammoname == saved["lastEquipped"] then
|
||||
restored = zButtonAmmo_EquipFromButton(child)
|
||||
break
|
||||
end
|
||||
end
|
||||
zButtonAmmo_LogInit("deferred sync restore attempt target=" .. tostring(saved["lastEquipped"]) .. " ok=" .. tostring(restored))
|
||||
end
|
||||
end)
|
||||
end
|
||||
@@ -678,13 +671,10 @@ end
|
||||
|
||||
function zButtonAmmo_OnEvent()
|
||||
if event == "VARIABLES_LOADED" then
|
||||
zButtonAmmo_LogInit("VARIABLES_LOADED fired")
|
||||
if not zButtonAmmo then
|
||||
zButtonAmmo_LogInit("abort: zButtonAmmo frame missing")
|
||||
return
|
||||
end
|
||||
if UnitClass("player") ~= ZHUNTER_HUNTER then
|
||||
zButtonAmmo_LogInit("abort: non-hunter")
|
||||
zButtonAmmo:UnregisterAllEvents()
|
||||
zButtonAmmo:Hide()
|
||||
return
|
||||
@@ -696,13 +686,7 @@ function zButtonAmmo_OnEvent()
|
||||
zButtonAmmoAdjustment:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
||||
zButtonAmmoAdjustment:RegisterEvent("BAG_UPDATE")
|
||||
zButtonAmmoAdjustment:SetScript("OnEvent", zButtonAmmoAdjustment_OnEvent)
|
||||
if zButtonAmmo_IsDebugEnabled() then
|
||||
MTH_ZH_Print("[AMMO] zButtonAmmoAdjustment frame created and events registered", "debug")
|
||||
end
|
||||
zButtonAmmo_SetupSizeAndPosition()
|
||||
local saved = zButtonAmmo_GetSaved()
|
||||
zButtonAmmo_LogInit("post-init saved.lastEquipped=" .. tostring(saved and saved["lastEquipped"]))
|
||||
zButtonAmmo_LogInit("post-init equippedNow=" .. tostring(zButtonAmmo_GetEquippedAmmoName()))
|
||||
zButtonAmmo_DeferredStartupSync()
|
||||
end
|
||||
end
|
||||
@@ -714,9 +698,6 @@ function zButtonAmmo_SaveEquippedAmmo(ammoname)
|
||||
return
|
||||
end
|
||||
saved["lastEquipped"] = ammoname
|
||||
if zButtonAmmo_IsDebugEnabled() then
|
||||
MTH_ZH_Print("[AMMO] Saved equipped ammo to persistent storage: " .. ammoname, "debug")
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonAmmo_LoadLastEquippedAmmo()
|
||||
@@ -760,84 +741,8 @@ function zButtonAmmo_CreateButtons()
|
||||
-- Try to restore the last equipped ammo from saved variables
|
||||
local lastEquipped = zButtonAmmo_LoadLastEquippedAmmo()
|
||||
local equippedAmmoNameAtInit = zButtonAmmo_GetEquippedAmmoName()
|
||||
zButtonAmmo_LogInit("CreateButtons saved.lastEquipped=" .. tostring(lastEquipped) .. " equippedNow=" .. tostring(equippedAmmoNameAtInit))
|
||||
if lastEquipped and zButtonAmmo_Cache[lastEquipped] then
|
||||
if zButtonAmmo_IsDebugEnabled() then
|
||||
MTH_ZH_Print("[AMMO] Restoring last equipped ammo from save: " .. lastEquipped, "debug")
|
||||
end
|
||||
-- Set the parent button directly from ammo cache data
|
||||
local ammoInfo = zButtonAmmo_Cache[lastEquipped]
|
||||
zButtonAmmo.ammoname = lastEquipped
|
||||
zButtonAmmo.ammoid = ammoInfo["id"]
|
||||
zButtonAmmo.icon = ammoInfo["icon"]
|
||||
zButtonAmmo.isspell = nil
|
||||
zButtonAmmo.ammobrol = ammoInfo["brol"]
|
||||
zButtonAmmo.ammoqual = ammoInfo["quality"]
|
||||
zButtonAmmo.ammolvl = ammoInfo["lvl"]
|
||||
zButtonAmmo.ammotype = ammoInfo["type"]
|
||||
zButtonAmmo.ammobag = ammoInfo["bag"]
|
||||
zButtonAmmo.ammoslot = ammoInfo["slot"]
|
||||
zButtonAmmo.ammolink = ammoInfo["link"]
|
||||
zButtonAmmo_UpdateButton(zButtonAmmo)
|
||||
zButtonAmmo:Enable()
|
||||
|
||||
local equippedAmmoName = zButtonAmmo_GetEquippedAmmoName()
|
||||
if equippedAmmoName ~= lastEquipped then
|
||||
local restored = false
|
||||
for i = 1, zButtonAmmo.count do
|
||||
local child = getglobal("zButtonAmmo" .. i)
|
||||
if child and child.ammoname == lastEquipped then
|
||||
restored = zButtonAmmo_EquipFromButton(child)
|
||||
break
|
||||
end
|
||||
end
|
||||
if not restored then
|
||||
restored = zButtonAmmo_EquipFromButton({
|
||||
ammoname = lastEquipped,
|
||||
ammobag = ammoInfo["bag"],
|
||||
ammoslot = ammoInfo["slot"],
|
||||
ammoid = ammoInfo["id"],
|
||||
})
|
||||
end
|
||||
if restored then
|
||||
zButtonAmmo_SaveEquippedAmmo(lastEquipped)
|
||||
zButtonAmmo_LogInit("restored to saved ammo=" .. tostring(lastEquipped))
|
||||
else
|
||||
zButtonAmmo_LogInit("restore failed for saved ammo=" .. tostring(lastEquipped))
|
||||
end
|
||||
else
|
||||
zButtonAmmo_LogInit("restore skipped: equipped already matches saved")
|
||||
end
|
||||
else
|
||||
zButtonAmmo_LogInit("restore skipped: no saved lastEquipped in cache")
|
||||
if equippedAmmoNameAtInit then
|
||||
zButtonAmmo_SaveEquippedAmmo(equippedAmmoNameAtInit)
|
||||
zButtonAmmo_LogInit("seeded lastEquipped from equippedNow=" .. tostring(equippedAmmoNameAtInit))
|
||||
else
|
||||
local bestAvailable = nil
|
||||
for i = 1, table.getn(ammoList) do
|
||||
local ammoName = ammoList[i]
|
||||
if ammoName and zButtonAmmo_Cache[ammoName] then
|
||||
bestAvailable = ammoName
|
||||
end
|
||||
end
|
||||
|
||||
if bestAvailable and zButtonAmmo_Cache[bestAvailable] then
|
||||
local bestInfo = zButtonAmmo_Cache[bestAvailable]
|
||||
local equippedBest = zButtonAmmo_EquipFromButton({
|
||||
ammoname = bestAvailable,
|
||||
ammobag = bestInfo["bag"],
|
||||
ammoslot = bestInfo["slot"],
|
||||
ammoid = bestInfo["id"],
|
||||
})
|
||||
if equippedBest then
|
||||
zButtonAmmo_SaveEquippedAmmo(bestAvailable)
|
||||
zButtonAmmo_LogInit("fallback equip bestAvailable=" .. tostring(bestAvailable))
|
||||
else
|
||||
zButtonAmmo_LogInit("fallback equip failed bestAvailable=" .. tostring(bestAvailable))
|
||||
end
|
||||
end
|
||||
end
|
||||
if equippedAmmoNameAtInit then
|
||||
zButtonAmmo_SaveEquippedAmmo(equippedAmmoNameAtInit)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -890,7 +795,6 @@ function zButtonAmmo_Reset()
|
||||
saved["children"]["hideonclick"] = 1
|
||||
saved["showammoname"] = 1
|
||||
saved["lastEquipped"] = nil
|
||||
saved["debug"] = false
|
||||
end
|
||||
|
||||
function zButtonAmmoAdjustment_OnEvent()
|
||||
@@ -901,8 +805,11 @@ function zButtonAmmoAdjustment_OnEvent()
|
||||
|
||||
if event == "UNIT_INVENTORY_CHANGED" or event == "BAG_UPDATE" then
|
||||
local ammoList = zButtonAmmo_GetAmmoList()
|
||||
if ZHunterMod_Ammo_Buttons ~= ammoList then
|
||||
ZHunterMod_Ammo_Buttons = ammoList
|
||||
local listChanged = (ZHunterMod_Ammo_Buttons ~= ammoList)
|
||||
ZHunterMod_Ammo_Buttons = ammoList
|
||||
zButtonAmmo_RebuildCache()
|
||||
local cacheSignature = zButtonAmmo_GetCacheSignature()
|
||||
if listChanged or cacheSignature ~= zButtonAmmo_LastCacheSignature then
|
||||
zButtonAmmo_EnsureSpellOrder(ammoList)
|
||||
local info = {}
|
||||
local infoIndex = 1
|
||||
@@ -915,8 +822,8 @@ function zButtonAmmoAdjustment_OnEvent()
|
||||
end
|
||||
zButtonAmmo.found = ZSpellButton_SetButtons(zButtonAmmo, info)
|
||||
zButtonAmmo_SetupSizeAndPosition()
|
||||
zButtonAmmo_LastCacheSignature = zButtonAmmo_GetCacheSignature()
|
||||
end
|
||||
zButtonAmmo_RebuildCache()
|
||||
-- Update ammo counts for child buttons
|
||||
for i=1, zButtonAmmo.count do
|
||||
local button = getglobal("zButtonAmmo"..i)
|
||||
@@ -1013,25 +920,8 @@ SlashCmdList["zButtonAmmo"] = function(msg)
|
||||
zButtonAmmo:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
||||
elseif msg == "options" then
|
||||
MTH_OpenOptions("Ammo")
|
||||
elseif msg == "debug" then
|
||||
-- Manually trigger ammo rescan with debug output
|
||||
local currentAmmoList = ZHunterMod_Ammo_Buttons or zButtonAmmo_GetAmmoList()
|
||||
zButtonAmmo_EnsureSpellOrder(currentAmmoList)
|
||||
local saved = zButtonAmmo_GetSaved()
|
||||
local info = {}
|
||||
local infoIndex = 1
|
||||
for i=1, table.getn(currentAmmoList) do
|
||||
local ammoIndex = saved["spells"][i]
|
||||
if saved["visible"][ammoIndex] ~= false then
|
||||
info[infoIndex] = currentAmmoList[ammoIndex]
|
||||
infoIndex = infoIndex + 1
|
||||
end
|
||||
end
|
||||
zButtonAmmo.found = ZSpellButton_SetButtons(zButtonAmmo, info)
|
||||
zButtonAmmo_UpdateButton(zButtonAmmo)
|
||||
MTH_ZH_Print("Ammo button rescanned")
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"options\", \"reset\", \"debug\"")
|
||||
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -99,6 +99,43 @@ local function zButtonAspect_ApplyRuntimeSettings()
|
||||
zButtonAspect.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
local function zButtonAspect_IsKnownAspectSpellId(spellId)
|
||||
if not spellId then
|
||||
return false
|
||||
end
|
||||
local spellName = GetSpellName(spellId, "spell")
|
||||
if not spellName or spellName == "" then
|
||||
return false
|
||||
end
|
||||
for i = 1, table.getn(ZHunterMod_Aspect_Spells) do
|
||||
if ZHunterMod_Aspect_Spells[i] == spellName then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function zButtonAspect_EnsureValidParentId()
|
||||
if not (zButtonAspect and zButtonAspect.count) then
|
||||
return
|
||||
end
|
||||
|
||||
if zButtonAspect_IsKnownAspectSpellId(zButtonAspect.id) then
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, zButtonAspect.count do
|
||||
local child = getglobal(zButtonAspect.name .. i)
|
||||
if child and child.id and zButtonAspect_IsKnownAspectSpellId(child.id) then
|
||||
zButtonAspect.id = child.id
|
||||
zButtonAspect.isspell = 1
|
||||
ZSpellButton_UpdateButton(zButtonAspect)
|
||||
ZSpellButton_UpdateCooldown(zButtonAspect)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonAspect_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
@@ -117,6 +154,9 @@ function zButtonAspect_OnEvent()
|
||||
zButtonAspectAdjustment = CreateFrame("Frame", "zButtonAspectAdjustment")
|
||||
zButtonAspectAdjustment:RegisterEvent("PLAYER_AURAS_CHANGED")
|
||||
zButtonAspectAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonAspectAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonAspectAdjustment:RegisterEvent("CHARACTER_POINTS_CHANGED")
|
||||
zButtonAspectAdjustment:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
||||
zButtonAspectAdjustment:SetScript("OnEvent", zButtonAspectAdjustment_OnEvent)
|
||||
zButtonAspect_Tooltip = CreateFrame("GameTooltip", "zButtonAspect_Tooltip", nil, "GameTooltipTemplate")
|
||||
zButtonAspect_SetupSizeAndPosition()
|
||||
@@ -144,6 +184,7 @@ function zButtonAspect_CreateButtons()
|
||||
end
|
||||
zButtonAspect.found = ZSpellButton_SetButtons(zButtonAspect, info)
|
||||
zButtonAspect_ApplyRuntimeSettings()
|
||||
zButtonAspect_EnsureValidParentId()
|
||||
end
|
||||
|
||||
function zButtonAspect_SetupSizeAndPosition()
|
||||
@@ -193,7 +234,14 @@ function zButtonAspectAdjustment_OnEvent()
|
||||
if not zButtonAspect or not zButtonAspect.count then
|
||||
return
|
||||
end
|
||||
if event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_ENTERING_WORLD" then
|
||||
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
|
||||
zButtonAspect_CreateButtons()
|
||||
zButtonAspect_SetupSizeAndPosition()
|
||||
zButtonAspect_EnsureValidParentId()
|
||||
end
|
||||
if event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_ENTERING_WORLD"
|
||||
or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" or event == "LEARNED_SPELL_IN_TAB" then
|
||||
zButtonAspect_EnsureValidParentId()
|
||||
if not zButtonAspect1.id then
|
||||
return
|
||||
end
|
||||
|
||||
+145
-10
@@ -42,6 +42,7 @@ ZHunterMod_Pet_Spells = {
|
||||
}
|
||||
|
||||
local ZHUNTER_PET_MAX = table.getn(ZHunterMod_Pet_Spells)
|
||||
local zButtonPet_SetButtons
|
||||
|
||||
local function zButtonPet_GetSaved()
|
||||
local currentRoot = zButtonPet_GetRoot()
|
||||
@@ -147,6 +148,7 @@ function zButtonPet_OnEvent()
|
||||
zButtonPet:Hide()
|
||||
return
|
||||
end
|
||||
zButtonPet.customSetButtons = zButtonPet_SetButtons
|
||||
zButtonPet_CreateButtons()
|
||||
zButtonPet.beforeclick = zButtonPetAdjustment_BeforeClick
|
||||
zButtonPet.afterclick = zButtonPet_AfterClick
|
||||
@@ -157,6 +159,7 @@ function zButtonPet_OnEvent()
|
||||
zButtonPetAdjustment:RegisterEvent("PET_BAR_UPDATE")
|
||||
zButtonPetAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonPetAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonPetAdjustment:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
||||
zButtonPetAdjustment:SetScript("OnEvent", zButtonPetAdjustment_OnEvent)
|
||||
zButtonPet_Tooltip = CreateFrame("GameTooltip", "zButtonPet_Tooltip", nil, "GameTooltipTemplate")
|
||||
zButtonPet_SetupSizeAndPosition()
|
||||
@@ -300,17 +303,110 @@ local function zButtonPet_FindSpellIdByName(spellName)
|
||||
if not spellName or spellName == "" then
|
||||
return nil
|
||||
end
|
||||
local maxSpells = tonumber((_G and _G["MAX_SPELLS"]) or nil) or 1024
|
||||
for i = 1, maxSpells do
|
||||
local current = GetSpellName(i, "spell")
|
||||
if not current then
|
||||
break
|
||||
end
|
||||
if current == spellName then
|
||||
return i
|
||||
local lookup = {}
|
||||
local foundAny = nil
|
||||
|
||||
if type(GetNumSpellTabs) == "function" and type(GetSpellTabInfo) == "function" then
|
||||
local numTabs = GetNumSpellTabs() or 0
|
||||
for tabIndex = 1, numTabs do
|
||||
local _, _, offset, numSpells = GetSpellTabInfo(tabIndex)
|
||||
offset = tonumber(offset) or 0
|
||||
numSpells = tonumber(numSpells) or 0
|
||||
if numSpells > 0 then
|
||||
for spellIndex = (offset + 1), (offset + numSpells) do
|
||||
local spellNameAtIndex = GetSpellName(spellIndex, "spell")
|
||||
if spellNameAtIndex then
|
||||
lookup[spellNameAtIndex] = spellIndex
|
||||
foundAny = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
|
||||
if not foundAny then
|
||||
local maxSpells = tonumber((_G and _G["MAX_SPELLS"]) or nil) or 1024
|
||||
local nilStreak = 0
|
||||
for spellIndex = 1, maxSpells do
|
||||
local spellNameAtIndex = GetSpellName(spellIndex, "spell")
|
||||
if spellNameAtIndex then
|
||||
lookup[spellNameAtIndex] = spellIndex
|
||||
nilStreak = 0
|
||||
else
|
||||
nilStreak = nilStreak + 1
|
||||
if nilStreak >= 30 then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if spellName == ZHUNTER_PET_POSITION then
|
||||
if lookup[spellName] then
|
||||
return lookup[spellName]
|
||||
end
|
||||
for currentName, currentId in lookup do
|
||||
if string.find(currentName, "Take Position", 1, true)
|
||||
or string.find(currentName, "Position", 1, true)
|
||||
or string.find(currentName, "Stay", 1, true) then
|
||||
return currentId
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
return lookup[spellName]
|
||||
end
|
||||
|
||||
zButtonPet_SetButtons = function(parent, spells)
|
||||
if not (parent and parent.count and parent.name and spells) then
|
||||
return 0
|
||||
end
|
||||
|
||||
local info = {}
|
||||
for i = 1, table.getn(spells) do
|
||||
local spellName = spells[i]
|
||||
local spellId = zButtonPet_FindSpellIdByName(spellName)
|
||||
if spellId then
|
||||
table.insert(info, spellId)
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, parent.count do
|
||||
local child = getglobal(parent.name..i)
|
||||
if child then
|
||||
child:Hide()
|
||||
child.id = nil
|
||||
child.icon = nil
|
||||
child.isspell = nil
|
||||
end
|
||||
end
|
||||
|
||||
parent.id = nil
|
||||
parent.isspell = nil
|
||||
|
||||
local foundCount = 0
|
||||
for i = 1, table.getn(info) do
|
||||
if i > parent.count then
|
||||
break
|
||||
end
|
||||
local button = getglobal(parent.name..i)
|
||||
if button then
|
||||
button.id = info[i]
|
||||
button.isspell = 1
|
||||
ZSpellButton_UpdateButton(button)
|
||||
button:Show()
|
||||
if i == 1 then
|
||||
parent.id = info[i]
|
||||
parent.isspell = 1
|
||||
ZSpellButton_UpdateButton(parent)
|
||||
parent:Enable()
|
||||
end
|
||||
foundCount = foundCount + 1
|
||||
end
|
||||
end
|
||||
|
||||
return foundCount
|
||||
end
|
||||
|
||||
function zButtonPetAdjustment_BeforeClick()
|
||||
@@ -437,18 +533,57 @@ function zButtonPet_FeedPet()
|
||||
|
||||
end
|
||||
|
||||
local function zButtonPet_DebugVerify()
|
||||
if not zButtonPet then
|
||||
MTH_ZH_Print("zPet: button frame is not ready yet.")
|
||||
return
|
||||
end
|
||||
|
||||
zButtonPet_CreateButtons()
|
||||
zButtonPet_RefreshParentSpell()
|
||||
|
||||
MTH_ZH_Print("zPet verify: expected spell availability")
|
||||
for i = 1, table.getn(ZHunterMod_Pet_Spells) do
|
||||
local spellName = ZHunterMod_Pet_Spells[i]
|
||||
local spellId = zButtonPet_FindSpellIdByName(spellName)
|
||||
if spellId then
|
||||
MTH_ZH_Print(" + "..spellName.." (id "..spellId..")")
|
||||
else
|
||||
MTH_ZH_Print(" - "..spellName.." (missing)")
|
||||
end
|
||||
end
|
||||
|
||||
if zButtonPet.id then
|
||||
local parentName = GetSpellName(zButtonPet.id, "spell") or "<unknown>"
|
||||
MTH_ZH_Print("zPet parent: "..parentName.." (id "..zButtonPet.id..")")
|
||||
else
|
||||
MTH_ZH_Print("zPet parent: <none>")
|
||||
end
|
||||
|
||||
for i = 1, (zButtonPet.count or 0) do
|
||||
local button = getglobal("zButtonPet"..i)
|
||||
if button and button.id then
|
||||
local name = GetSpellName(button.id, "spell") or "<unknown>"
|
||||
MTH_ZH_Print(" slot "..i..": "..name.." (id "..button.id..")")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_zButtonPet1 = "/ZPet"
|
||||
SlashCmdList["zButtonPet"] = function(msg)
|
||||
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Pet button is disabled while module 'zhunter' is disabled.") then
|
||||
return
|
||||
end
|
||||
msg = (msg and string.lower(msg)) or ""
|
||||
if msg == "reset" then
|
||||
zButtonPet_Reset()
|
||||
zButtonPet:ClearAllPoints()
|
||||
zButtonPet:SetPoint("CENTER", UIParent, "CENTER", 0, 60)
|
||||
elseif msg == "options" then
|
||||
MTH_OpenOptions("Pet")
|
||||
elseif msg == "verify" then
|
||||
zButtonPet_DebugVerify()
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
|
||||
MTH_ZH_Print("Possible Commands: \"options\", \"reset\", \"verify\"")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,717 @@
|
||||
local function zButtonRanged_GetRoot()
|
||||
return MTH_ZH_GetSavedRoot()
|
||||
end
|
||||
|
||||
local root = zButtonRanged_GetRoot()
|
||||
if not root["zButtonRanged"] then
|
||||
root["zButtonRanged"] = {}
|
||||
root["zButtonRanged"]["spells"] = {}
|
||||
root["zButtonRanged"]["visible"] = {}
|
||||
root["zButtonRanged"]["rows"] = 1
|
||||
root["zButtonRanged"]["horizontal"] = nil
|
||||
root["zButtonRanged"]["vertical"] = nil
|
||||
root["zButtonRanged"]["firstbutton"] = "RIGHT"
|
||||
root["zButtonRanged"]["enabled"] = false
|
||||
root["zButtonRanged"]["tooltip"] = 1
|
||||
root["zButtonRanged"]["parent"] = {}
|
||||
root["zButtonRanged"]["parent"]["size"] = 36
|
||||
root["zButtonRanged"]["parent"]["hide"] = nil
|
||||
root["zButtonRanged"]["parent"]["circle"] = 1
|
||||
root["zButtonRanged"]["children"] = {}
|
||||
root["zButtonRanged"]["children"]["size"] = 36
|
||||
root["zButtonRanged"]["children"]["hideonclick"] = 1
|
||||
end
|
||||
|
||||
ZHunterMod_Ranged_Weapons = ZHunterMod_Ranged_Weapons or {}
|
||||
|
||||
local ZHUNTER_RANGED_MAX_COUNT = 80
|
||||
local zButtonRanged_Cache = {}
|
||||
local zButtonRanged_TooltipWarmed = false
|
||||
|
||||
local function zButtonRanged_GetKnownItemSpeed(itemId)
|
||||
local idNum = tonumber(itemId)
|
||||
if not idNum then
|
||||
return nil
|
||||
end
|
||||
local items = _G["MTH_DS_Items"] or MTH_DS_AmmoItems
|
||||
local item = items and items[idNum]
|
||||
local speedVal = item and tonumber(item.speed)
|
||||
if speedVal and speedVal > 0 then
|
||||
return speedVal
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function zButtonRanged_GetSaved()
|
||||
local currentRoot = zButtonRanged_GetRoot()
|
||||
if not currentRoot["zButtonRanged"] then
|
||||
currentRoot["zButtonRanged"] = {}
|
||||
end
|
||||
return currentRoot["zButtonRanged"]
|
||||
end
|
||||
|
||||
local function zButtonRanged_GetColorGradient(perc)
|
||||
perc = perc > 1 and 1 or perc
|
||||
perc = perc < 0 and 0 or perc
|
||||
local r1, g1, b1, r2, g2, b2
|
||||
if perc <= 0.5 then
|
||||
perc = perc * 2
|
||||
r1, g1, b1 = 1, 0, 0
|
||||
r2, g2, b2 = 1, 1, 0
|
||||
else
|
||||
perc = perc * 2 - 1
|
||||
r1, g1, b1 = 1, 1, 0
|
||||
r2, g2, b2 = 0, 1, 0
|
||||
end
|
||||
local r = r1 + (r2 - r1) * perc
|
||||
local g = g1 + (g2 - g1) * perc
|
||||
local b = b1 + (b2 - b1) * perc
|
||||
return r, g, b
|
||||
end
|
||||
|
||||
local function zButtonRanged_EnsureDurabilityText(button)
|
||||
if button and not button.rangedDurabilityText then
|
||||
button.rangedDurabilityText = button:CreateFontString(nil, "OVERLAY")
|
||||
button.rangedDurabilityText:SetPoint("BOTTOMRIGHT", button)
|
||||
button.rangedDurabilityText:SetFont("Fonts\\ARIALN.ttf", 13, "OUTLINE")
|
||||
end
|
||||
return button and button.rangedDurabilityText
|
||||
end
|
||||
|
||||
local function zButtonRanged_EnsureSpeedText(button)
|
||||
if button and not button.rangedSpeedText then
|
||||
button.rangedSpeedText = button:CreateFontString(nil, "OVERLAY")
|
||||
button.rangedSpeedText:SetPoint("TOPLEFT", button, "TOPLEFT", 1, -1)
|
||||
button.rangedSpeedText:SetFont("Fonts\\ARIALN.ttf", 9, "OUTLINE")
|
||||
end
|
||||
return button and button.rangedSpeedText
|
||||
end
|
||||
|
||||
local function zButtonRanged_IsRangedItem(subtype, equipLoc)
|
||||
local subtypeText = tostring(subtype or "")
|
||||
if subtypeText == tostring(MTH_WEAPON_BOWS or "Bows") then return true end
|
||||
if subtypeText == tostring(MTH_WEAPON_GUNS or "Guns") then return true end
|
||||
if subtypeText == tostring(MTH_WEAPON_CROSSBOWS or "Crossbows") then return true end
|
||||
if subtypeText == "Thrown" then return true end
|
||||
if equipLoc == "INVTYPE_RANGED" or equipLoc == "INVTYPE_RANGEDRIGHT" or equipLoc == "INVTYPE_THROWN" then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function zButtonRanged_RebuildCache()
|
||||
zButtonRanged_Cache = {}
|
||||
for bag = 0, 4 do
|
||||
for slot = 1, GetContainerNumSlots(bag) do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
if link then
|
||||
local _, _, id = string.find(link, "Hitem:((%d+).-)")
|
||||
if id then
|
||||
local itemNameResolved, itemLink, itemQuality, itemReqLevel, _, itemSubtype, _, itemEquipLoc, itemIcon = GetItemInfo(id)
|
||||
local _, _, linkName = string.find(link, "%[(.+)%]")
|
||||
local itemName = itemNameResolved or linkName
|
||||
if itemName and zButtonRanged_IsRangedItem(itemSubtype, itemEquipLoc) then
|
||||
local _, itemCount = GetContainerItemInfo(bag, slot)
|
||||
local knownSpeed = zButtonRanged_GetKnownItemSpeed(id)
|
||||
local rangedInfo = zButtonRanged_Cache[itemName]
|
||||
if not rangedInfo then
|
||||
rangedInfo = {
|
||||
name = itemName,
|
||||
quality = itemQuality,
|
||||
reqLevel = itemReqLevel,
|
||||
subtype = itemSubtype,
|
||||
equipLoc = itemEquipLoc,
|
||||
bag = bag,
|
||||
slot = slot,
|
||||
id = id,
|
||||
link = link,
|
||||
icon = itemIcon,
|
||||
speed = knownSpeed,
|
||||
count = 0,
|
||||
}
|
||||
zButtonRanged_Cache[itemName] = rangedInfo
|
||||
end
|
||||
if rangedInfo.speed == nil and knownSpeed ~= nil then
|
||||
rangedInfo.speed = knownSpeed
|
||||
end
|
||||
rangedInfo.count = (rangedInfo.count or 0) + (itemCount or 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonRanged_GetOrderedWeapons()
|
||||
local names = {}
|
||||
for weaponName, weaponInfo in pairs(zButtonRanged_Cache) do
|
||||
if weaponName and weaponInfo and (tonumber(weaponInfo.count) or 0) > 0 then
|
||||
table.insert(names, weaponName)
|
||||
end
|
||||
end
|
||||
table.sort(names, function(a, b)
|
||||
local infoA = zButtonRanged_Cache[a] or {}
|
||||
local infoB = zButtonRanged_Cache[b] or {}
|
||||
local lvlA = tonumber(infoA.reqLevel) or 0
|
||||
local lvlB = tonumber(infoB.reqLevel) or 0
|
||||
if lvlA ~= lvlB then
|
||||
return lvlA < lvlB
|
||||
end
|
||||
local qualityA = tonumber(infoA.quality) or 0
|
||||
local qualityB = tonumber(infoB.quality) or 0
|
||||
if qualityA ~= qualityB then
|
||||
return qualityA < qualityB
|
||||
end
|
||||
return tostring(a) < tostring(b)
|
||||
end)
|
||||
return names
|
||||
end
|
||||
|
||||
local function zButtonRanged_EnsureSpellOrder(weapons)
|
||||
local saved = zButtonRanged_GetSaved()
|
||||
if not saved["spells"] then
|
||||
saved["spells"] = {}
|
||||
end
|
||||
if not saved["visible"] then
|
||||
saved["visible"] = {}
|
||||
end
|
||||
|
||||
local maxWeapons = table.getn(weapons or {})
|
||||
local needsReset = false
|
||||
for i = 1, maxWeapons do
|
||||
local index = saved["spells"][i]
|
||||
if not tonumber(index) or index < 1 or index > maxWeapons then
|
||||
needsReset = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if needsReset or table.getn(saved["spells"]) ~= maxWeapons then
|
||||
saved["spells"] = {}
|
||||
for i = 1, maxWeapons do
|
||||
saved["spells"][i] = i
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, maxWeapons do
|
||||
if saved["visible"][i] == nil then
|
||||
saved["visible"][i] = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonRanged_AssignButtonFromInfo(button, weaponInfo)
|
||||
if not (button and weaponInfo) then
|
||||
return false
|
||||
end
|
||||
button.id = weaponInfo.id
|
||||
button.icon = weaponInfo.icon
|
||||
button.isspell = nil
|
||||
button.ammoname = weaponInfo.name
|
||||
button.ammobag = weaponInfo.bag
|
||||
button.ammoslot = weaponInfo.slot
|
||||
button.ammoid = weaponInfo.id
|
||||
button.ammolink = weaponInfo.link
|
||||
button.ammocount = weaponInfo.count
|
||||
button.rangedType = weaponInfo.subtype
|
||||
button.rangedReqLevel = weaponInfo.reqLevel
|
||||
button.rangedQuality = weaponInfo.quality
|
||||
button.rangedSpeed = weaponInfo.speed
|
||||
return true
|
||||
end
|
||||
|
||||
local function zButtonRanged_ApplyRuntimeSettings()
|
||||
if not zButtonRanged then
|
||||
return
|
||||
end
|
||||
local saved = zButtonRanged_GetSaved()
|
||||
zButtonRanged.tooltip = saved["tooltip"] and true or false
|
||||
zButtonRanged.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
local function zButtonRanged_UpdateDurabilityText(button)
|
||||
local text = zButtonRanged_EnsureDurabilityText(button)
|
||||
if not text then
|
||||
return
|
||||
end
|
||||
|
||||
if button ~= zButtonRanged then
|
||||
text:SetText("")
|
||||
return
|
||||
end
|
||||
|
||||
if type(GetInventoryItemDurability) ~= "function" then
|
||||
text:SetText("")
|
||||
return
|
||||
end
|
||||
|
||||
local cur, max = nil, nil
|
||||
local okPlayer, cPlayer, mPlayer = pcall(GetInventoryItemDurability, "player", 18)
|
||||
if okPlayer then
|
||||
cur, max = cPlayer, mPlayer
|
||||
else
|
||||
local okSlot, cSlot, mSlot = pcall(GetInventoryItemDurability, 18)
|
||||
if okSlot then
|
||||
cur, max = cSlot, mSlot
|
||||
end
|
||||
end
|
||||
|
||||
cur = tonumber(cur)
|
||||
max = tonumber(max)
|
||||
if not cur or not max or max <= 0 then
|
||||
text:SetText("")
|
||||
return
|
||||
end
|
||||
|
||||
local perc = math.floor(((cur / max) * 100) + 0.5)
|
||||
if perc >= 100 then
|
||||
text:SetText("")
|
||||
return
|
||||
end
|
||||
|
||||
local r, g, b = zButtonRanged_GetColorGradient(cur / max)
|
||||
text:SetTextColor(r, g, b)
|
||||
text:SetText(tostring(perc) .. "%")
|
||||
end
|
||||
|
||||
local function zButtonRanged_UpdateSpeedText(button)
|
||||
local text = zButtonRanged_EnsureSpeedText(button)
|
||||
if not text then
|
||||
return
|
||||
end
|
||||
local speedVal = tonumber(button and button.rangedSpeed)
|
||||
if not speedVal then
|
||||
text:SetText("")
|
||||
return
|
||||
end
|
||||
text:SetText(string.format("%.2f", speedVal))
|
||||
end
|
||||
|
||||
local function zButtonRanged_UpdateParentFromEquipped()
|
||||
if not zButtonRanged then
|
||||
return false
|
||||
end
|
||||
|
||||
local equippedLink = GetInventoryItemLink("player", 18)
|
||||
if not equippedLink then
|
||||
return false
|
||||
end
|
||||
local _, _, linkName = string.find(equippedLink, "%[(.+)%]")
|
||||
|
||||
local _, _, itemId = string.find(equippedLink, "item:(%d+)")
|
||||
if not itemId then
|
||||
local _, _, altId = string.find(equippedLink, "Hitem:((%d+).-)")
|
||||
itemId = altId
|
||||
end
|
||||
|
||||
local itemName, _, itemQuality, itemReqLevel, _, itemSubtype, _, itemEquipLoc, itemIcon = GetItemInfo(itemId)
|
||||
itemName = itemName or linkName
|
||||
if not itemName then
|
||||
return false
|
||||
end
|
||||
if (itemSubtype or itemEquipLoc) and not zButtonRanged_IsRangedItem(itemSubtype, itemEquipLoc) then
|
||||
return false
|
||||
end
|
||||
|
||||
local cacheInfo = zButtonRanged_Cache[itemName]
|
||||
local info = {
|
||||
name = itemName,
|
||||
quality = itemQuality,
|
||||
reqLevel = itemReqLevel,
|
||||
subtype = itemSubtype,
|
||||
equipLoc = itemEquipLoc,
|
||||
bag = cacheInfo and cacheInfo.bag or nil,
|
||||
slot = cacheInfo and cacheInfo.slot or nil,
|
||||
id = itemId,
|
||||
link = equippedLink,
|
||||
icon = itemIcon or GetInventoryItemTexture("player", 18),
|
||||
speed = (cacheInfo and cacheInfo.speed) or zButtonRanged_GetKnownItemSpeed(itemId),
|
||||
count = cacheInfo and cacheInfo.count or 1,
|
||||
}
|
||||
|
||||
if not info.icon then
|
||||
info.icon = GetInventoryItemTexture("player", 18)
|
||||
end
|
||||
|
||||
zButtonRanged_AssignButtonFromInfo(zButtonRanged, info)
|
||||
zButtonRanged:Enable()
|
||||
zButtonRanged:Show()
|
||||
return true
|
||||
end
|
||||
|
||||
local function zButtonRanged_SetButtons(parent, weaponNames)
|
||||
if not (parent and parent.count) then
|
||||
return 0
|
||||
end
|
||||
|
||||
for i = 1, parent.count do
|
||||
local child = getglobal(parent.name .. i)
|
||||
if child then
|
||||
child:Hide()
|
||||
child.id = nil
|
||||
child.icon = nil
|
||||
child.isspell = nil
|
||||
child.ammoname = nil
|
||||
child.ammobag = nil
|
||||
child.ammoslot = nil
|
||||
end
|
||||
end
|
||||
|
||||
local found = 0
|
||||
for i = 1, table.getn(weaponNames or {}) do
|
||||
if found >= parent.count then
|
||||
break
|
||||
end
|
||||
local weaponName = weaponNames[i]
|
||||
local weaponInfo = weaponName and zButtonRanged_Cache[weaponName] or nil
|
||||
if weaponInfo and weaponInfo.id then
|
||||
found = found + 1
|
||||
local child = getglobal(parent.name .. found)
|
||||
if child then
|
||||
zButtonRanged_AssignButtonFromInfo(child, weaponInfo)
|
||||
zButtonRanged_UpdateButton(child)
|
||||
child:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local hasEquipped = zButtonRanged_UpdateParentFromEquipped()
|
||||
if not hasEquipped and found > 0 then
|
||||
local first = getglobal(parent.name .. 1)
|
||||
if first then
|
||||
zButtonRanged_AssignButtonFromInfo(parent, {
|
||||
name = first.ammoname,
|
||||
quality = first.rangedQuality,
|
||||
reqLevel = first.rangedReqLevel,
|
||||
subtype = first.rangedType,
|
||||
equipLoc = nil,
|
||||
bag = first.ammobag,
|
||||
slot = first.ammoslot,
|
||||
id = first.ammoid or first.id,
|
||||
link = first.ammolink,
|
||||
icon = first.icon,
|
||||
speed = first.rangedSpeed,
|
||||
count = first.ammocount,
|
||||
})
|
||||
zButtonRanged_UpdateButton(parent)
|
||||
parent:Enable()
|
||||
parent:Show()
|
||||
end
|
||||
end
|
||||
|
||||
if found <= 0 and not hasEquipped then
|
||||
parent.id = nil
|
||||
parent.icon = nil
|
||||
parent.ammoname = nil
|
||||
parent:Hide()
|
||||
else
|
||||
parent:Show()
|
||||
end
|
||||
|
||||
return found
|
||||
end
|
||||
|
||||
function zButtonRanged_UpdateButton(button)
|
||||
if not button then
|
||||
button = this
|
||||
end
|
||||
if not (button and button.icontexture) then
|
||||
return
|
||||
end
|
||||
if not button.id then
|
||||
button.icontexture:Hide()
|
||||
zButtonRanged_UpdateSpeedText(button)
|
||||
zButtonRanged_UpdateDurabilityText(button)
|
||||
return
|
||||
end
|
||||
button.icontexture:SetTexture(button.icon)
|
||||
button.icontexture:Show()
|
||||
zButtonRanged_UpdateSpeedText(button)
|
||||
zButtonRanged_UpdateDurabilityText(button)
|
||||
end
|
||||
|
||||
local function zButtonRanged_OnEnter(button)
|
||||
if not button then
|
||||
button = this
|
||||
end
|
||||
if not button then
|
||||
return
|
||||
end
|
||||
if not (zButtonRanged and zButtonRanged.tooltip) then
|
||||
return
|
||||
end
|
||||
GameTooltip:SetOwner(button, "ANCHOR_TOPLEFT")
|
||||
if button == zButtonRanged then
|
||||
if not GameTooltip:SetInventoryItem("player", 18) and button.ammobag and button.ammoslot then
|
||||
GameTooltip:SetBagItem(button.ammobag, button.ammoslot)
|
||||
end
|
||||
elseif button.ammobag and button.ammoslot then
|
||||
GameTooltip:SetBagItem(button.ammobag, button.ammoslot)
|
||||
elseif button.ammolink then
|
||||
GameTooltip:SetHyperlink(button.ammolink)
|
||||
end
|
||||
GameTooltip:Show()
|
||||
end
|
||||
|
||||
local function zButtonRanged_PrewarmTooltipOnce()
|
||||
if zButtonRanged_TooltipWarmed then
|
||||
return
|
||||
end
|
||||
zButtonRanged_TooltipWarmed = true
|
||||
if not GameTooltip then
|
||||
return
|
||||
end
|
||||
GameTooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
GameTooltip:ClearLines()
|
||||
if zButtonRanged and zButtonRanged.ammolink then
|
||||
GameTooltip:SetHyperlink(zButtonRanged.ammolink)
|
||||
elseif zButtonRanged and zButtonRanged.ammobag and zButtonRanged.ammoslot then
|
||||
GameTooltip:SetBagItem(zButtonRanged.ammobag, zButtonRanged.ammoslot)
|
||||
else
|
||||
GameTooltip:SetInventoryItem("player", 18)
|
||||
end
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local function zButtonRanged_EquipFromButton(button)
|
||||
if not (button and button.ammobag and button.ammoslot) then
|
||||
return false
|
||||
end
|
||||
|
||||
PickupContainerItem(button.ammobag, button.ammoslot)
|
||||
if CursorHasItem() then
|
||||
EquipCursorItem(18)
|
||||
end
|
||||
if CursorHasItem() then
|
||||
if ClearCursor then ClearCursor() end
|
||||
return false
|
||||
end
|
||||
|
||||
zButtonRanged_UpdateParentFromEquipped()
|
||||
zButtonRanged_UpdateButton(zButtonRanged)
|
||||
return true
|
||||
end
|
||||
|
||||
local function zButtonRanged_BeforeClick(button)
|
||||
if not button then
|
||||
return false
|
||||
end
|
||||
if button.isspell then
|
||||
return false
|
||||
end
|
||||
zButtonRanged_EquipFromButton(button)
|
||||
return true
|
||||
end
|
||||
|
||||
local function zButtonRanged_RefreshButtonsFromState()
|
||||
if not zButtonRanged then
|
||||
return
|
||||
end
|
||||
|
||||
local saved = zButtonRanged_GetSaved()
|
||||
zButtonRanged_RebuildCache()
|
||||
local weapons = zButtonRanged_GetOrderedWeapons()
|
||||
ZHunterMod_Ranged_Weapons = weapons
|
||||
zButtonRanged_EnsureSpellOrder(weapons)
|
||||
|
||||
local info = {}
|
||||
local infoIndex = 1
|
||||
for i = 1, table.getn(weapons) do
|
||||
local weaponIndex = saved["spells"][i]
|
||||
if weaponIndex and saved["visible"][weaponIndex] ~= false then
|
||||
info[infoIndex] = weapons[weaponIndex]
|
||||
infoIndex = infoIndex + 1
|
||||
end
|
||||
end
|
||||
|
||||
zButtonRanged.found = ZSpellButton_SetButtons(zButtonRanged, info)
|
||||
zButtonRanged_ApplyRuntimeSettings()
|
||||
end
|
||||
|
||||
local function zButtonRanged_EnsureConfig()
|
||||
local saved = zButtonRanged_GetSaved()
|
||||
saved["count"] = nil
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = false
|
||||
end
|
||||
if saved["tooltip"] == nil then
|
||||
saved["tooltip"] = 1
|
||||
end
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
end
|
||||
if saved["children"]["hideonclick"] == nil then
|
||||
saved["children"]["hideonclick"] = 1
|
||||
end
|
||||
if not saved["spells"] then
|
||||
saved["spells"] = {}
|
||||
end
|
||||
if not saved["visible"] then
|
||||
saved["visible"] = {}
|
||||
end
|
||||
if not saved["parent"] then
|
||||
saved["parent"] = {}
|
||||
end
|
||||
if not saved["children"]["size"] then
|
||||
saved["children"]["size"] = 36
|
||||
end
|
||||
if not saved["parent"]["size"] then
|
||||
saved["parent"]["size"] = 36
|
||||
end
|
||||
if saved["parent"]["circle"] == nil then
|
||||
saved["parent"]["circle"] = 1
|
||||
end
|
||||
if not saved["rows"] or saved["rows"] < 1 then
|
||||
saved["rows"] = 1
|
||||
end
|
||||
if not saved["firstbutton"] then
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonRanged_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
function zButtonRanged_OnEvent()
|
||||
if event == "VARIABLES_LOADED" then
|
||||
if not zButtonRanged then
|
||||
return
|
||||
end
|
||||
if UnitClass("player") ~= ZHUNTER_HUNTER then
|
||||
zButtonRanged:UnregisterAllEvents()
|
||||
zButtonRanged:Hide()
|
||||
return
|
||||
end
|
||||
zButtonRanged.customSetButtons = zButtonRanged_SetButtons
|
||||
zButtonRanged.customUpdateButton = zButtonRanged_UpdateButton
|
||||
zButtonRanged.beforeclick = zButtonRanged_BeforeClick
|
||||
zButtonRanged_CreateButtons()
|
||||
zButtonRangedAdjustment = CreateFrame("Frame", "zButtonRangedAdjustment")
|
||||
zButtonRangedAdjustment:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
||||
zButtonRangedAdjustment:RegisterEvent("BAG_UPDATE")
|
||||
zButtonRangedAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonRangedAdjustment:SetScript("OnEvent", zButtonRangedAdjustment_OnEvent)
|
||||
zButtonRanged_SetupSizeAndPosition()
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonRanged_CreateButtons()
|
||||
zButtonRanged_EnsureConfig()
|
||||
if not zButtonRanged.children then
|
||||
ZSpellButton_CreateChildren(zButtonRanged, "zButtonRanged", ZHUNTER_RANGED_MAX_COUNT)
|
||||
else
|
||||
zButtonRanged.count = ZHUNTER_RANGED_MAX_COUNT
|
||||
end
|
||||
zButtonRanged:SetScript("OnEnter", function()
|
||||
zButtonRanged_OnEnter(this)
|
||||
end)
|
||||
for i = 1, zButtonRanged.count do
|
||||
local child = getglobal("zButtonRanged" .. i)
|
||||
if child then
|
||||
child:SetScript("OnEnter", function()
|
||||
zButtonRanged_OnEnter(this)
|
||||
end)
|
||||
end
|
||||
end
|
||||
zButtonRanged_RefreshButtonsFromState()
|
||||
end
|
||||
|
||||
function zButtonRanged_SetupSizeAndPosition()
|
||||
local saved = zButtonRanged_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonRanged and zButtonRanged.Hide then
|
||||
zButtonRanged:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
local displayCount = zButtonRanged.found or 0
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
end
|
||||
ZSpellButton_SetSize(zButtonRanged, saved["parent"]["size"])
|
||||
ZSpellButton_SetSize(zButtonRanged, saved["children"]["size"], 1)
|
||||
ZSpellButton_SetExpandDirection(zButtonRanged, saved["firstbutton"])
|
||||
ZSpellButton_ArrangeChildren(zButtonRanged, saved["rows"], displayCount, saved["horizontal"], saved["vertical"])
|
||||
zButtonRanged_UpdateButton(zButtonRanged)
|
||||
end
|
||||
|
||||
function zButtonRanged_Reset()
|
||||
local currentRoot = zButtonRanged_GetRoot()
|
||||
currentRoot["zButtonRanged"] = {}
|
||||
local saved = zButtonRanged_GetSaved()
|
||||
saved["spells"] = {}
|
||||
saved["visible"] = {}
|
||||
saved["rows"] = 1
|
||||
saved["horizontal"] = nil
|
||||
saved["vertical"] = nil
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
saved["enabled"] = false
|
||||
saved["tooltip"] = 1
|
||||
saved["parent"] = {}
|
||||
saved["parent"]["size"] = 36
|
||||
saved["parent"]["hide"] = nil
|
||||
saved["parent"]["circle"] = 1
|
||||
saved["children"] = {}
|
||||
saved["children"]["size"] = 36
|
||||
saved["children"]["hideonclick"] = 1
|
||||
zButtonRanged_EnsureConfig()
|
||||
end
|
||||
|
||||
function zButtonRangedAdjustment_OnEvent()
|
||||
if not zButtonRanged then
|
||||
return
|
||||
end
|
||||
if event == "UNIT_INVENTORY_CHANGED" and arg1 and arg1 ~= "player" then
|
||||
return
|
||||
end
|
||||
zButtonRanged_RefreshButtonsFromState()
|
||||
zButtonRanged_SetupSizeAndPosition()
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
zButtonRanged_PrewarmTooltipOnce()
|
||||
end
|
||||
if GameTooltip:IsOwned(zButtonRanged) then
|
||||
zButtonRanged_OnEnter(zButtonRanged)
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonRanged_KeyBinding(index)
|
||||
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local button
|
||||
if index then
|
||||
button = getglobal("zButtonRanged" .. index)
|
||||
else
|
||||
button = zButtonRanged
|
||||
end
|
||||
if button then
|
||||
zButtonRanged_EquipFromButton(button)
|
||||
if zButtonRanged.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(zButtonRanged, false)
|
||||
elseif zButtonRanged.children then
|
||||
zButtonRanged.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_zButtonRanged1 = "/ZRanged"
|
||||
SlashCmdList["zButtonRanged"] = function(msg)
|
||||
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Ranged button is disabled while module 'zhunter' is disabled.") then
|
||||
return
|
||||
end
|
||||
if msg == "reset" then
|
||||
zButtonRanged_Reset()
|
||||
zButtonRanged:ClearAllPoints()
|
||||
zButtonRanged:SetPoint("CENTER", UIParent, "CENTER", 120, 0)
|
||||
zButtonRanged_RefreshButtonsFromState()
|
||||
zButtonRanged_SetupSizeAndPosition()
|
||||
elseif msg == "options" then
|
||||
MTH_OpenOptions("Ranged")
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"reset\", \"options\"")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Frame name="zButtonRangedFrame">
|
||||
</Frame>
|
||||
<CheckButton name="zButtonRanged" inherits="ZSpellButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="120" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</CheckButton>
|
||||
</Ui>
|
||||
@@ -103,6 +103,7 @@ local function zButtonTrack_ApplyRuntimeSettings()
|
||||
zButtonTrack.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
|
||||
function zButtonTrack_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
@@ -96,6 +96,7 @@ local function zButtonTrap_ApplyRuntimeSettings()
|
||||
zButtonTrap.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
|
||||
function zButtonTrap_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user