mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-10-02 04:20:01 +00:00
First version
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
<!--
|
||||
MetaHunt AutoBuy Module Loader
|
||||
Standalone auto-buy foundation for pet food and ammo.
|
||||
-->
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Include file="engine.lua"/>
|
||||
<Include file="module.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,161 @@
|
||||
------------------------------------------------------
|
||||
-- MetaHunt: AutoBuy Module
|
||||
-- Standalone module shell for vendor auto-buy features.
|
||||
------------------------------------------------------
|
||||
|
||||
local MTH_AutoBuy = {
|
||||
name = "autobuy",
|
||||
enabled = false,
|
||||
version = "1.0.3",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"MERCHANT_SHOW",
|
||||
"MERCHANT_UPDATE",
|
||||
"MERCHANT_CLOSED",
|
||||
},
|
||||
initialized = false,
|
||||
}
|
||||
|
||||
local function AB_Log(message, severity)
|
||||
if type(MTH_Log) == "function" then
|
||||
MTH_Log("[AutoBuy] " .. tostring(message or ""), severity)
|
||||
end
|
||||
end
|
||||
|
||||
local AB_Engine
|
||||
|
||||
local function AB_Trace(message)
|
||||
return
|
||||
end
|
||||
|
||||
local function AB_EnsureBridgeFrame(moduleRef)
|
||||
if MTH_AutoBuy._bridgeFrame then
|
||||
return MTH_AutoBuy._bridgeFrame
|
||||
end
|
||||
|
||||
local frame = CreateFrame("Frame", "MTH_AutoBuyBridgeFrame")
|
||||
if not frame then
|
||||
AB_Log("failed to create bridge frame", "error")
|
||||
return nil
|
||||
end
|
||||
|
||||
frame:RegisterEvent("VARIABLES_LOADED")
|
||||
frame:RegisterEvent("MERCHANT_SHOW")
|
||||
frame:RegisterEvent("MERCHANT_UPDATE")
|
||||
frame:RegisterEvent("MERCHANT_CLOSED")
|
||||
frame:SetScript("OnEvent", function(_, eventName)
|
||||
eventName = eventName or event
|
||||
local engine = AB_Engine()
|
||||
if not engine then
|
||||
AB_Trace("bridge event=" .. tostring(eventName) .. " engine missing")
|
||||
return
|
||||
end
|
||||
|
||||
if eventName == "VARIABLES_LOADED" then
|
||||
engine:Init()
|
||||
local store = engine:EnsureDefaults()
|
||||
AB_Trace("bridge VARIABLES_LOADED store.enabled=" .. tostring(store and store.enabled)
|
||||
.. " projectiles.enabled=" .. tostring(store and store.projectiles and store.projectiles.enabled))
|
||||
return
|
||||
end
|
||||
|
||||
if eventName == "MERCHANT_SHOW" or eventName == "MERCHANT_UPDATE" then
|
||||
AB_Trace("bridge " .. tostring(eventName) .. " -> engine")
|
||||
engine:OnMerchantEvent(eventName)
|
||||
elseif eventName == "MERCHANT_CLOSED" then
|
||||
AB_Trace("bridge MERCHANT_CLOSED -> engine")
|
||||
if engine.OnMerchantClosed then
|
||||
engine:OnMerchantClosed()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
MTH_AutoBuy._bridgeFrame = frame
|
||||
MTH_AutoBuy._bridgeActive = true
|
||||
return frame
|
||||
end
|
||||
|
||||
AB_Engine = function()
|
||||
return MTH_AutoBuyEngine
|
||||
end
|
||||
|
||||
function MTH_AutoBuy:init()
|
||||
local engine = AB_Engine()
|
||||
if not engine then
|
||||
AB_Log("init failed: engine missing", "error")
|
||||
AB_Trace("init failed: engine missing")
|
||||
return
|
||||
end
|
||||
engine:Init()
|
||||
AB_EnsureBridgeFrame(self)
|
||||
self.initialized = true
|
||||
AB_Trace("init done")
|
||||
if self.enabled then
|
||||
AB_Log("module initialized", "debug")
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_AutoBuy:setEnabled(enabled)
|
||||
if not self.initialized then
|
||||
self:init()
|
||||
end
|
||||
local engine = AB_Engine()
|
||||
if not engine then
|
||||
AB_Trace("setEnabled ignored: engine missing")
|
||||
return
|
||||
end
|
||||
local store = engine:EnsureDefaults()
|
||||
store.enabled = enabled and true or false
|
||||
AB_EnsureBridgeFrame(self)
|
||||
AB_Trace("setEnabled store.enabled=" .. tostring(store.enabled))
|
||||
end
|
||||
|
||||
function MTH_AutoBuy:onEvent(event)
|
||||
local engine = AB_Engine()
|
||||
if not engine then
|
||||
AB_Log("onEvent ignored: engine missing, event=" .. tostring(event), "debug")
|
||||
AB_Trace("engine missing, event=" .. tostring(event))
|
||||
return
|
||||
end
|
||||
if self._bridgeActive and (event == "MERCHANT_SHOW" or event == "MERCHANT_UPDATE" or event == "MERCHANT_CLOSED") then
|
||||
return
|
||||
end
|
||||
|
||||
AB_Log("onEvent event=" .. tostring(event) .. " module.enabled=" .. tostring(self.enabled), "debug")
|
||||
|
||||
if event == "VARIABLES_LOADED" then
|
||||
engine:Init()
|
||||
AB_EnsureBridgeFrame(self)
|
||||
AB_Log("onEvent VARIABLES_LOADED -> engine init", "debug")
|
||||
local store = engine:EnsureDefaults()
|
||||
AB_Trace("VARIABLES_LOADED module.enabled=" .. tostring(self.enabled)
|
||||
.. " store.enabled=" .. tostring(store and store.enabled)
|
||||
.. " projectiles.enabled=" .. tostring(store and store.projectiles and store.projectiles.enabled))
|
||||
return
|
||||
end
|
||||
|
||||
if not self.enabled then
|
||||
AB_Log("onEvent ignored: module disabled", "debug")
|
||||
if event == "MERCHANT_SHOW" or event == "MERCHANT_UPDATE" then
|
||||
AB_Trace(tostring(event) .. " ignored: module disabled")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if event == "MERCHANT_SHOW" or event == "MERCHANT_UPDATE" then
|
||||
AB_Log("onEvent merchant event forwarded: " .. tostring(event), "debug")
|
||||
AB_Trace("forwarding " .. tostring(event) .. " to engine")
|
||||
engine:OnMerchantEvent(event)
|
||||
elseif event == "MERCHANT_CLOSED" then
|
||||
AB_Trace("forwarding MERCHANT_CLOSED to engine")
|
||||
if engine.OnMerchantClosed then
|
||||
engine:OnMerchantClosed()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_AutoBuy:cleanup()
|
||||
AB_Log("module cleanup", "debug")
|
||||
end
|
||||
|
||||
MTH:RegisterModule("autobuy", MTH_AutoBuy)
|
||||
@@ -0,0 +1,78 @@
|
||||
local BS = setmetatable({}, {
|
||||
__index = function(_, key)
|
||||
if MTH and MTH.LocalizeSpell then
|
||||
return MTH:LocalizeSpell(key)
|
||||
end
|
||||
return key
|
||||
end,
|
||||
})
|
||||
|
||||
function MTH_ChronometerHunterInstallData(engine)
|
||||
if not engine then
|
||||
return
|
||||
end
|
||||
|
||||
local _, class = UnitClass("player")
|
||||
if class == "HUNTER" then
|
||||
engine:AddGroup(1, true, "MAGENTA")
|
||||
engine:AddGroup(2, false, "MAROON")
|
||||
engine:AddGroup(3, false, "GREEN")
|
||||
|
||||
engine:AddTimer(engine.SPELL, BS["Bestial Wrath"], 18, 0, 1, 1, { cr = "RED" })
|
||||
engine:AddTimer(engine.SPELL, BS["Concussive Shot"], 4, 1, 0, 0, { cr = "BLUE", ea = { [BS["Improved Concussive Shot"]] = 4 } })
|
||||
engine:AddTimer(engine.SPELL, BS["Counterattack"], 5, 1, 0, 0, { cr = "ORANGE" })
|
||||
engine:AddTimer(engine.SPELL, BS["Deterrence"], 10, 0, 1, 1, { cr = "ORANGE" })
|
||||
engine:AddTimer(engine.SPELL, BS["Explosive Trap"], 60, 0, 0, 0, { gr = 1, cr = "ORANGE", rc = true, ea = { [BS["Explosive Trap Effect"]] = 60 } })
|
||||
engine:AddTimer(engine.SPELL, BS["Freezing Trap"], 60, 0, 0, 0, { gr = 1, cr = "CYAN", rc = true, ea = { [BS["Freezing Trap Effect"]] = 60 } })
|
||||
engine:AddTimer(engine.SPELL, BS["Frost Trap"], 60, 0, 0, 0, { gr = 1, cr = "CYAN", rc = true, ea = { [BS["Frost Trap Aura"]] = 60 } })
|
||||
engine:AddTimer(engine.SPELL, BS["Flare"], 30, 0, 0, 0, { cr = "YELLOW", rc = true })
|
||||
engine:AddTimer(engine.SPELL, BS["Hunter's Mark"], 120, 1, 0, 0, { cr = "RED", rc = true })
|
||||
engine:AddTimer(engine.SPELL, BS["Immolation Trap"], 60, 0, 0, 0, { gr = 1, cr = "ORANGE", ea = { [BS["Immolation Trap Effect"]] = 60 } })
|
||||
engine:AddTimer(engine.SPELL, BS["Rapid Fire"], 15, 0, 1, 1, { cr = "RED" })
|
||||
engine:AddTimer(engine.SPELL, BS["Scare Beast"], 10, 1, 0, 0, { cr = "BLUE", rc = true, d = { rs = 5 } })
|
||||
engine:AddTimer(engine.SPELL, BS["Scatter Shot"], 4, 1, 0, 0, { cr = "MAROON" })
|
||||
engine:AddTimer(engine.SPELL, BS["Scorpid Sting"], 20, 1, 0, 0, { gr = 2, cr = "PURPLE", rc = true })
|
||||
engine:AddTimer(engine.SPELL, BS["Serpent Sting"], 15, 1, 0, 0, { gr = 2, cr = "GREEN", rc = true })
|
||||
engine:AddTimer(engine.SPELL, BS["Viper Sting"], 8, 1, 0, 0, { gr = 2, cr = "CYAN", rc = true })
|
||||
engine:AddTimer(engine.SPELL, BS["Wing Clip"], 10, 1, 0, 0, { cr = "YELLOW", rc = true, ea = { [BS["Improved Wing Clip"]] = 10 } })
|
||||
engine:AddTimer(engine.SPELL, BS["Wyvern Sting"], 12, 1, 0, 0, { gr = 2, cr = "MAROON", rc = true })
|
||||
engine:AddTimer(engine.SPELL, BS["Feed Pet"], 20, 0, 0, 0, { cr = "MAROON" })
|
||||
|
||||
engine:AddTimer(engine.EVENT, BS["Explosive Trap Effect"], 20, 1, 0, 1, { gr = 1, cr = "ORANGE", a = 1, xn = BS["Explosive Trap"] })
|
||||
engine:AddTimer(engine.EVENT, BS["Freezing Trap Effect"], 10, 1, 0, 1, { gr = 1, cr = "CYAN", a = 1, d = { rs = 5, tn = BS["Clever Traps"], tb = 0.15, tp = 1 }, xn = BS["Freezing Trap"] })
|
||||
engine:AddTimer(engine.EVENT, BS["Frost Trap Aura"], 30, 0, 0, 0, { gr = 1, cr = "CYAN", a = 1, d = { tn = BS["Clever Traps"], tb = 0.15, tp = 1 }, xn = BS["Frost Trap"] })
|
||||
engine:AddTimer(engine.EVENT, BS["Immolation Trap Effect"], 15, 1, 0, 1, { gr = 1, cr = "ORANGE", a = 1, xn = BS["Immolation Trap"] })
|
||||
engine:AddTimer(engine.EVENT, BS["Improved Concussive Shot"], 3, 1, 0, 0, { a = 1, cr = "BLUE", xn = BS["Concussive Shot"] })
|
||||
engine:AddTimer(engine.EVENT, BS["Improved Wing Clip"], 5, 1, 0, 0, { a = 1, cr = "YELLOW", xn = BS["Wing Clip"] })
|
||||
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 })
|
||||
end
|
||||
|
||||
local _, race = UnitRace("player")
|
||||
if race == "Dwarf" then
|
||||
engine:AddTimer(engine.SPELL, BS["Stoneform"], 8, 0, 1, 1, { cl = "RACIAL" })
|
||||
elseif race == "Human" then
|
||||
engine:AddTimer(engine.SPELL, BS["Perception"], 20, 0, 1, 1, { cl = "RACIAL" })
|
||||
elseif race == "Orc" then
|
||||
engine:AddTimer(engine.SPELL, BS["Blood Fury"], 15, 0, 1, 1, { cl = "RACIAL" })
|
||||
elseif race == "Tauren" then
|
||||
engine:AddTimer(engine.SPELL, BS["War Stomp"], 2, 0, 0, 0, { cl = "RACIAL" })
|
||||
elseif race == "Troll" then
|
||||
engine:AddTimer(engine.SPELL, BS["Berserking"], 10, 0, 1, 1, { cl = "RACIAL" })
|
||||
elseif race == "Scourge" then
|
||||
engine:AddTimer(engine.SPELL, BS["Will of the Forsaken"], 5, 0, 1, 1, { cl = "RACIAL" })
|
||||
end
|
||||
|
||||
if class == "PALADIN" or class == "WARRIOR" or class == "ROGUE" or class == "SHAMAN" then
|
||||
engine:AddTimer(engine.EVENT, BS["Holy Strength"], 15, 0, 1, 1, { cr = "YELLOW", a = 1, cl = "COMMON" })
|
||||
end
|
||||
engine:AddTimer(engine.EVENT, BS["Unstable Power"], 20, 0, 1, 1, { a = 1, cr = "CYAN", cl = "COMMON" })
|
||||
engine:AddTimer(engine.EVENT, BS["Ephemeral Power"], 15, 0, 1, 1, { a = 1, cr = "CYAN", cl = "COMMON" })
|
||||
engine:AddTimer(engine.EVENT, BS["Mind Quickening"], 20, 0, 1, 1, { a = 1, cr = "CYAN", cl = "COMMON", xn = BS["Critical Mass"] })
|
||||
end
|
||||
|
||||
if MTH_ChronometerHunter and MTH_ChronometerHunter.dataSetup then
|
||||
table.insert(MTH_ChronometerHunter.dataSetup, MTH_ChronometerHunterInstallData)
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,973 @@
|
||||
--[[
|
||||
Name: AceEvent-2.0
|
||||
Revision: $Rev: 17803 $
|
||||
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
||||
Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
||||
Website: http://www.wowace.com/
|
||||
Documentation: http://www.wowace.com/index.php/AceEvent-2.0
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceEvent-2.0
|
||||
Description: Mixin to allow for event handling, scheduling, and inter-addon
|
||||
communication.
|
||||
Dependencies: AceLibrary, AceOO-2.0
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceEvent-2.0"
|
||||
local MINOR_VERSION = "$Revision: 17803 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check
|
||||
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
||||
|
||||
local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
||||
local Mixin = AceOO.Mixin
|
||||
local AceEvent = Mixin {
|
||||
"RegisterEvent",
|
||||
"RegisterAllEvents",
|
||||
"UnregisterEvent",
|
||||
"UnregisterAllEvents",
|
||||
"TriggerEvent",
|
||||
"ScheduleEvent",
|
||||
"ScheduleRepeatingEvent",
|
||||
"CancelScheduledEvent",
|
||||
"CancelAllScheduledEvents",
|
||||
"IsEventRegistered",
|
||||
"IsEventScheduled",
|
||||
"RegisterBucketEvent",
|
||||
"UnregisterBucketEvent",
|
||||
"UnregisterAllBucketEvents",
|
||||
"IsBucketEventRegistered",
|
||||
}
|
||||
|
||||
local table_setn
|
||||
do
|
||||
local version = GetBuildInfo()
|
||||
if string.find(version, "^2%.") then
|
||||
-- 2.0.0
|
||||
table_setn = function() end
|
||||
else
|
||||
table_setn = table.setn
|
||||
end
|
||||
end
|
||||
|
||||
local weakKey = {__mode="k"}
|
||||
local new, del
|
||||
do
|
||||
local list = setmetatable({}, weakKey)
|
||||
function new()
|
||||
local t = next(list)
|
||||
if t then
|
||||
list[t] = nil
|
||||
return t
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
|
||||
function del(t)
|
||||
setmetatable(t, nil)
|
||||
for k in pairs(t) do
|
||||
t[k] = nil
|
||||
end
|
||||
list[t] = true
|
||||
end
|
||||
end
|
||||
|
||||
local FAKE_NIL
|
||||
local RATE
|
||||
|
||||
local eventsWhichHappenOnce = {
|
||||
PLAYER_LOGIN = true,
|
||||
AceEvent_FullyInitialized = true,
|
||||
VARIABLES_LOADED = true,
|
||||
PLAYER_LOGOUT = true,
|
||||
}
|
||||
|
||||
local registeringFromAceEvent
|
||||
function AceEvent:RegisterEvent(event, method, once)
|
||||
AceEvent:argCheck(event, 2, "string")
|
||||
if self == AceEvent and not registeringFromAceEvent then
|
||||
AceEvent:argCheck(method, 3, "function")
|
||||
self = method
|
||||
else
|
||||
AceEvent:argCheck(method, 3, "string", "function", "nil", "boolean", "number")
|
||||
if type(method) == "boolean" or type(method) == "number" then
|
||||
AceEvent:argCheck(once, 4, "nil")
|
||||
once, method = method, event
|
||||
end
|
||||
end
|
||||
AceEvent:argCheck(once, 4, "number", "boolean", "nil")
|
||||
if eventsWhichHappenOnce[event] then
|
||||
once = true
|
||||
end
|
||||
local throttleRate
|
||||
if type(once) == "number" then
|
||||
throttleRate, once = once
|
||||
end
|
||||
if not method then
|
||||
method = event
|
||||
end
|
||||
if type(method) == "string" and type(self[method]) ~= "function" then
|
||||
AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method)
|
||||
else
|
||||
assert(type(method) == "function" or type(method) == "string")
|
||||
end
|
||||
|
||||
local AceEvent_registry = AceEvent.registry
|
||||
if not AceEvent_registry[event] then
|
||||
AceEvent_registry[event] = new()
|
||||
AceEvent.frame:RegisterEvent(event)
|
||||
end
|
||||
|
||||
local remember = true
|
||||
if AceEvent_registry[event][self] then
|
||||
remember = false
|
||||
end
|
||||
AceEvent_registry[event][self] = method
|
||||
|
||||
local AceEvent_onceRegistry = AceEvent.onceRegistry
|
||||
if once then
|
||||
if not AceEvent_onceRegistry then
|
||||
AceEvent.onceRegistry = new()
|
||||
AceEvent_onceRegistry = AceEvent.onceRegistry
|
||||
end
|
||||
if not AceEvent_onceRegistry[event] then
|
||||
AceEvent_onceRegistry[event] = new()
|
||||
end
|
||||
AceEvent_onceRegistry[event][self] = true
|
||||
else
|
||||
if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then
|
||||
AceEvent_onceRegistry[event][self] = nil
|
||||
if not next(AceEvent_onceRegistry[event]) then
|
||||
AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local AceEvent_throttleRegistry = AceEvent.throttleRegistry
|
||||
if throttleRate then
|
||||
if not AceEvent_throttleRegistry then
|
||||
AceEvent.throttleRegistry = new()
|
||||
AceEvent_throttleRegistry = AceEvent.throttleRegistry
|
||||
end
|
||||
if not AceEvent_throttleRegistry[event] then
|
||||
AceEvent_throttleRegistry[event] = new()
|
||||
end
|
||||
if AceEvent_throttleRegistry[event][self] then
|
||||
AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self])
|
||||
end
|
||||
AceEvent_throttleRegistry[event][self] = setmetatable(new(), weakKey)
|
||||
local t = AceEvent_throttleRegistry[event][self]
|
||||
t[RATE] = throttleRate
|
||||
else
|
||||
if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] then
|
||||
if AceEvent_throttleRegistry[event][self] then
|
||||
AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self])
|
||||
end
|
||||
if not next(AceEvent_throttleRegistry[event]) then
|
||||
AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if remember then
|
||||
AceEvent:TriggerEvent("AceEvent_EventRegistered", self, event)
|
||||
end
|
||||
end
|
||||
|
||||
local ALL_EVENTS
|
||||
|
||||
function AceEvent:RegisterAllEvents(method)
|
||||
if self == AceEvent then
|
||||
AceEvent:argCheck(method, 1, "function")
|
||||
self = method
|
||||
else
|
||||
AceEvent:argCheck(method, 1, "string", "function")
|
||||
if type(method) == "string" and type(self[method]) ~= "function" then
|
||||
AceEvent:error("Cannot register all events to method %q, it does not exist", method)
|
||||
end
|
||||
end
|
||||
|
||||
local AceEvent_registry = AceEvent.registry
|
||||
if not AceEvent_registry[ALL_EVENTS] then
|
||||
AceEvent_registry[ALL_EVENTS] = new()
|
||||
AceEvent.frame:RegisterAllEvents()
|
||||
end
|
||||
|
||||
AceEvent_registry[ALL_EVENTS][self] = method
|
||||
end
|
||||
|
||||
local _G = getfenv(0)
|
||||
local memstack, timestack = {}, {}
|
||||
local memdiff, timediff
|
||||
function AceEvent:TriggerEvent(event, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
AceEvent:argCheck(event, 2, "string")
|
||||
local AceEvent_registry = AceEvent.registry
|
||||
if (not AceEvent_registry[event] or not next(AceEvent_registry[event])) and (not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS])) then
|
||||
return
|
||||
end
|
||||
local _G_event = _G.event
|
||||
_G.event = event
|
||||
local lastEvent = AceEvent.currentEvent
|
||||
AceEvent.currentEvent = event
|
||||
|
||||
local AceEvent_onceRegistry = AceEvent.onceRegistry
|
||||
local AceEvent_debugTable = AceEvent.debugTable
|
||||
if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then
|
||||
local tmp = new()
|
||||
for obj, method in pairs(AceEvent_onceRegistry[event]) do
|
||||
tmp[obj] = AceEvent_registry[event] and AceEvent_registry[event][obj] or nil
|
||||
end
|
||||
local obj = next(tmp)
|
||||
while obj do
|
||||
local mem, time
|
||||
if AceEvent_debugTable then
|
||||
if not AceEvent_debugTable[event] then
|
||||
AceEvent_debugTable[event] = new()
|
||||
end
|
||||
if not AceEvent_debugTable[event][obj] then
|
||||
AceEvent_debugTable[event][obj] = new()
|
||||
AceEvent_debugTable[event][obj].mem = 0
|
||||
AceEvent_debugTable[event][obj].time = 0
|
||||
AceEvent_debugTable[event][obj].count = 0
|
||||
end
|
||||
if memdiff then
|
||||
table.insert(memstack, memdiff)
|
||||
table.insert(timestack, timediff)
|
||||
end
|
||||
memdiff, timediff = 0, 0
|
||||
mem, time = gcinfo(), GetTime()
|
||||
end
|
||||
local method = tmp[obj]
|
||||
AceEvent.UnregisterEvent(obj, event)
|
||||
if type(method) == "string" then
|
||||
local obj_method = obj[method]
|
||||
if obj_method then
|
||||
obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
elseif method then -- function
|
||||
method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
if AceEvent_debugTable then
|
||||
local dmem, dtime = memdiff, timediff
|
||||
mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff
|
||||
AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem
|
||||
AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time
|
||||
AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1
|
||||
|
||||
memdiff, timediff = table.remove(memstack), table.remove(timestack)
|
||||
if memdiff then
|
||||
memdiff = memdiff + mem + dmem
|
||||
timediff = timediff + time + dtime
|
||||
end
|
||||
end
|
||||
tmp[obj] = nil
|
||||
obj = next(tmp)
|
||||
end
|
||||
del(tmp)
|
||||
end
|
||||
|
||||
local AceEvent_throttleRegistry = AceEvent.throttleRegistry
|
||||
local throttleTable = AceEvent_throttleRegistry and AceEvent_throttleRegistry[event]
|
||||
if AceEvent_registry[event] then
|
||||
local tmp = new()
|
||||
for obj, method in pairs(AceEvent_registry[event]) do
|
||||
tmp[obj] = method
|
||||
end
|
||||
local obj = next(tmp)
|
||||
while obj do
|
||||
local method = tmp[obj]
|
||||
local continue = false
|
||||
if throttleTable and throttleTable[obj] then
|
||||
local a1 = a1
|
||||
if a1 == nil then
|
||||
a1 = FAKE_NIL
|
||||
end
|
||||
if not throttleTable[obj][a1] or GetTime() - throttleTable[obj][a1] >= throttleTable[obj][RATE] then
|
||||
throttleTable[obj][a1] = GetTime()
|
||||
else
|
||||
continue = true
|
||||
end
|
||||
end
|
||||
if not continue then
|
||||
local mem, time
|
||||
if AceEvent_debugTable then
|
||||
if not AceEvent_debugTable[event] then
|
||||
AceEvent_debugTable[event] = new()
|
||||
end
|
||||
if not AceEvent_debugTable[event][obj] then
|
||||
AceEvent_debugTable[event][obj] = new()
|
||||
AceEvent_debugTable[event][obj].mem = 0
|
||||
AceEvent_debugTable[event][obj].time = 0
|
||||
AceEvent_debugTable[event][obj].count = 0
|
||||
end
|
||||
if memdiff then
|
||||
table.insert(memstack, memdiff)
|
||||
table.insert(timestack, timediff)
|
||||
end
|
||||
memdiff, timediff = 0, 0
|
||||
mem, time = gcinfo(), GetTime()
|
||||
end
|
||||
if type(method) == "string" then
|
||||
local obj_method = obj[method]
|
||||
if obj_method then
|
||||
obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
elseif method then -- function
|
||||
method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
if AceEvent_debugTable then
|
||||
local dmem, dtime = memdiff, timediff
|
||||
mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff
|
||||
AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem
|
||||
AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time
|
||||
AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1
|
||||
|
||||
memdiff, timediff = table.remove(memstack), table.remove(timestack)
|
||||
if memdiff then
|
||||
memdiff = memdiff + mem + dmem
|
||||
timediff = timediff + time + dtime
|
||||
end
|
||||
end
|
||||
end
|
||||
tmp[obj] = nil
|
||||
obj = next(tmp)
|
||||
end
|
||||
del(tmp)
|
||||
end
|
||||
if AceEvent_registry[ALL_EVENTS] then
|
||||
local tmp = new()
|
||||
for obj, method in pairs(AceEvent_registry[ALL_EVENTS]) do
|
||||
tmp[obj] = method
|
||||
end
|
||||
local obj = next(tmp)
|
||||
while obj do
|
||||
local method = tmp[obj]
|
||||
local mem, time
|
||||
if AceEvent_debugTable then
|
||||
if not AceEvent_debugTable[event] then
|
||||
AceEvent_debugTable[event] = new()
|
||||
end
|
||||
if not AceEvent_debugTable[event][obj] then
|
||||
AceEvent_debugTable[event][obj] = new()
|
||||
AceEvent_debugTable[event][obj].mem = 0
|
||||
AceEvent_debugTable[event][obj].time = 0
|
||||
AceEvent_debugTable[event][obj].count = 0
|
||||
end
|
||||
if memdiff then
|
||||
table.insert(memstack, memdiff)
|
||||
table.insert(timestack, timediff)
|
||||
end
|
||||
memdiff, timediff = 0, 0
|
||||
mem, time = gcinfo(), GetTime()
|
||||
end
|
||||
if type(method) == "string" then
|
||||
local obj_method = obj[method]
|
||||
if obj_method then
|
||||
obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
elseif method then -- function
|
||||
method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
if AceEvent_debugTable then
|
||||
local dmem, dtime = memdiff, timediff
|
||||
mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff
|
||||
AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem
|
||||
AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time
|
||||
AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1
|
||||
|
||||
memdiff, timediff = table.remove(memstack), table.remove(timestack)
|
||||
if memdiff then
|
||||
memdiff = memdiff + mem + dmem
|
||||
timediff = timediff + time + dtime
|
||||
end
|
||||
end
|
||||
tmp[obj] = nil
|
||||
obj = next(tmp)
|
||||
end
|
||||
del(tmp)
|
||||
end
|
||||
_G.event = _G_event
|
||||
AceEvent.currentEvent = lastEvent
|
||||
end
|
||||
|
||||
-- local accessors
|
||||
local getn = table.getn
|
||||
local tinsert = table.insert
|
||||
local tremove = table.remove
|
||||
local floor = math.floor
|
||||
local GetTime = GetTime
|
||||
local next = next
|
||||
local pairs = pairs
|
||||
local unpack = unpack
|
||||
|
||||
local delayRegistry
|
||||
local tmp = {}
|
||||
local function OnUpdate()
|
||||
local t = GetTime()
|
||||
for k,v in pairs(delayRegistry) do
|
||||
tmp[k] = true
|
||||
end
|
||||
for k in pairs(tmp) do
|
||||
local v = delayRegistry[k]
|
||||
if v then
|
||||
local v_time = v.time
|
||||
if not v_time then
|
||||
delayRegistry[k] = del(v)
|
||||
elseif v_time <= t then
|
||||
local v_repeatDelay = v.repeatDelay
|
||||
if v_repeatDelay then
|
||||
-- use the event time, not the current time, else timing inaccuracies add up over time
|
||||
v.time = v_time + v_repeatDelay
|
||||
end
|
||||
local event = v.event
|
||||
local mem, time
|
||||
if AceEvent_debugTable then
|
||||
mem, time = gcinfo(), GetTime()
|
||||
end
|
||||
if type(event) == "function" then
|
||||
event(unpack(v))
|
||||
else
|
||||
AceEvent:TriggerEvent(event, unpack(v))
|
||||
end
|
||||
if AceEvent_debugTable then
|
||||
mem, time = gcinfo() - mem, GetTime() - time
|
||||
v.mem = v.mem + mem
|
||||
v.timeSpent = v.timeSpent + time
|
||||
v.count = v.count + 1
|
||||
end
|
||||
if not v_repeatDelay then
|
||||
local x = delayRegistry[k]
|
||||
if x and x.time == v_time then -- check if it was manually reset
|
||||
delayRegistry[k] = del(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for k in pairs(tmp) do
|
||||
tmp[k] = nil
|
||||
end
|
||||
if not next(delayRegistry) then
|
||||
AceEvent.frame:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local function ScheduleEvent(self, repeating, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
local id
|
||||
if type(event) == "string" or type(event) == "table" then
|
||||
if type(event) == "table" then
|
||||
if not delayRegistry or not delayRegistry[event] then
|
||||
AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.")
|
||||
end
|
||||
end
|
||||
if type(delay) ~= "number" then
|
||||
id, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20
|
||||
AceEvent:argCheck(event, 3, "string", "function", --[[ so message is right ]] "number")
|
||||
AceEvent:argCheck(delay, 4, "number")
|
||||
self:CancelScheduledEvent(id)
|
||||
end
|
||||
else
|
||||
AceEvent:argCheck(event, 2, "string", "function")
|
||||
AceEvent:argCheck(delay, 3, "number")
|
||||
end
|
||||
|
||||
if not delayRegistry then
|
||||
AceEvent.delayRegistry = new()
|
||||
delayRegistry = AceEvent.delayRegistry
|
||||
AceEvent.frame:SetScript("OnUpdate", OnUpdate)
|
||||
end
|
||||
local t
|
||||
if type(id) == "table" then
|
||||
for k in pairs(id) do
|
||||
id[k] = nil
|
||||
end
|
||||
t = id
|
||||
else
|
||||
t = new()
|
||||
end
|
||||
t[1] = a1
|
||||
t[2] = a2
|
||||
t[3] = a3
|
||||
t[4] = a4
|
||||
t[5] = a5
|
||||
t[6] = a6
|
||||
t[7] = a7
|
||||
t[8] = a8
|
||||
t[9] = a9
|
||||
t[10] = a10
|
||||
t[11] = a11
|
||||
t[12] = a12
|
||||
t[13] = a13
|
||||
t[14] = a14
|
||||
t[15] = a15
|
||||
t[16] = a16
|
||||
t[17] = a17
|
||||
t[18] = a18
|
||||
t[19] = a19
|
||||
t[20] = a20
|
||||
table_setn(t, 20)
|
||||
t.event = event
|
||||
t.time = GetTime() + delay
|
||||
t.self = self
|
||||
t.id = id or t
|
||||
t.repeatDelay = repeating and delay
|
||||
if AceEvent_debugTable then
|
||||
t.mem = 0
|
||||
t.count = 0
|
||||
t.timeSpent = 0
|
||||
end
|
||||
delayRegistry[t.id] = t
|
||||
AceEvent.frame:Show()
|
||||
return t.id
|
||||
end
|
||||
|
||||
function AceEvent:ScheduleEvent(event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if type(event) == "string" or type(event) == "table" then
|
||||
if type(event) == "table" then
|
||||
if not delayRegistry or not delayRegistry[event] then
|
||||
AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.")
|
||||
end
|
||||
end
|
||||
if type(delay) ~= "number" then
|
||||
AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number")
|
||||
AceEvent:argCheck(a1, 4, "number")
|
||||
end
|
||||
else
|
||||
AceEvent:argCheck(event, 2, "string", "function")
|
||||
AceEvent:argCheck(delay, 3, "number")
|
||||
end
|
||||
|
||||
return ScheduleEvent(self, false, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
|
||||
function AceEvent:ScheduleRepeatingEvent(event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if type(event) == "string" or type(event) == "table" then
|
||||
if type(event) == "table" then
|
||||
if not delayRegistry or not delayRegistry[event] then
|
||||
AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.")
|
||||
end
|
||||
end
|
||||
if type(delay) ~= "number" then
|
||||
AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number")
|
||||
AceEvent:argCheck(a1, 4, "number")
|
||||
end
|
||||
else
|
||||
AceEvent:argCheck(event, 2, "string", "function")
|
||||
AceEvent:argCheck(delay, 3, "number")
|
||||
end
|
||||
|
||||
return ScheduleEvent(self, true, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
|
||||
function AceEvent:CancelScheduledEvent(t)
|
||||
AceEvent:argCheck(t, 2, "string", "table")
|
||||
if delayRegistry then
|
||||
local v = delayRegistry[t]
|
||||
if v then
|
||||
delayRegistry[t] = del(v)
|
||||
if not next(delayRegistry) then
|
||||
AceEvent.frame:Hide()
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function AceEvent:IsEventScheduled(t)
|
||||
AceEvent:argCheck(t, 2, "string", "table")
|
||||
if delayRegistry then
|
||||
local v = delayRegistry[t]
|
||||
if v then
|
||||
return true, v.time - GetTime()
|
||||
end
|
||||
end
|
||||
return false, nil
|
||||
end
|
||||
|
||||
function AceEvent:UnregisterEvent(event)
|
||||
AceEvent:argCheck(event, 2, "string")
|
||||
local AceEvent_registry = AceEvent.registry
|
||||
if AceEvent_registry[event] and AceEvent_registry[event][self] then
|
||||
AceEvent_registry[event][self] = nil
|
||||
local AceEvent_onceRegistry = AceEvent.onceRegistry
|
||||
if AceEvent_onceRegistry and AceEvent_onceRegistry[event] and AceEvent_onceRegistry[event][self] then
|
||||
AceEvent_onceRegistry[event][self] = nil
|
||||
if not next(AceEvent_onceRegistry[event]) then
|
||||
AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event])
|
||||
end
|
||||
end
|
||||
local AceEvent_throttleRegistry = AceEvent.throttleRegistry
|
||||
if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] and AceEvent_throttleRegistry[event][self] then
|
||||
AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self])
|
||||
if not next(AceEvent_throttleRegistry[event]) then
|
||||
AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event])
|
||||
end
|
||||
end
|
||||
if not next(AceEvent_registry[event]) then
|
||||
AceEvent_registry[event] = del(AceEvent_registry[event])
|
||||
if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then
|
||||
AceEvent.frame:UnregisterEvent(event)
|
||||
end
|
||||
end
|
||||
else
|
||||
if self == AceEvent then
|
||||
error(string.format("Cannot unregister event %q. Improperly unregistering from AceEvent-2.0.", event), 2)
|
||||
else
|
||||
AceEvent:error("Cannot unregister event %q. %q is not registered with it.", event, self)
|
||||
end
|
||||
end
|
||||
AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event)
|
||||
end
|
||||
|
||||
function AceEvent:UnregisterAllEvents()
|
||||
local AceEvent_registry = AceEvent.registry
|
||||
if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then
|
||||
AceEvent_registry[ALL_EVENTS][self] = nil
|
||||
if not next(AceEvent_registry[ALL_EVENTS]) then
|
||||
del(AceEvent_registry[ALL_EVENTS])
|
||||
AceEvent.frame:UnregisterAllEvents()
|
||||
for k,v in pairs(AceEvent_registry) do
|
||||
if k ~= ALL_EVENTS then
|
||||
AceEvent.frame:RegisterEvent(k)
|
||||
end
|
||||
end
|
||||
AceEvent_registry[event] = nil
|
||||
end
|
||||
end
|
||||
local first = true
|
||||
for event, data in pairs(AceEvent_registry) do
|
||||
if first then
|
||||
if AceEvent_registry.AceEvent_EventUnregistered then
|
||||
event = "AceEvent_EventUnregistered"
|
||||
else
|
||||
first = false
|
||||
end
|
||||
end
|
||||
local x = data[self]
|
||||
data[self] = nil
|
||||
if x and event ~= ALL_EVENTS then
|
||||
if not next(data) then
|
||||
del(data)
|
||||
if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then
|
||||
AceEvent.frame:UnregisterEvent(event)
|
||||
end
|
||||
AceEvent_registry[event] = nil
|
||||
end
|
||||
AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event)
|
||||
end
|
||||
if first then
|
||||
event = nil
|
||||
end
|
||||
end
|
||||
if AceEvent.onceRegistry then
|
||||
for event, data in pairs(AceEvent.onceRegistry) do
|
||||
data[self] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceEvent:CancelAllScheduledEvents()
|
||||
if delayRegistry then
|
||||
for k,v in pairs(delayRegistry) do
|
||||
if v.self == self then
|
||||
delayRegistry[k] = del(v)
|
||||
end
|
||||
end
|
||||
if not next(delayRegistry) then
|
||||
AceEvent.frame:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceEvent:IsEventRegistered(event)
|
||||
AceEvent:argCheck(event, 2, "string")
|
||||
local AceEvent_registry = AceEvent.registry
|
||||
if self == AceEvent then
|
||||
return AceEvent_registry[event] and next(AceEvent_registry[event]) and true or false
|
||||
end
|
||||
if AceEvent_registry[event] and AceEvent_registry[event][self] then
|
||||
return true, AceEvent_registry[event][self]
|
||||
end
|
||||
return false, nil
|
||||
end
|
||||
|
||||
local bucketfunc
|
||||
function AceEvent:RegisterBucketEvent(event, delay, method)
|
||||
AceEvent:argCheck(event, 2, "string", "table")
|
||||
if type(event) == "table" then
|
||||
for k,v in pairs(event) do
|
||||
if type(k) ~= "number" then
|
||||
AceEvent:error("All keys to argument #2 to `RegisterBucketEvent' must be numbers.")
|
||||
elseif type(v) ~= "string" then
|
||||
AceEvent:error("All values to argument #2 to `RegisterBucketEvent' must be strings.")
|
||||
end
|
||||
end
|
||||
end
|
||||
AceEvent:argCheck(delay, 3, "number")
|
||||
if AceEvent == self then
|
||||
AceEvent:argCheck(method, 4, "function")
|
||||
self = method
|
||||
else
|
||||
if type(event) == "string" then
|
||||
AceEvent:argCheck(method, 4, "string", "function", "nil")
|
||||
if not method then
|
||||
method = event
|
||||
end
|
||||
else
|
||||
AceEvent:argCheck(method, 4, "string", "function")
|
||||
end
|
||||
|
||||
if type(method) == "string" and type(self[method]) ~= "function" then
|
||||
AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method)
|
||||
end
|
||||
end
|
||||
if not AceEvent.buckets then
|
||||
AceEvent.buckets = new()
|
||||
end
|
||||
if not AceEvent.buckets[event] then
|
||||
AceEvent.buckets[event] = new()
|
||||
end
|
||||
if not AceEvent.buckets[event][self] then
|
||||
AceEvent.buckets[event][self] = new()
|
||||
AceEvent.buckets[event][self].current = new()
|
||||
AceEvent.buckets[event][self].self = self
|
||||
else
|
||||
AceEvent.CancelScheduledEvent(self, AceEvent.buckets[event][self].id)
|
||||
end
|
||||
local bucket = AceEvent.buckets[event][self]
|
||||
bucket.method = method
|
||||
|
||||
local func = function(arg1)
|
||||
bucket.run = true
|
||||
if arg1 then
|
||||
bucket.current[arg1] = true
|
||||
end
|
||||
end
|
||||
AceEvent.buckets[event][self].func = func
|
||||
if type(event) == "string" then
|
||||
AceEvent.RegisterEvent(self, event, func)
|
||||
else
|
||||
for _,v in ipairs(event) do
|
||||
AceEvent.RegisterEvent(self, v, func)
|
||||
end
|
||||
end
|
||||
if not bucketfunc then
|
||||
bucketfunc = function(bucket)
|
||||
local current = bucket.current
|
||||
local method = bucket.method
|
||||
local self = bucket.self
|
||||
if bucket.run then
|
||||
if type(method) == "string" then
|
||||
self[method](self, current)
|
||||
elseif method then -- function
|
||||
method(current)
|
||||
end
|
||||
for k in pairs(current) do
|
||||
current[k] = nil
|
||||
k = nil
|
||||
end
|
||||
bucket.run = false
|
||||
end
|
||||
end
|
||||
end
|
||||
bucket.id = AceEvent.ScheduleRepeatingEvent(self, bucketfunc, delay, bucket)
|
||||
end
|
||||
|
||||
function AceEvent:IsBucketEventRegistered(event)
|
||||
AceEvent:argCheck(event, 2, "string", "table")
|
||||
return AceEvent.buckets and AceEvent.buckets[event] and AceEvent.buckets[event][self]
|
||||
end
|
||||
|
||||
function AceEvent:UnregisterBucketEvent(event)
|
||||
AceEvent:argCheck(event, 2, "string", "table")
|
||||
if not AceEvent.buckets or not AceEvent.buckets[event] or not AceEvent.buckets[event][self] then
|
||||
AceEvent:error("Cannot unregister bucket event %q. %q is not registered with it.", event, self)
|
||||
end
|
||||
|
||||
local bucket = AceEvent.buckets[event][self]
|
||||
|
||||
if type(event) == "string" then
|
||||
AceEvent.UnregisterEvent(self, event)
|
||||
else
|
||||
for _,v in ipairs(event) do
|
||||
AceEvent.UnregisterEvent(self, v)
|
||||
end
|
||||
end
|
||||
AceEvent:CancelScheduledEvent(bucket.id)
|
||||
|
||||
del(bucket.current)
|
||||
AceEvent.buckets[event][self] = del(AceEvent.buckets[event][self])
|
||||
if not next(AceEvent.buckets[event]) then
|
||||
AceEvent.buckets[event] = del(AceEvent.buckets[event])
|
||||
end
|
||||
end
|
||||
|
||||
function AceEvent:UnregisterAllBucketEvents()
|
||||
if not AceEvent.buckets or not next(AceEvent.buckets) then
|
||||
return
|
||||
end
|
||||
for k,v in pairs(AceEvent.buckets) do
|
||||
if v == self then
|
||||
AceEvent.UnregisterBucketEvent(self, k)
|
||||
k = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceEvent:OnEmbedDisable(target)
|
||||
self.UnregisterAllEvents(target)
|
||||
|
||||
self.CancelAllScheduledEvents(target)
|
||||
|
||||
self.UnregisterAllBucketEvents(target)
|
||||
end
|
||||
|
||||
function AceEvent:EnableDebugging()
|
||||
if not self.debugTable then
|
||||
self.debugTable = new()
|
||||
|
||||
if delayRegistry then
|
||||
for k,v in pairs(self.delayRegistry) do
|
||||
if not v.mem then
|
||||
v.mem = 0
|
||||
v.count = 0
|
||||
v.timeSpent = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceEvent:IsFullyInitialized()
|
||||
return self.postInit or false
|
||||
end
|
||||
|
||||
function AceEvent:IsPostPlayerLogin()
|
||||
return self.playerLogin or false
|
||||
end
|
||||
|
||||
function AceEvent:activate(oldLib, oldDeactivate)
|
||||
AceEvent = self
|
||||
|
||||
if oldLib then
|
||||
self.onceRegistry = oldLib.onceRegistry
|
||||
self.throttleRegistry = oldLib.throttleRegistry
|
||||
self.delayRegistry = oldLib.delayRegistry
|
||||
self.buckets = oldLib.buckets
|
||||
self.registry = oldLib.registry
|
||||
self.frame = oldLib.frame
|
||||
self.debugTable = oldLib.debugTable
|
||||
self.playerLogin = oldLib.pew or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage and true
|
||||
self.postInit = oldLib.postInit or self.playerLogin and ChatTypeInfo and ChatTypeInfo.WHISPER and ChatTypeInfo.WHISPER.r and true
|
||||
self.ALL_EVENTS = oldLib.ALL_EVENTS
|
||||
self.FAKE_NIL = oldLib.FAKE_NIL
|
||||
self.RATE = oldLib.RATE
|
||||
end
|
||||
if not self.registry then
|
||||
self.registry = {}
|
||||
end
|
||||
if not self.frame then
|
||||
self.frame = CreateFrame("Frame", "AceEvent20Frame")
|
||||
end
|
||||
if not self.ALL_EVENTS then
|
||||
self.ALL_EVENTS = {}
|
||||
end
|
||||
if not self.FAKE_NIL then
|
||||
self.FAKE_NIL = {}
|
||||
end
|
||||
if not self.RATE then
|
||||
self.RATE = {}
|
||||
end
|
||||
ALL_EVENTS = self.ALL_EVENTS
|
||||
FAKE_NIL = self.FAKE_NIL
|
||||
RATE = self.RATE
|
||||
local inPlw = false
|
||||
local blacklist = {
|
||||
UNIT_INVENTORY_CHANGED = true,
|
||||
BAG_UPDATE = true,
|
||||
ITEM_LOCK_CHANGED = true,
|
||||
ACTIONBAR_SLOT_CHANGED = true,
|
||||
}
|
||||
self.frame:SetScript("OnEvent", function()
|
||||
local event = event
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
inPlw = false
|
||||
elseif event == "PLAYER_LEAVING_WORLD" then
|
||||
inPlw = true
|
||||
end
|
||||
if event and (not inPlw or not blacklist[event]) then
|
||||
self:TriggerEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
|
||||
end
|
||||
end)
|
||||
if self.delayRegistry then
|
||||
delayRegistry = self.delayRegistry
|
||||
self.frame:SetScript("OnUpdate", OnUpdate)
|
||||
end
|
||||
|
||||
self:UnregisterAllEvents()
|
||||
self:CancelAllScheduledEvents()
|
||||
|
||||
registeringFromAceEvent = true
|
||||
self:RegisterEvent("LOOT_OPENED", function()
|
||||
SendAddonMessage("LOOT_OPENED", "", "RAID")
|
||||
end)
|
||||
registeringFromAceEvent = nil
|
||||
|
||||
if not self.playerLogin then
|
||||
registeringFromAceEvent = true
|
||||
self:RegisterEvent("PLAYER_LOGIN", function()
|
||||
self.playerLogin = true
|
||||
end, true)
|
||||
registeringFromAceEvent = nil
|
||||
end
|
||||
|
||||
if not self.postInit then
|
||||
local isReload = true
|
||||
local function func()
|
||||
self.postInit = true
|
||||
self:TriggerEvent("AceEvent_FullyInitialized")
|
||||
if self.registry["CHAT_MSG_CHANNEL_NOTICE"] and self.registry["CHAT_MSG_CHANNEL_NOTICE"][self] then
|
||||
self:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE")
|
||||
end
|
||||
if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then
|
||||
self:UnregisterEvent("MEETINGSTONE_CHANGED")
|
||||
end
|
||||
if self.registry["MINIMAP_ZONE_CHANGED"] and self.registry["MINIMAP_ZONE_CHANGED"][self] then
|
||||
self:UnregisterEvent("MINIMAP_ZONE_CHANGED")
|
||||
end
|
||||
if self.registry["LANGUAGE_LIST_CHANGED"] and self.registry["LANGUAGE_LIST_CHANGED"][self] then
|
||||
self:UnregisterEvent("LANGUAGE_LIST_CHANGED")
|
||||
end
|
||||
end
|
||||
registeringFromAceEvent = true
|
||||
local f = function()
|
||||
self.playerLogin = true
|
||||
self:ScheduleEvent("AceEvent_FullyInitialized", func, 1)
|
||||
end
|
||||
self:RegisterEvent("MEETINGSTONE_CHANGED", f, true)
|
||||
self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", function()
|
||||
self:ScheduleEvent("AceEvent_FullyInitialized", func, 0.05)
|
||||
end)
|
||||
self:RegisterEvent("LANGUAGE_LIST_CHANGED", function()
|
||||
if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then
|
||||
registeringFromAceEvent = true
|
||||
self:UnregisterEvent("MEETINGSTONE_CHANGED")
|
||||
self:RegisterEvent("MINIMAP_ZONE_CHANGED", f, true)
|
||||
registeringFromAceEvent = nil
|
||||
end
|
||||
end)
|
||||
self:ScheduleEvent("AceEvent_FullyInitialized", func, 10)
|
||||
registeringFromAceEvent = nil
|
||||
end
|
||||
|
||||
self.super.activate(self, oldLib, oldDeactivate)
|
||||
if oldLib then
|
||||
oldDeactivate(oldLib)
|
||||
end
|
||||
end
|
||||
|
||||
AceLibrary:Register(AceEvent, MAJOR_VERSION, MINOR_VERSION, AceEvent.activate)
|
||||
AceEvent = AceLibrary(MAJOR_VERSION)
|
||||
@@ -0,0 +1,569 @@
|
||||
--[[
|
||||
Name: AceHook-2.1
|
||||
Revision: $Rev: 17638 $
|
||||
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
||||
Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
||||
Website: http://www.wowace.com/
|
||||
Documentation: http://www.wowace.com/index.php/AceHook-2.1
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceHook-2.1
|
||||
Description: Mixin to allow for safe hooking of functions, methods, and scripts.
|
||||
Dependencies: AceLibrary, AceOO-2.0
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceHook-2.1"
|
||||
local MINOR_VERSION = "$Revision: 17638 $"
|
||||
|
||||
-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check
|
||||
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Create the library object
|
||||
----------------------------------------------------------------------------------]]
|
||||
|
||||
local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
||||
local AceHook = AceOO.Mixin {
|
||||
"Hook",
|
||||
"HookScript",
|
||||
"SecureHook",
|
||||
"Unhook",
|
||||
"UnhookAll",
|
||||
"HookReport",
|
||||
"IsHooked",
|
||||
}
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Library Definitions
|
||||
----------------------------------------------------------------------------------]]
|
||||
|
||||
local protFuncs = {
|
||||
CameraOrSelectOrMoveStart = true, CameraOrSelectOrMoveStop = true,
|
||||
TurnOrActionStart = true, TurnOrActionStop = true,
|
||||
PitchUpStart = true, PitchUpStop = true,
|
||||
PitchDownStart = true, PitchDownStop = true,
|
||||
MoveBackwardStart = true, MoveBackwardStop = true,
|
||||
MoveForwardStart = true, MoveForwardStop = true,
|
||||
Jump = true, StrafeLeftStart = true,
|
||||
StrafeLeftStop = true, StrafeRightStart = true,
|
||||
StrafeRightStop = true, ToggleMouseMove = true,
|
||||
ToggleRun = true, TurnLeftStart = true,
|
||||
TurnLeftStop = true, TurnRightStart = true,
|
||||
TurnRightStop = true,
|
||||
}
|
||||
|
||||
local function issecurevariable(x)
|
||||
if protFuncs[x] then
|
||||
return 1
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local _G = getfenv(0)
|
||||
|
||||
local function hooksecurefunc(arg1, arg2, arg3)
|
||||
if type(arg1) == "string" then
|
||||
arg1, arg2, arg3 = _G, arg1, arg2
|
||||
end
|
||||
local orig = arg1[arg2]
|
||||
arg1[arg2] = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
local x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20 = orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
|
||||
arg3(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
|
||||
return x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20
|
||||
end
|
||||
end
|
||||
|
||||
local protectedScripts = {
|
||||
OnClick = true,
|
||||
}
|
||||
|
||||
|
||||
local handlers, scripts, actives, registry
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Private definitions (Not exposed)
|
||||
----------------------------------------------------------------------------------]]
|
||||
|
||||
local new, del
|
||||
do
|
||||
local list = setmetatable({}, {__mode = "k"})
|
||||
function new()
|
||||
local t = next(list)
|
||||
if not t then
|
||||
return {}
|
||||
end
|
||||
list[t] = nil
|
||||
return t
|
||||
end
|
||||
|
||||
function del(t)
|
||||
setmetatable(t, nil)
|
||||
for k in pairs(t) do
|
||||
t[k] = nil
|
||||
end
|
||||
list[t] = true
|
||||
end
|
||||
end
|
||||
|
||||
local function createFunctionHook(self, func, handler, orig, secure)
|
||||
if not secure then
|
||||
if type(handler) == "string" then
|
||||
-- The handler is a method, need to self it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
else
|
||||
-- secure hooks don't call the original method
|
||||
if type(handler) == "string" then
|
||||
-- The handler is a method, need to self it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function createMethodHook(self, object, method, handler, orig, secure, script)
|
||||
if script then
|
||||
if type(handler) == "string" then
|
||||
local uid
|
||||
uid = function()
|
||||
if actives[uid] then
|
||||
return self[handler](self, object)
|
||||
else
|
||||
return orig()
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function()
|
||||
if actives[uid] then
|
||||
return handler(object)
|
||||
else
|
||||
return orig()
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
elseif not secure then
|
||||
if type(handler) == "string" then
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
else
|
||||
-- secure hooks don't call the original method
|
||||
if type(handler) == "string" then
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function hookFunction(self, func, handler, secure)
|
||||
local orig = _G[func]
|
||||
|
||||
if not orig or type(orig) ~= "function" then
|
||||
AceHook:error("Attempt to hook a non-existant function %q", func)
|
||||
end
|
||||
|
||||
if not handler then
|
||||
handler = func
|
||||
end
|
||||
|
||||
if registry[self][func] then
|
||||
local uid = registry[self][func]
|
||||
|
||||
if actives[uid] then
|
||||
-- We have an active hook from this source. Don't multi-hook
|
||||
AceHook:error("%q already has an active hook from this source.", func)
|
||||
end
|
||||
|
||||
if handlers[uid] == handler then
|
||||
-- The hook is inactive, so reactivate it
|
||||
actives[uid] = true
|
||||
return
|
||||
else
|
||||
AceHook:error("There is a stale hook for %q can't hook or reactivate.", func)
|
||||
end
|
||||
end
|
||||
|
||||
if type(handler) == "string" then
|
||||
if type(self[handler]) ~= "function" then
|
||||
AceHook:error("Could not find the the handler %q when hooking function %q", handler, func)
|
||||
end
|
||||
elseif type(handler) ~= "function" then
|
||||
AceHook:error("Could not find the handler you supplied when hooking %q", func)
|
||||
end
|
||||
|
||||
local uid = createFunctionHook(self, func, handler, orig, secure)
|
||||
registry[self][func] = uid
|
||||
actives[uid] = true
|
||||
handlers[uid] = handler
|
||||
|
||||
if not secure then
|
||||
_G[func] = uid
|
||||
self.hooks[func] = orig
|
||||
else
|
||||
hooksecurefunc(func, uid)
|
||||
end
|
||||
end
|
||||
|
||||
local function unhookFunction(self, func)
|
||||
if not registry[self][func] then
|
||||
AceHook:error("Tried to unhook %q which is not currently hooked.", func)
|
||||
end
|
||||
|
||||
local uid = registry[self][func]
|
||||
|
||||
if actives[uid] then
|
||||
-- See if we own the global function
|
||||
if self.hooks[func] and _G[func] == uid then
|
||||
_G[func] = self.hooks[func]
|
||||
self.hooks[func] = nil
|
||||
registry[self][func] = nil
|
||||
handlers[uid] = nil
|
||||
scripts[uid] = nil
|
||||
actives[uid] = nil
|
||||
-- Magically all-done
|
||||
else
|
||||
actives[uid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function hookMethod(self, obj, method, handler, script, secure)
|
||||
if not handler then
|
||||
handler = method
|
||||
end
|
||||
|
||||
if not obj or type(obj) ~= "table" then
|
||||
AceHook:error("The object you supplied could not be found, or isn't a table.")
|
||||
end
|
||||
|
||||
local uid = registry[self][obj] and registry[self][obj][method]
|
||||
if uid then
|
||||
if actives[uid] then
|
||||
-- We have an active hook from this source. Don't multi-hook
|
||||
AceHook:error("%q already has an active hook from this source.", method)
|
||||
end
|
||||
|
||||
if handlers[uid] == handler then
|
||||
-- The hook is inactive, reactivate it.
|
||||
actives[uid] = true
|
||||
return
|
||||
else
|
||||
AceHook:error("There is a stale hook for %q can't hook or reactivate.", method)
|
||||
end
|
||||
end
|
||||
|
||||
if type(handler) == "string" then
|
||||
if type(self[handler]) ~= "function" then
|
||||
AceHook:error("Could not find the handler %q you supplied when hooking method %q", handler, method)
|
||||
end
|
||||
elseif type(handler) ~= "function" then
|
||||
AceHook:error("Could not find the handler you supplied when hooking method %q", method)
|
||||
end
|
||||
|
||||
local orig
|
||||
if script then
|
||||
if not obj.GetScript then
|
||||
AceHook:error("The object you supplied does not have a GetScript method.")
|
||||
end
|
||||
if not obj:HasScript(method) then
|
||||
AceHook:error("The object you supplied doesn't allow the %q method.", method)
|
||||
end
|
||||
|
||||
orig = obj:GetScript(method)
|
||||
if type(orig) ~= "function" then
|
||||
-- Sometimes there is not a original function for a script.
|
||||
orig = function() end
|
||||
end
|
||||
else
|
||||
orig = obj[method]
|
||||
end
|
||||
if not orig then
|
||||
AceHook:error("Could not find the method or script %q you are trying to hook.", method)
|
||||
end
|
||||
|
||||
if not registry[self][obj] then
|
||||
registry[self][obj] = new()
|
||||
end
|
||||
|
||||
if not self.hooks[obj] then
|
||||
self.hooks[obj] = new()
|
||||
end
|
||||
|
||||
local uid = createMethodHook(self, obj, method, handler, orig, secure, script)
|
||||
registry[self][obj][method] = uid
|
||||
actives[uid] = true
|
||||
handlers[uid] = handler
|
||||
scripts[uid] = script and true or nil
|
||||
|
||||
if script then
|
||||
obj:SetScript(method, uid)
|
||||
self.hooks[obj][method] = orig
|
||||
elseif not secure then
|
||||
obj[method] = uid
|
||||
self.hooks[obj][method] = orig
|
||||
else
|
||||
hooksecurefunc(obj, method, uid)
|
||||
end
|
||||
end
|
||||
|
||||
local function unhookMethod(self, obj, method)
|
||||
if not registry[self][obj] or not registry[self][obj][method] then
|
||||
AceHook:error("Attempt to unhook a method %q that is not currently hooked.", method)
|
||||
return
|
||||
end
|
||||
|
||||
local uid = registry[self][obj][method]
|
||||
|
||||
if actives[uid] then
|
||||
if scripts[uid] then -- If this is a script
|
||||
if obj:GetScript(method) == uid then
|
||||
-- We own the script. Revert to normal.
|
||||
obj:SetScript(method, self.hooks[obj][method])
|
||||
self.hooks[obj][method] = nil
|
||||
registry[self][obj][method] = nil
|
||||
handlers[uid] = nil
|
||||
scripts[uid] = nil
|
||||
actives[uid] = nil
|
||||
else
|
||||
actives[uid] = nil
|
||||
end
|
||||
else
|
||||
if self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then
|
||||
-- We own the method. Revert to normal.
|
||||
obj[method] = self.hooks[obj][method]
|
||||
self.hooks[obj][method] = nil
|
||||
registry[self][obj][method] = nil
|
||||
handlers[uid] = nil
|
||||
actives[uid] = nil
|
||||
else
|
||||
actives[uid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if self.hooks[obj] and not next(self.hooks[obj]) then
|
||||
self.hooks[obj] = del(self.hooks[obj])
|
||||
end
|
||||
if not next(registry[self][obj]) then
|
||||
registry[self][obj] = del(registry[self][obj])
|
||||
end
|
||||
end
|
||||
|
||||
-- ("function" [, handler] [, hookSecure]) or (object, "method" [, handler] [, hookSecure])
|
||||
function AceHook:Hook(object, method, handler, hookSecure)
|
||||
if type(object) == "string" then
|
||||
method, handler, hookSecure = object, method, handler
|
||||
if handler == true then
|
||||
handler, hookSecure = nil, true
|
||||
end
|
||||
if not hookSecure and issecurevariable(method) then
|
||||
AceHook:error("Attempt to hook secure function %q. Use `SecureHook' or add `true' to the argument list to override.", method)
|
||||
end
|
||||
AceHook:argCheck(handler, 3, "function", "string", "nil")
|
||||
AceHook:argCheck(hookSecure, 4, "boolean", "nil")
|
||||
hookFunction(self, method, handler, false)
|
||||
else
|
||||
if handler == true then
|
||||
handler, hookSecure = nil, true
|
||||
end
|
||||
if not hookSecure and issecurevariable(object, method) then
|
||||
AceHook:error("Attempt to hook secure method %q. Use `SecureHook' or add `true' to the argument list to override.", method)
|
||||
end
|
||||
AceHook:argCheck(object, 2, "table")
|
||||
AceHook:argCheck(method, 3, "string")
|
||||
AceHook:argCheck(handler, 4, "function", "string", "nil")
|
||||
AceHook:argCheck(hookSecure, 5, "boolean", "nil")
|
||||
hookMethod(self, object, method, handler, false, false)
|
||||
end
|
||||
end
|
||||
|
||||
-- ("function", handler) or (object, "method", handler)
|
||||
function AceHook:SecureHook(object, method, handler)
|
||||
if type(object) == "string" then
|
||||
method, handler = object, method
|
||||
AceHook:argCheck(handler, 3, "function", "string", "nil")
|
||||
hookFunction(self, method, handler, true)
|
||||
else
|
||||
AceHook:argCheck(object, 2, "table")
|
||||
AceHook:argCheck(method, 3, "string")
|
||||
AceHook:argCheck(handler, 4, "function", "string", "nil")
|
||||
hookMethod(self, object, method, handler, false, true)
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:HookScript(frame, script, handler)
|
||||
AceHook:argCheck(frame, 2, "table")
|
||||
if not frame[0] or type(frame.IsFrameType) ~= "function" then
|
||||
AceHook:error("Bad argument #2 to `HookScript'. Expected frame.")
|
||||
end
|
||||
AceHook:argCheck(script, 3, "string")
|
||||
AceHook:argCheck(handler, 4, "function", "string", "nil")
|
||||
hookMethod(self, frame, script, handler, true, false)
|
||||
end
|
||||
|
||||
-- ("function") or (object, "method")
|
||||
function AceHook:IsHooked(obj, method)
|
||||
if type(obj) == "string" then
|
||||
if registry[self][obj] and actives[registry[self][obj]] then
|
||||
return true, handlers[registry[self][obj]]
|
||||
end
|
||||
else
|
||||
AceHook:argCheck(obj, 2, "string", "table")
|
||||
AceHook:argCheck(method, 3, "string")
|
||||
if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then
|
||||
return true, handlers[registry[self][obj][method]]
|
||||
end
|
||||
end
|
||||
|
||||
return false, nil
|
||||
end
|
||||
|
||||
-- ("function") or (object, "method")
|
||||
function AceHook:Unhook(obj, method)
|
||||
if type(obj) == "string" then
|
||||
unhookFunction(self, obj)
|
||||
else
|
||||
AceHook:argCheck(obj, 2, "string", "table")
|
||||
AceHook:argCheck(method, 3, "string")
|
||||
unhookMethod(self, obj, method)
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:UnhookAll()
|
||||
for key, value in pairs(registry[self]) do
|
||||
if type(key) == "table" then
|
||||
for method in pairs(value) do
|
||||
self:Unhook(key, method)
|
||||
end
|
||||
else
|
||||
self:Unhook(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:HookReport()
|
||||
DEFAULT_CHAT_FRAME:AddMessage("This is a list of all active hooks for this object:")
|
||||
if not next(registry[self]) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("No hooks")
|
||||
end
|
||||
|
||||
for key, value in pairs(registry[self]) do
|
||||
if type(value) == "table" then
|
||||
for method, uid in pairs(value) do
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("object: %s method: %q |cff%s|r%s", tostring(key), method, actives[uid] and "00ff00Active" or "ffff00Inactive", not self.hooks[key][method] and " |cff7f7fff-Secure-|r" or ""))
|
||||
end
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("function: %q |cff%s|r%s", tostring(key), actives[value] and "00ff00Active" or "ffff00Inactive", not self.hooks[key] and " |cff7f7fff-Secure-|r" or ""))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:OnInstanceInit(object)
|
||||
if not object.hooks then
|
||||
object.hooks = new()
|
||||
end
|
||||
if not registry[object] then
|
||||
registry[object] = new()
|
||||
end
|
||||
end
|
||||
|
||||
AceHook.OnManualEmbed = AceHook.OnInstanceInit
|
||||
|
||||
function AceHook:OnEmbedDisable(target)
|
||||
self.UnhookAll(target)
|
||||
end
|
||||
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
AceHook = self
|
||||
|
||||
self.handlers = oldLib and oldLib.handlers or {}
|
||||
self.registry = oldLib and oldLib.registry or {}
|
||||
self.scripts = oldLib and oldLib.scripts or {}
|
||||
self.actives = oldLib and oldLib.actives or {}
|
||||
|
||||
handlers = self.handlers
|
||||
registry = self.registry
|
||||
scripts = self.scripts
|
||||
actives = self.actives
|
||||
|
||||
AceHook.super.activate(self, oldLib, oldDeactivate)
|
||||
|
||||
if oldDeactivate then
|
||||
oldDeactivate(oldLib)
|
||||
end
|
||||
end
|
||||
|
||||
AceLibrary:Register(AceHook, MAJOR_VERSION, MINOR_VERSION, activate)
|
||||
@@ -0,0 +1,757 @@
|
||||
--[[
|
||||
Name: AceLibrary
|
||||
Revision: $Rev: 17722 $
|
||||
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
||||
Inspired By: Iriel (iriel@vigilance-committee.org)
|
||||
Tekkub (tekkub@gmail.com)
|
||||
Revision: $Rev: 17722 $
|
||||
Website: http://www.wowace.com/
|
||||
Documentation: http://www.wowace.com/index.php/AceLibrary
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary
|
||||
Description: Versioning library to handle other library instances, upgrading,
|
||||
and proper access.
|
||||
It also provides a base for libraries to work off of, providing
|
||||
proper error tools. It is handy because all the errors occur in the
|
||||
file that called it, not in the library file itself.
|
||||
Dependencies: None
|
||||
]]
|
||||
|
||||
local ACELIBRARY_MAJOR = "AceLibrary"
|
||||
local ACELIBRARY_MINOR = "$Revision: 17722 $"
|
||||
|
||||
if loadstring("return function(...) return ... end") and AceLibrary and AceLibrary:HasInstance(ACELIBRARY_MAJOR) then return end -- lua51 check
|
||||
local table_setn
|
||||
do
|
||||
local version = GetBuildInfo()
|
||||
if string.find(version, "^2%.") then
|
||||
-- 2.0.0
|
||||
table_setn = function() end
|
||||
else
|
||||
table_setn = table.setn
|
||||
end
|
||||
end
|
||||
|
||||
local string_gfind = string.gmatch or string.gfind
|
||||
|
||||
local _G = getfenv(0)
|
||||
local previous = _G[ACELIBRARY_MAJOR]
|
||||
if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end
|
||||
|
||||
local function safecall(func,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
local success, err = pcall(func,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
if not success then geterrorhandler()(err) end
|
||||
end
|
||||
|
||||
-- @table AceLibrary
|
||||
-- @brief System to handle all versioning of libraries.
|
||||
local AceLibrary = {}
|
||||
local AceLibrary_mt = {}
|
||||
setmetatable(AceLibrary, AceLibrary_mt)
|
||||
|
||||
local tmp
|
||||
local function error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if type(self) ~= "table" then
|
||||
_G.error(string.format("Bad argument #1 to `error' (table expected, got %s)", type(self)), 2)
|
||||
end
|
||||
if not tmp then
|
||||
tmp = {}
|
||||
else
|
||||
for k in pairs(tmp) do tmp[k] = nil end
|
||||
table_setn(tmp, 0)
|
||||
end
|
||||
|
||||
table.insert(tmp, a1)
|
||||
table.insert(tmp, a2)
|
||||
table.insert(tmp, a3)
|
||||
table.insert(tmp, a4)
|
||||
table.insert(tmp, a5)
|
||||
table.insert(tmp, a6)
|
||||
table.insert(tmp, a7)
|
||||
table.insert(tmp, a8)
|
||||
table.insert(tmp, a9)
|
||||
table.insert(tmp, a10)
|
||||
table.insert(tmp, a11)
|
||||
table.insert(tmp, a12)
|
||||
table.insert(tmp, a13)
|
||||
table.insert(tmp, a14)
|
||||
table.insert(tmp, a15)
|
||||
table.insert(tmp, a16)
|
||||
table.insert(tmp, a17)
|
||||
table.insert(tmp, a18)
|
||||
table.insert(tmp, a19)
|
||||
table.insert(tmp, a20)
|
||||
|
||||
local stack = debugstack()
|
||||
if not message then
|
||||
local _,_,second = string.find(stack, "\n(.-)\n")
|
||||
message = "error raised! " .. second
|
||||
else
|
||||
for i = 1,table.getn(tmp) do
|
||||
tmp[i] = tostring(tmp[i])
|
||||
end
|
||||
for i = 1,10 do
|
||||
table.insert(tmp, "nil")
|
||||
end
|
||||
message = string.format(message, unpack(tmp))
|
||||
end
|
||||
|
||||
if getmetatable(self) and getmetatable(self).__tostring then
|
||||
message = string.format("%s: %s", tostring(self), message)
|
||||
elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then
|
||||
message = string.format("%s: %s", self:GetLibraryVersion(), message)
|
||||
elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then
|
||||
message = string.format("%s: %s", self.class:GetLibraryVersion(), message)
|
||||
end
|
||||
|
||||
local first = string.gsub(stack, "\n.*", "")
|
||||
local file = string.gsub(first, ".*\\(.*).lua:%d+: .*", "%1")
|
||||
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
||||
|
||||
local i = 0
|
||||
for s in string_gfind(stack, "\n([^\n]*)") do
|
||||
i = i + 1
|
||||
if not string.find(s, file .. "%.lua:%d+:") then
|
||||
file = string.gsub(s, "^.*\\(.*).lua:%d+: .*", "%1")
|
||||
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
||||
break
|
||||
end
|
||||
end
|
||||
local j = 0
|
||||
for s in string_gfind(stack, "\n([^\n]*)") do
|
||||
j = j + 1
|
||||
if j > i and not string.find(s, file .. "%.lua:%d+:") then
|
||||
_G.error(message, j + 1)
|
||||
return
|
||||
end
|
||||
end
|
||||
_G.error(message, 2)
|
||||
return
|
||||
end
|
||||
|
||||
local function assert(self, condition, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not condition then
|
||||
if not message then
|
||||
local stack = debugstack()
|
||||
local _,_,second = string.find(stack, "\n(.-)\n")
|
||||
message = "assertion failed! " .. second
|
||||
end
|
||||
error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
return
|
||||
end
|
||||
return condition
|
||||
end
|
||||
|
||||
local function argCheck(self, arg, num, kind, kind2, kind3, kind4, kind5)
|
||||
if type(num) ~= "number" then
|
||||
error(self, "Bad argument #3 to `argCheck' (number expected, got %s)", type(num))
|
||||
elseif type(kind) ~= "string" then
|
||||
error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind))
|
||||
end
|
||||
local errored = false
|
||||
arg = type(arg)
|
||||
if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then
|
||||
local _,_,func = string.find(debugstack(), "`argCheck'.-([`<].-['>])")
|
||||
if not func then
|
||||
_,_,func = string.find(debugstack(), "([`<].-['>])")
|
||||
end
|
||||
if kind5 then
|
||||
error(self, "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, kind5, arg)
|
||||
elseif kind4 then
|
||||
error(self, "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, arg)
|
||||
elseif kind3 then
|
||||
error(self, "Bad argument #%s to %s (%s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, arg)
|
||||
elseif kind2 then
|
||||
error(self, "Bad argument #%s to %s (%s or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, arg)
|
||||
else
|
||||
error(self, "Bad argument #%s to %s (%s expected, got %s)", tonumber(num) or 0/0, func, kind, arg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function pcall(self, func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = _G.pcall(func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not a1 then
|
||||
error(self, string.gsub(a2, ".-%.lua:%d-: ", ""))
|
||||
else
|
||||
return a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20
|
||||
end
|
||||
end
|
||||
|
||||
local recurse = {}
|
||||
local function addToPositions(t, major)
|
||||
if not AceLibrary.positions[t] or AceLibrary.positions[t] == major then
|
||||
rawset(t, recurse, true)
|
||||
AceLibrary.positions[t] = major
|
||||
for k,v in pairs(t) do
|
||||
if type(v) == "table" and not rawget(v, recurse) then
|
||||
addToPositions(v, major)
|
||||
end
|
||||
if type(k) == "table" and not rawget(k, recurse) then
|
||||
addToPositions(k, major)
|
||||
end
|
||||
end
|
||||
local mt = getmetatable(t)
|
||||
if mt and not rawget(mt, recurse) then
|
||||
addToPositions(mt, major)
|
||||
end
|
||||
rawset(t, recurse, nil)
|
||||
end
|
||||
end
|
||||
|
||||
local function svnRevisionToNumber(text)
|
||||
if type(text) == "string" then
|
||||
if string.find(text, "^%$Revision: (%d+) %$$") then
|
||||
return tonumber((string.gsub(text, "^%$Revision: (%d+) %$$", "%1")))
|
||||
elseif string.find(text, "^%$Rev: (%d+) %$$") then
|
||||
return tonumber((string.gsub(text, "^%$Rev: (%d+) %$$", "%1")))
|
||||
elseif string.find(text, "^%$LastChangedRevision: (%d+) %$$") then
|
||||
return tonumber((string.gsub(text, "^%$LastChangedRevision: (%d+) %$$", "%1")))
|
||||
end
|
||||
elseif type(text) == "number" then
|
||||
return text
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local crawlReplace
|
||||
do
|
||||
local recurse = {}
|
||||
local function func(t, to, from)
|
||||
if recurse[t] then
|
||||
return
|
||||
end
|
||||
recurse[t] = true
|
||||
local mt = getmetatable(t)
|
||||
setmetatable(t, nil)
|
||||
rawset(t, to, rawget(t, from))
|
||||
rawset(t, from, nil)
|
||||
for k,v in pairs(t) do
|
||||
if v == from then
|
||||
t[k] = to
|
||||
elseif type(v) == "table" then
|
||||
if not recurse[v] then
|
||||
func(v, to, from)
|
||||
end
|
||||
end
|
||||
|
||||
if type(k) == "table" then
|
||||
if not recurse[k] then
|
||||
func(k, to, from)
|
||||
end
|
||||
end
|
||||
end
|
||||
setmetatable(t, mt)
|
||||
if mt then
|
||||
if mt == from then
|
||||
setmetatable(t, to)
|
||||
elseif not recurse[mt] then
|
||||
func(mt, to, from)
|
||||
end
|
||||
end
|
||||
end
|
||||
function crawlReplace(t, to, from)
|
||||
func(t, to, from)
|
||||
for k in pairs(recurse) do
|
||||
recurse[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- @function destroyTable
|
||||
-- @brief remove all the contents of a table
|
||||
-- @param t table to destroy
|
||||
local function destroyTable(t)
|
||||
setmetatable(t, nil)
|
||||
for k,v in pairs(t) do t[k] = nil end
|
||||
table_setn(t, 0)
|
||||
end
|
||||
|
||||
local function isFrame(frame)
|
||||
return type(frame) == "table" and type(rawget(frame, 0)) == "userdata" and type(rawget(frame, 'IsFrameType')) == "function" and getmetatable(frame) and type(rawget(getmetatable(frame), '__index')) == "function"
|
||||
end
|
||||
|
||||
local new, del
|
||||
do
|
||||
local tables = setmetatable({}, {__mode = "k"})
|
||||
|
||||
function new()
|
||||
local t = next(tables)
|
||||
if t then
|
||||
tables[t] = nil
|
||||
return t
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
|
||||
function del(t, depth)
|
||||
if depth and depth > 0 then
|
||||
for k,v in pairs(t) do
|
||||
if type(v) == "table" and not isFrame(v) then
|
||||
del(v, depth - 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
destroyTable(t)
|
||||
tables[t] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- @function copyTable
|
||||
-- @brief Create a shallow copy of a table and return it.
|
||||
-- @param from The table to copy from
|
||||
-- @return A shallow copy of the table
|
||||
local function copyTable(from)
|
||||
local to = new()
|
||||
for k,v in pairs(from) do to[k] = v end
|
||||
table_setn(to, table.getn(from))
|
||||
setmetatable(to, getmetatable(from))
|
||||
return to
|
||||
end
|
||||
|
||||
-- @function deepTransfer
|
||||
-- @brief Fully transfer all data, keeping proper previous table
|
||||
-- backreferences stable.
|
||||
-- @param to The table with which data is to be injected into
|
||||
-- @param from The table whose data will be injected into the first
|
||||
-- @param saveFields If available, a shallow copy of the basic data is saved
|
||||
-- in here.
|
||||
-- @param list The account of table references
|
||||
-- @param list2 The current status on which tables have been traversed.
|
||||
local deepTransfer
|
||||
do
|
||||
-- @function examine
|
||||
-- @brief Take account of all the table references to be shared
|
||||
-- between the to and from tables.
|
||||
-- @param to The table with which data is to be injected into
|
||||
-- @param from The table whose data will be injected into the first
|
||||
-- @param list An account of the table references
|
||||
local function examine(to, from, list, major)
|
||||
list[from] = to
|
||||
for k,v in pairs(from) do
|
||||
if rawget(to, k) and type(from[k]) == "table" and type(to[k]) == "table" and not list[from[k]] then
|
||||
if from[k] == to[k] then
|
||||
list[from[k]] = to[k]
|
||||
elseif AceLibrary.positions[from[v]] ~= major and AceLibrary.positions[from[v]] then
|
||||
list[from[k]] = from[k]
|
||||
elseif not list[from[k]] then
|
||||
examine(to[k], from[k], list, major)
|
||||
end
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
function deepTransfer(to, from, saveFields, major, list, list2)
|
||||
setmetatable(to, nil)
|
||||
local createdList
|
||||
if not list then
|
||||
createdList = true
|
||||
list = new()
|
||||
list2 = new()
|
||||
examine(to, from, list, major)
|
||||
end
|
||||
list2[to] = to
|
||||
for k,v in pairs(to) do
|
||||
if type(rawget(from, k)) ~= "table" or type(v) ~= "table" or isFrame(v) then
|
||||
if saveFields then
|
||||
saveFields[k] = v
|
||||
end
|
||||
to[k] = nil
|
||||
elseif v ~= _G then
|
||||
if saveFields then
|
||||
saveFields[k] = copyTable(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
for k in pairs(from) do
|
||||
if rawget(to, k) and to[k] ~= from[k] and AceLibrary.positions[to[k]] == major and from[k] ~= _G then
|
||||
if not list2[to[k]] then
|
||||
deepTransfer(to[k], from[k], nil, major, list, list2)
|
||||
end
|
||||
to[k] = list[to[k]] or list2[to[k]]
|
||||
else
|
||||
rawset(to, k, from[k])
|
||||
end
|
||||
end
|
||||
table_setn(to, table.getn(from))
|
||||
setmetatable(to, getmetatable(from))
|
||||
local mt = getmetatable(to)
|
||||
if mt then
|
||||
if list[mt] then
|
||||
setmetatable(to, list[mt])
|
||||
elseif mt.__index and list[mt.__index] then
|
||||
mt.__index = list[mt.__index]
|
||||
end
|
||||
end
|
||||
destroyTable(from)
|
||||
if createdList then
|
||||
del(list)
|
||||
del(list2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- @method TryToLoadStandalone
|
||||
-- @brief Attempt to find and load a standalone version of the requested library
|
||||
-- @param major A string representing the major version
|
||||
-- @return If library is found, return values from the call to LoadAddOn are returned
|
||||
-- If the library has been requested previously, nil is returned.
|
||||
local function TryToLoadStandalone(major)
|
||||
if not AceLibrary.scannedlibs then AceLibrary.scannedlibs = {} end
|
||||
if AceLibrary.scannedlibs[major] then return end
|
||||
|
||||
AceLibrary.scannedlibs[major] = true
|
||||
|
||||
local name, _, _, enabled, loadable = GetAddOnInfo(major)
|
||||
if loadable then
|
||||
return LoadAddOn(name)
|
||||
end
|
||||
|
||||
for i=1,GetNumAddOns() do
|
||||
if GetAddOnMetadata(i, "X-AceLibrary-"..major) then
|
||||
local name, _, _, enabled, loadable = GetAddOnInfo(i)
|
||||
if loadable then
|
||||
return LoadAddOn(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- @method IsNewVersion
|
||||
-- @brief Obtain whether the supplied version would be an upgrade to the
|
||||
-- current version. This allows for bypass code in library
|
||||
-- declaration.
|
||||
-- @param major A string representing the major version
|
||||
-- @param minor An integer or an svn revision string representing the minor version
|
||||
-- @return whether the supplied version would be newer than what is
|
||||
-- currently available.
|
||||
function AceLibrary:IsNewVersion(major, minor)
|
||||
argCheck(self, major, 2, "string")
|
||||
TryToLoadStandalone(major)
|
||||
|
||||
if type(minor) == "string" then
|
||||
local m = svnRevisionToNumber(minor)
|
||||
if m then
|
||||
minor = m
|
||||
else
|
||||
_G.error(string.format("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
||||
end
|
||||
end
|
||||
argCheck(self, minor, 3, "number")
|
||||
local data = self.libs[major]
|
||||
if not data then
|
||||
return true
|
||||
end
|
||||
return data.minor < minor
|
||||
end
|
||||
|
||||
-- @method HasInstance
|
||||
-- @brief Returns whether an instance exists. This allows for optional support of a library.
|
||||
-- @param major A string representing the major version.
|
||||
-- @param minor (optional) An integer or an svn revision string representing the minor version.
|
||||
-- @return Whether an instance exists.
|
||||
function AceLibrary:HasInstance(major, minor)
|
||||
argCheck(self, major, 2, "string")
|
||||
TryToLoadStandalone(major)
|
||||
|
||||
if minor then
|
||||
if type(minor) == "string" then
|
||||
local m = svnRevisionToNumber(minor)
|
||||
if m then
|
||||
minor = m
|
||||
else
|
||||
_G.error(string.format("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
||||
end
|
||||
end
|
||||
argCheck(self, minor, 3, "number")
|
||||
if not self.libs[major] then
|
||||
return
|
||||
end
|
||||
return self.libs[major].minor == minor
|
||||
end
|
||||
return self.libs[major] and true
|
||||
end
|
||||
|
||||
-- @method GetInstance
|
||||
-- @brief Returns the library with the given major/minor version.
|
||||
-- @param major A string representing the major version.
|
||||
-- @param minor (optional) An integer or an svn revision string representing the minor version.
|
||||
-- @return The library with the given major/minor version.
|
||||
function AceLibrary:GetInstance(major, minor)
|
||||
argCheck(self, major, 2, "string")
|
||||
TryToLoadStandalone(major)
|
||||
|
||||
local data = self.libs[major]
|
||||
if not data then
|
||||
_G.error(string.format("Cannot find a library instance of %s.", major), 2)
|
||||
return
|
||||
end
|
||||
if minor then
|
||||
if type(minor) == "string" then
|
||||
local m = svnRevisionToNumber(minor)
|
||||
if m then
|
||||
minor = m
|
||||
else
|
||||
_G.error(string.format("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
||||
end
|
||||
end
|
||||
argCheck(self, minor, 2, "number")
|
||||
if data.minor ~= minor then
|
||||
_G.error(string.format("Cannot find a library instance of %s, minor version %d.", major, minor), 2)
|
||||
return
|
||||
end
|
||||
end
|
||||
return data.instance
|
||||
end
|
||||
|
||||
-- Syntax sugar. AceLibrary("FooBar-1.0")
|
||||
AceLibrary_mt.__call = AceLibrary.GetInstance
|
||||
|
||||
local donothing
|
||||
|
||||
local AceEvent
|
||||
|
||||
-- @method Register
|
||||
-- @brief Registers a new version of a given library.
|
||||
-- @param newInstance the library to register
|
||||
-- @param major the major version of the library
|
||||
-- @param minor the minor version of the library
|
||||
-- @param activateFunc (optional) A function to be called when the library is
|
||||
-- fully activated. Takes the arguments
|
||||
-- (newInstance [, oldInstance, oldDeactivateFunc]). If
|
||||
-- oldInstance is given, you should probably call
|
||||
-- oldDeactivateFunc(oldInstance).
|
||||
-- @param deactivateFunc (optional) A function to be called by a newer library's
|
||||
-- activateFunc.
|
||||
-- @param externalFunc (optional) A function to be called whenever a new
|
||||
-- library is registered.
|
||||
function AceLibrary:Register(newInstance, major, minor, activateFunc, deactivateFunc, externalFunc)
|
||||
argCheck(self, newInstance, 2, "table")
|
||||
argCheck(self, major, 3, "string")
|
||||
if type(minor) == "string" then
|
||||
local m = svnRevisionToNumber(minor)
|
||||
if m then
|
||||
minor = m
|
||||
else
|
||||
_G.error(string.format("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
||||
end
|
||||
end
|
||||
argCheck(self, minor, 4, "number")
|
||||
if math.floor(minor) ~= minor or minor < 0 then
|
||||
error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor)
|
||||
end
|
||||
argCheck(self, activateFunc, 5, "function", "nil")
|
||||
argCheck(self, deactivateFunc, 6, "function", "nil")
|
||||
argCheck(self, externalFunc, 7, "function", "nil")
|
||||
if not deactivateFunc then
|
||||
if not donothing then
|
||||
donothing = function() end
|
||||
end
|
||||
deactivateFunc = donothing
|
||||
end
|
||||
local data = self.libs[major]
|
||||
if not data then
|
||||
-- This is new
|
||||
local instance = copyTable(newInstance)
|
||||
crawlReplace(instance, instance, newInstance)
|
||||
destroyTable(newInstance)
|
||||
if AceLibrary == newInstance then
|
||||
self = instance
|
||||
AceLibrary = instance
|
||||
end
|
||||
self.libs[major] = {
|
||||
instance = instance,
|
||||
minor = minor,
|
||||
deactivateFunc = deactivateFunc,
|
||||
externalFunc = externalFunc,
|
||||
}
|
||||
rawset(instance, 'GetLibraryVersion', function(self)
|
||||
return major, minor
|
||||
end)
|
||||
if not rawget(instance, 'error') then
|
||||
rawset(instance, 'error', error)
|
||||
end
|
||||
if not rawget(instance, 'assert') then
|
||||
rawset(instance, 'assert', assert)
|
||||
end
|
||||
if not rawget(instance, 'argCheck') then
|
||||
rawset(instance, 'argCheck', argCheck)
|
||||
end
|
||||
if not rawget(instance, 'pcall') then
|
||||
rawset(instance, 'pcall', pcall)
|
||||
end
|
||||
addToPositions(instance, major)
|
||||
if activateFunc then
|
||||
safecall(activateFunc, instance, nil, nil) -- no old version, so explicit nil
|
||||
end
|
||||
|
||||
if externalFunc then
|
||||
for k,data in pairs(self.libs) do
|
||||
if k ~= major then
|
||||
safecall(externalFunc, instance, k, data.instance)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k,data in pairs(self.libs) do
|
||||
if k ~= major and data.externalFunc then
|
||||
safecall(data.externalFunc, data.instance, major, instance)
|
||||
end
|
||||
end
|
||||
if major == "AceEvent-2.0" then
|
||||
AceEvent = instance
|
||||
end
|
||||
if AceEvent then
|
||||
AceEvent.TriggerEvent(self, "AceLibrary_Register", major, instance)
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
local instance = data.instance
|
||||
if minor <= data.minor then
|
||||
-- This one is already obsolete, raise an error.
|
||||
_G.error(string.format("Obsolete library registered. %s is already registered at version %d. You are trying to register version %d. Hint: if not AceLibrary:IsNewVersion(%q, %d) then return end", major, data.minor, minor, major, minor), 2)
|
||||
return
|
||||
end
|
||||
-- This is an update
|
||||
local oldInstance = new()
|
||||
|
||||
addToPositions(newInstance, major)
|
||||
local isAceLibrary = (AceLibrary == newInstance)
|
||||
local old_error, old_assert, old_argCheck, old_pcall
|
||||
if isAceLibrary then
|
||||
self = instance
|
||||
AceLibrary = instance
|
||||
|
||||
old_error = instance.error
|
||||
old_assert = instance.assert
|
||||
old_argCheck = instance.argCheck
|
||||
old_pcall = instance.pcall
|
||||
|
||||
self.error = error
|
||||
self.assert = assert
|
||||
self.argCheck = argCheck
|
||||
self.pcall = pcall
|
||||
end
|
||||
deepTransfer(instance, newInstance, oldInstance, major)
|
||||
crawlReplace(instance, instance, newInstance)
|
||||
local oldDeactivateFunc = data.deactivateFunc
|
||||
data.minor = minor
|
||||
data.deactivateFunc = deactivateFunc
|
||||
data.externalFunc = externalFunc
|
||||
rawset(instance, 'GetLibraryVersion', function(self)
|
||||
return major, minor
|
||||
end)
|
||||
if not rawget(instance, 'error') then
|
||||
rawset(instance, 'error', error)
|
||||
end
|
||||
if not rawget(instance, 'assert') then
|
||||
rawset(instance, 'assert', assert)
|
||||
end
|
||||
if not rawget(instance, 'argCheck') then
|
||||
rawset(instance, 'argCheck', argCheck)
|
||||
end
|
||||
if not rawget(instance, 'pcall') then
|
||||
rawset(instance, 'pcall', pcall)
|
||||
end
|
||||
if isAceLibrary then
|
||||
for _,v in pairs(self.libs) do
|
||||
local i = type(v) == "table" and v.instance
|
||||
if type(i) == "table" then
|
||||
if not rawget(i, 'error') or i.error == old_error then
|
||||
rawset(i, 'error', error)
|
||||
end
|
||||
if not rawget(i, 'assert') or i.assert == old_assert then
|
||||
rawset(i, 'assert', assert)
|
||||
end
|
||||
if not rawget(i, 'argCheck') or i.argCheck == old_argCheck then
|
||||
rawset(i, 'argCheck', argCheck)
|
||||
end
|
||||
if not rawget(i, 'pcall') or i.pcall == old_pcall then
|
||||
rawset(i, 'pcall', pcall)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if activateFunc then
|
||||
safecall(activateFunc, instance, oldInstance, oldDeactivateFunc)
|
||||
else
|
||||
safecall(oldDeactivateFunc, oldInstance)
|
||||
end
|
||||
del(oldInstance)
|
||||
|
||||
if externalFunc then
|
||||
for k,data in pairs(self.libs) do
|
||||
if k ~= major then
|
||||
safecall(externalFunc, instance, k, data.instance)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
|
||||
local iter
|
||||
function AceLibrary:IterateLibraries()
|
||||
if not iter then
|
||||
local function iter(t, k)
|
||||
k = next(t, k)
|
||||
if not k then
|
||||
return nil
|
||||
else
|
||||
return k, t[k].instance
|
||||
end
|
||||
end
|
||||
end
|
||||
return iter, self.libs, nil
|
||||
end
|
||||
|
||||
-- @function Activate
|
||||
-- @brief The activateFunc for AceLibrary itself. Called when
|
||||
-- AceLibrary properly registers.
|
||||
-- @param self Reference to AceLibrary
|
||||
-- @param oldLib (optional) Reference to an old version of AceLibrary
|
||||
-- @param oldDeactivate (optional) Function to deactivate the old lib
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
if not self.libs then
|
||||
if oldLib then
|
||||
self.libs = oldLib.libs
|
||||
self.scannedlibs = oldLib.scannedlibs
|
||||
end
|
||||
if not self.libs then
|
||||
self.libs = {}
|
||||
end
|
||||
if not self.scannedlibs then
|
||||
self.scannedlibs = {}
|
||||
end
|
||||
end
|
||||
if not self.positions then
|
||||
if oldLib then
|
||||
self.positions = oldLib.positions
|
||||
end
|
||||
if not self.positions then
|
||||
self.positions = setmetatable({}, { __mode = "k" })
|
||||
end
|
||||
end
|
||||
|
||||
-- Expose the library in the global environment
|
||||
_G[ACELIBRARY_MAJOR] = self
|
||||
|
||||
if oldDeactivate then
|
||||
oldDeactivate(oldLib)
|
||||
end
|
||||
end
|
||||
|
||||
if not previous then
|
||||
previous = AceLibrary
|
||||
end
|
||||
if not previous.libs then
|
||||
previous.libs = {}
|
||||
end
|
||||
AceLibrary.libs = previous.libs
|
||||
if not previous.positions then
|
||||
previous.positions = setmetatable({}, { __mode = "k" })
|
||||
end
|
||||
AceLibrary.positions = previous.positions
|
||||
AceLibrary:Register(AceLibrary, ACELIBRARY_MAJOR, ACELIBRARY_MINOR, activate)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
||||
-- Add a function to fix some global strings.
|
||||
if GetLocale() == "koKR" then
|
||||
function FixGlobalString(pName, str)
|
||||
-- wrong global strings
|
||||
-- "%1$s|1이;가; %3$s에게 %2$s|1을;를; 사용했습니다." <- "%s|1이;가; %3$s에게 %2$s|1을;를; 사용했습니다."
|
||||
if (pName == "OPEN_LOCK_OTHER")
|
||||
or (pName == "SIMPLEPERFORMOTHEROTHER")
|
||||
or (pName == "SPELLPERFORMGOOTHERTARGETTED")
|
||||
or (pName == "PERIODICAURADAMAGEOTHEROTHER")
|
||||
or (pName == "PERIODICAURADAMAGESELFOTHER")
|
||||
or (pName == "SIMPLECASTOTHEROTHER")
|
||||
or (pName == "SIMPLECASTOTHERSELF")
|
||||
or (pName == "SIMPLEPERFORMOTHERSELF")
|
||||
or (pName == "SPELLDURABILITYDAMAGEALLOTHERSELF")
|
||||
or (pName == "SPELLDURABILITYDAMAGEOTHERSELF")
|
||||
or (pName == "SPELLMISSOTHEROTHER") then
|
||||
str = string.gsub(str, "%%s", "%%1%$s"); -- by creep7
|
||||
elseif (pName == "COMBATLOG_HONORGAIN") then
|
||||
str = "%1$s|1이;가; 죽었습니다. 계급: %2$s (예상 명예 점수: %3$d)"; -- by creep7
|
||||
end
|
||||
|
||||
--problematic strings
|
||||
-- %s의
|
||||
return string.gsub(str, "(%%%d?$?s)(의)", "%1% %2") -- by mundi4
|
||||
end
|
||||
else
|
||||
function FixGlobalString(pName, str)
|
||||
--problematic strings
|
||||
-- %s's
|
||||
return str
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,215 @@
|
||||
|
||||
if GetLocale() == "enUS" then
|
||||
|
||||
if not ParserLibOptimizer then
|
||||
ParserLibOptimizer = {
|
||||
AURAADDEDOTHERHARMFUL = "afflict",
|
||||
AURAADDEDOTHERHELPFUL = "gain",
|
||||
AURAADDEDSELFHARMFUL = "afflict",
|
||||
AURAADDEDSELFHELPFUL = "gain",
|
||||
AURAAPPLICATIONADDEDOTHERHARMFUL = "afflict",
|
||||
AURAAPPLICATIONADDEDOTHERHELPFUL = "gain",
|
||||
AURAAPPLICATIONADDEDSELFHARMFUL = "afflict",
|
||||
AURAAPPLICATIONADDEDSELFHELPFUL = "gain",
|
||||
AURADISPELOTHER = "remove",
|
||||
AURADISPELSELF = "remove",
|
||||
AURAREMOVEDOTHER = "fade",
|
||||
AURAREMOVEDSELF = "fade",
|
||||
COMBATHITCRITOTHEROTHER = "crit",
|
||||
COMBATHITCRITOTHERSELF = "crit",
|
||||
COMBATHITCRITSELFOTHER = "crit",
|
||||
COMBATHITCRITSELFSELF = "crit",
|
||||
COMBATHITCRITSCHOOLOTHEROTHER = "crit",
|
||||
COMBATHITCRITSCHOOLOTHERSELF = "crit",
|
||||
COMBATHITCRITSCHOOLSELFOTHER = "crit",
|
||||
COMBATHITCRITSCHOOLSELFSELF = "crit",
|
||||
COMBATHITOTHEROTHER = "hit",
|
||||
COMBATHITOTHERSELF = "hit",
|
||||
COMBATHITSELFOTHER = "hit",
|
||||
COMBATHITSELFSELF = "hit",
|
||||
COMBATHITSCHOOLOTHEROTHER = "hit",
|
||||
COMBATHITSCHOOLOTHERSELF = "hit",
|
||||
COMBATHITSCHOOLSELFOTHER = "hit",
|
||||
COMBATHITSCHOOLSELFSELF = "hit",
|
||||
DAMAGESHIELDOTHEROTHER = "reflect",
|
||||
DAMAGESHIELDOTHERSELF = "reflect",
|
||||
DAMAGESHIELDSELFOTHER = "reflect",
|
||||
DISPELFAILEDOTHEROTHER = "fail",
|
||||
DISPELFAILEDOTHERSELF = "fail",
|
||||
DISPELFAILEDSELFOTHER = "fail",
|
||||
DISPELFAILEDSELFSELF = "fail",
|
||||
HEALEDCRITOTHEROTHER = "crit",
|
||||
HEALEDCRITOTHERSELF = "crit",
|
||||
HEALEDCRITSELFOTHER = "crit",
|
||||
HEALEDCRITSELFSELF = "crit",
|
||||
HEALEDOTHEROTHER = "heal",
|
||||
HEALEDOTHERSELF = "heal",
|
||||
HEALEDSELFOTHER = "heal",
|
||||
HEALEDSELFSELF = "heal",
|
||||
IMMUNESPELLOTHEROTHER = "immune",
|
||||
IMMUNESPELLSELFOTHER = "immune",
|
||||
IMMUNESPELLOTHERSELF = "immune",
|
||||
IMMUNESPELLSELFSELF = "immune",
|
||||
ITEMENCHANTMENTADDOTHEROTHER = "cast",
|
||||
ITEMENCHANTMENTADDOTHERSELF = "cast",
|
||||
ITEMENCHANTMENTADDSELFOTHER = "cast",
|
||||
ITEMENCHANTMENTADDSELFSELF = "cast",
|
||||
MISSEDOTHEROTHER = "miss",
|
||||
MISSEDOTHERSELF = "miss",
|
||||
MISSEDSELFOTHER = "miss",
|
||||
MISSEDSELFSELF = "miss",
|
||||
OPEN_LOCK_OTHER = "perform",
|
||||
OPEN_LOCK_SELF = "perform",
|
||||
PARTYKILLOTHER = "slain",
|
||||
PERIODICAURADAMAGEOTHEROTHER = "suffer",
|
||||
PERIODICAURADAMAGEOTHERSELF = "suffer",
|
||||
PERIODICAURADAMAGESELFOTHER = "suffer",
|
||||
PERIODICAURADAMAGESELFSELF = "suffer",
|
||||
PERIODICAURAHEALOTHEROTHER = "gain",
|
||||
PERIODICAURAHEALOTHERSELF = "gain",
|
||||
PERIODICAURAHEALSELFOTHER = "gain",
|
||||
PERIODICAURAHEALSELFSELF = "gain",
|
||||
POWERGAINOTHEROTHER = "gain",
|
||||
POWERGAINOTHERSELF = "gain",
|
||||
POWERGAINSELFSELF = "gain",
|
||||
POWERGAINSELFOTHER = "gain",
|
||||
PROCRESISTOTHEROTHER = "resist",
|
||||
PROCRESISTOTHERSELF = "resist",
|
||||
PROCRESISTSELFOTHER = "resist",
|
||||
PROCRESISTSELFSELF = "resist",
|
||||
SIMPLECASTOTHEROTHER = "cast",
|
||||
SIMPLECASTOTHERSELF = "cast",
|
||||
SIMPLECASTSELFOTHER = "cast",
|
||||
SIMPLECASTSELFSELF = "cast",
|
||||
SIMPLEPERFORMOTHEROTHER = "perform",
|
||||
SIMPLEPERFORMOTHERSELF = "perform",
|
||||
SIMPLEPERFORMSELFOTHER = "perform",
|
||||
SIMPLEPERFORMSELFSELF = "perform",
|
||||
SPELLBLOCKEDOTHEROTHER = "block",
|
||||
SPELLBLOCKEDOTHERSELF = "block",
|
||||
SPELLBLOCKEDSELFOTHER = "block",
|
||||
SPELLBLOCKEDSELFSELF = "block",
|
||||
SPELLCASTOTHERSTART = "begin",
|
||||
SPELLCASTSELFSTART = "begin",
|
||||
SPELLDEFLECTEDOTHEROTHER = "deflect",
|
||||
SPELLDEFLECTEDOTHERSELF = "deflect",
|
||||
SPELLDEFLECTEDSELFOTHER = "deflect",
|
||||
SPELLDEFLECTEDSELFSELF = "deflect",
|
||||
SPELLDODGEDOTHEROTHER = "dodge",
|
||||
SPELLDODGEDOTHERSELF = "dodge",
|
||||
SPELLDODGEDSELFOTHER = "dodge",
|
||||
SPELLEVADEDOTHEROTHER = "evade",
|
||||
SPELLEVADEDOTHERSELF = "evade",
|
||||
SPELLEVADEDSELFOTHER = "evade",
|
||||
SPELLEVADEDSELFSELF = "evade",
|
||||
SPELLEXTRAATTACKSOTHER = "extra",
|
||||
SPELLEXTRAATTACKSOTHER_SINGULAR = "extra",
|
||||
SPELLEXTRAATTACKSSELF = "extra",
|
||||
SPELLEXTRAATTACKSSELF_SINGULAR = "extra",
|
||||
SPELLFAILCASTSELF = "fail",
|
||||
SPELLFAILPERFORMSELF = "fail",
|
||||
SPELLIMMUNEOTHEROTHER = "immune",
|
||||
SPELLIMMUNEOTHERSELF = "immune",
|
||||
SPELLIMMUNESELFOTHER = "immune",
|
||||
SPELLIMMUNESELFSELF = "immune",
|
||||
SPELLINTERRUPTOTHEROTHER = "interrupt",
|
||||
SPELLINTERRUPTOTHERSELF = "interrupt",
|
||||
SPELLINTERRUPTSELFOTHER = "interrupt",
|
||||
SPELLLOGABSORBOTHEROTHER = "absorb",
|
||||
SPELLLOGABSORBOTHERSELF = "absorb",
|
||||
SPELLLOGABSORBSELFOTHER = "absorb",
|
||||
SPELLLOGABSORBSELFSELF = "absorb",
|
||||
SPELLLOGCRITOTHEROTHER = "crit",
|
||||
SPELLLOGCRITOTHERSELF = "crit",
|
||||
SPELLLOGCRITSCHOOLOTHEROTHER = "crit",
|
||||
SPELLLOGCRITSCHOOLOTHERSELF = "crit",
|
||||
SPELLLOGCRITSCHOOLSELFOTHER = "crit",
|
||||
SPELLLOGCRITSCHOOLSELFSELF = "crit",
|
||||
SPELLLOGCRITSELFOTHER = "crit",
|
||||
SPELLLOGOTHEROTHER = "hit",
|
||||
SPELLLOGOTHERSELF = "hit",
|
||||
SPELLLOGOTHERSELF = "hit",
|
||||
SPELLLOGSCHOOLOTHEROTHER = "hit",
|
||||
SPELLLOGSCHOOLOTHERSELF = "hit",
|
||||
SPELLLOGSCHOOLSELFOTHER = "hit",
|
||||
SPELLLOGSCHOOLSELFSELF = "hit",
|
||||
SPELLLOGSELFOTHER = "hit",
|
||||
SPELLMISSOTHEROTHER = "miss",
|
||||
SPELLMISSOTHERSELF = "miss",
|
||||
SPELLMISSSELFOTHER = "miss",
|
||||
SPELLPARRIEDOTHEROTHER = "parr",
|
||||
SPELLPARRIEDOTHERSELF = "parr",
|
||||
SPELLPARRIEDSELFOTHER = "parr",
|
||||
SPELLPERFORMOTHERSTART = "begin",
|
||||
SPELLPERFORMSELFSTART = "begin",
|
||||
SPELLPOWERDRAINOTHEROTHER = "drain",
|
||||
SPELLPOWERDRAINOTHERSELF = "drain",
|
||||
SPELLPOWERDRAINSELFOTHER = "drain",
|
||||
SPELLPOWERLEECHOTHEROTHER = "drain",
|
||||
SPELLPOWERLEECHOTHERSELF = "drain",
|
||||
SPELLPOWERLEECHSELFOTHER = "drain",
|
||||
SPELLREFLECTOTHEROTHER = "reflect",
|
||||
SPELLREFLECTOTHERSELF = "reflect",
|
||||
SPELLREFLECTSELFOTHER = "reflect",
|
||||
SPELLREFLECTSELFSELF = "reflect",
|
||||
SPELLRESISTOTHEROTHER = "resist",
|
||||
SPELLRESISTOTHERSELF = "resist",
|
||||
SPELLRESISTSELFOTHER = "resist",
|
||||
SPELLRESISTSELFSELF = "resist",
|
||||
SPELLSPLITDAMAGESELFOTHER = "cause",
|
||||
SPELLSPLITDAMAGEOTHEROTHER = "cause",
|
||||
SPELLSPLITDAMAGEOTHERSELF = "cause",
|
||||
SPELLTERSEPERFORM_OTHER = "perform",
|
||||
SPELLTERSEPERFORM_SELF = "perform",
|
||||
SPELLTERSE_OTHER = "cast",
|
||||
SPELLTERSE_SELF = "cast",
|
||||
VSABSORBOTHEROTHER = "absorb",
|
||||
VSABSORBOTHERSELF = "absorb",
|
||||
VSABSORBSELFOTHER = "absorb",
|
||||
VSBLOCKOTHEROTHER = "block",
|
||||
VSBLOCKOTHERSELF = "block",
|
||||
VSBLOCKSELFOTHER = "block",
|
||||
VSBLOCKSELFSELF = "block",
|
||||
VSDEFLECTOTHEROTHER = "deflect",
|
||||
VSDEFLECTOTHERSELF = "deflect",
|
||||
VSDEFLECTSELFOTHER = "deflect",
|
||||
VSDEFLECTSELFSELF = "deflect",
|
||||
VSDODGEOTHEROTHER = "dodge",
|
||||
VSDODGEOTHERSELF = "dodge",
|
||||
VSDODGESELFOTHER = "dodge",
|
||||
VSDODGESELFSELF = "dodge",
|
||||
VSENVIRONMENTALDAMAGE_FALLING_OTHER = "fall",
|
||||
VSENVIRONMENTALDAMAGE_FALLING_SELF = "fall",
|
||||
VSENVIRONMENTALDAMAGE_FIRE_OTHER = "fire",
|
||||
VSENVIRONMENTALDAMAGE_FIRE_SELF = "fire",
|
||||
VSENVIRONMENTALDAMAGE_LAVA_OTHER = "lava",
|
||||
VSENVIRONMENTALDAMAGE_LAVA_SELF = "lava",
|
||||
VSEVADEOTHEROTHER = "evade",
|
||||
VSEVADEOTHERSELF = "evade",
|
||||
VSEVADESELFOTHER = "evade",
|
||||
VSEVADESELFSELF = "evade",
|
||||
VSIMMUNEOTHEROTHER = "immune",
|
||||
VSIMMUNEOTHERSELF = "immune",
|
||||
VSIMMUNESELFOTHER = "immune",
|
||||
VSPARRYOTHEROTHER = "parr",
|
||||
VSPARRYOTHERSELF = "parr",
|
||||
VSPARRYSELFOTHER = "parr",
|
||||
VSRESISTOTHEROTHER = "resist",
|
||||
VSRESISTOTHERSELF = "resist",
|
||||
VSRESISTSELFOTHER = "resist",
|
||||
VSRESISTSELFSELF = "resist",
|
||||
VSENVIRONMENTALDAMAGE_FATIGUE_OTHER = "exhaust",
|
||||
VSENVIRONMENTALDAMAGE_FIRE_OTHER = "fire",
|
||||
VSENVIRONMENTALDAMAGE_SLIME_OTHER = "slime",
|
||||
VSENVIRONMENTALDAMAGE_SLIME_SELF = "slime",
|
||||
VSENVIRONMENTALDAMAGE_DROWNING_OTHER = "drown",
|
||||
UNITDIESSELF = "die",
|
||||
UNITDIESOTHER = "die",
|
||||
UNITDESTROYEDOTHER = "destroy",
|
||||
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
The newest documentation can be found at http://www.wowace.com/index.php/ParserLib
|
||||
@@ -0,0 +1,17 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Include file="libs\AceLibrary\AceLibrary.lua"/>
|
||||
<Include file="libs\AceOO-2.0\AceOO-2.0.lua"/>
|
||||
<Include file="libs\AceEvent-2.0\AceEvent-2.0.lua"/>
|
||||
<Include file="libs\AceHook-2.1\AceHook-2.1.lua"/>
|
||||
<Include file="libs\AceAddon-2.0\AceAddon-2.0.lua"/>
|
||||
|
||||
<Include file="libs\CandyBar-2.0\CandyBar-2.0.lua"/>
|
||||
|
||||
<Include file="libs\ParserLib\FixGlobalString.lua"/>
|
||||
<Include file="libs\ParserLib\ParserLib.lua"/>
|
||||
<Include file="libs\ParserLib\optimizer-enUS.lua"/>
|
||||
|
||||
<Include file="engine.lua"/>
|
||||
<Include file="data-hunter.lua"/>
|
||||
<Include file="module.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,45 @@
|
||||
local MTH_ChronometerModule = {
|
||||
name = "chronometer",
|
||||
enabled = true,
|
||||
version = "1.0.3",
|
||||
events = {},
|
||||
initialized = false,
|
||||
}
|
||||
|
||||
local function MTH_CHRON_ApplyRuntimeEnabledState(enabled)
|
||||
if not MTH_ChronometerHunter then
|
||||
return
|
||||
end
|
||||
if enabled then
|
||||
if MTH_ChronometerHunter.MTH_Enable then
|
||||
MTH_ChronometerHunter:MTH_Enable()
|
||||
end
|
||||
else
|
||||
if MTH_ChronometerHunter.MTH_Disable then
|
||||
MTH_ChronometerHunter:MTH_Disable()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_ChronometerModule:init()
|
||||
if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Initialize then
|
||||
MTH_ChronometerHunter:MTH_Initialize()
|
||||
end
|
||||
MTH_CHRON_ApplyRuntimeEnabledState(self.enabled and true or false)
|
||||
self.initialized = true
|
||||
end
|
||||
|
||||
function MTH_ChronometerModule:setEnabled(enabled)
|
||||
if not self.initialized then
|
||||
self:init()
|
||||
end
|
||||
MTH_CHRON_ApplyRuntimeEnabledState(enabled and true or false)
|
||||
end
|
||||
|
||||
function MTH_ChronometerModule:cleanup()
|
||||
if MTH_ChronometerHunter and MTH_ChronometerHunter.MTH_Disable then
|
||||
MTH_ChronometerHunter:MTH_Disable()
|
||||
end
|
||||
end
|
||||
|
||||
MTH:RegisterModule("chronometer", MTH_ChronometerModule)
|
||||
@@ -0,0 +1,5 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Binding name="FEEDOMATIC" header="FEEDOMATIC">
|
||||
FOM_Feed();
|
||||
</Binding>
|
||||
</Ui>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
||||
FOM_Emotes = {
|
||||
|
||||
["any"] = {
|
||||
"Yum!",
|
||||
"Mmm, good stuff.",
|
||||
},
|
||||
|
||||
["male"] = {
|
||||
"Good boy!",
|
||||
},
|
||||
["female"] = {
|
||||
"Good girl!",
|
||||
},
|
||||
|
||||
["Zesty Clam Meat"] = {
|
||||
"Mmm, zesty!",
|
||||
},
|
||||
["Heaven Peach"] = {
|
||||
"Movin' to the country...",
|
||||
},
|
||||
["Mystery Meat"] = {
|
||||
"Tastes like chicken.",
|
||||
},
|
||||
["Dragonbreath Chili"] = {
|
||||
"Yow, spicy!",
|
||||
},
|
||||
|
||||
["Bat"] = {
|
||||
"Squeak-squeak snack attack!",
|
||||
},
|
||||
["Bear"] = {
|
||||
"One paw for me, one paw for the bear.",
|
||||
},
|
||||
["Boar"] = {
|
||||
"Good piggy!"
|
||||
},
|
||||
["Carrion Bird"] = {
|
||||
"A gourmet meal... by scavenger standards.",
|
||||
},
|
||||
["Cat"] = {
|
||||
"Nice kitty!",
|
||||
},
|
||||
["Crab"] = {
|
||||
"Crabby no more!",
|
||||
},
|
||||
["Crocolisk"] = {
|
||||
"Easy there, chompy friend.",
|
||||
},
|
||||
["Gorilla"] = {
|
||||
"Big buddy deserves a big bite.",
|
||||
},
|
||||
["Hyena"] = {
|
||||
"Good dog!",
|
||||
},
|
||||
["Owl"] = {
|
||||
"Whoo's a hungry hunter helper?",
|
||||
},
|
||||
["Raptor"] = {
|
||||
"Tiny arms, huge appetite.",
|
||||
},
|
||||
["Scorpid"] = {
|
||||
"No stinging the cook, deal?",
|
||||
},
|
||||
["Spider"] = {
|
||||
"Eight legs, zero table manners.",
|
||||
},
|
||||
["Tallstrider"] = {
|
||||
"Long neck, longer lunch break.",
|
||||
},
|
||||
["Turtle"] = {
|
||||
"Slow and steady wins the snacks.",
|
||||
},
|
||||
["Wind Serpent"] = {
|
||||
"Lightning in the sky, snacks on the ground.",
|
||||
},
|
||||
["Wolf"] = {
|
||||
"Good dog!",
|
||||
},
|
||||
|
||||
["Foxes"] = {
|
||||
"Clever fox, clever snack choice.",
|
||||
},
|
||||
["Serpents (Cobra)"] = {
|
||||
"No hissing with your mouth full.",
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,238 @@
|
||||
FOM_Foods = {
|
||||
[FOM_DIET_FUNGUS] = {
|
||||
4607, -- Delicious Cave Mold
|
||||
8948, -- Dried King Bolete
|
||||
4604, -- Forest Mushroom Cap
|
||||
4608, -- Raw Black Truffle
|
||||
4605, -- Red-speckled Mushroom
|
||||
3448, -- Senggin Root
|
||||
4606, -- Spongy Morel
|
||||
},
|
||||
[FOM_DIET_FISH] = {
|
||||
13889, -- Raw Whitescale Salmon
|
||||
19996, -- Harvest Fish
|
||||
13933, -- Lobster Stew
|
||||
13888, -- Darkclaw Lobster
|
||||
13935, -- Baked Salmon
|
||||
13546, -- Bloodbelly Fish
|
||||
6290, -- Brilliant Smallfish
|
||||
4593, -- Bristle Whisker Catfish
|
||||
5503, -- Clam Meat
|
||||
16971, -- Clamlette Surprise
|
||||
2682, -- Cooked Crab Claw
|
||||
13927, -- Cooked Glossy Mightfish
|
||||
2675, -- Crawler Claw
|
||||
13930, -- Filet of Redgill
|
||||
5476, -- Fillet of Frenzy
|
||||
4655, -- Giant Clam Meat
|
||||
6038, -- Giant Clam Scorcho
|
||||
13928, -- Grilled Squid
|
||||
13929, -- Hot Smoked Bass
|
||||
13893, -- Large Raw Mightfish
|
||||
4592, -- Longjaw Mud Snapper
|
||||
8364, -- Mithril Head Trout
|
||||
13932, -- Poached Sunscale Salmon
|
||||
5095, -- Rainbow Fin Albacore
|
||||
6291, -- Raw Brilliant Smallfish
|
||||
6308, -- Raw Bristle Whisker Catfish
|
||||
13754, -- Raw Glossy Mightfish
|
||||
6317, -- Raw Loch Frenzy
|
||||
6289, -- Raw Longjaw Mud Snapper
|
||||
8365, -- Raw Mithril Head Trout
|
||||
6361, -- Raw Rainbow Fin Albacore
|
||||
13758, -- Raw Redgill
|
||||
6362, -- Raw Rockscale Cod
|
||||
6303, -- Raw Slitherskin Mackerel
|
||||
8959, -- Raw Spinefin Halibut
|
||||
4603, -- Raw Spotted Yellowtail
|
||||
13756, -- Raw Summer Bass
|
||||
13760, -- Raw Sunscale Salmon
|
||||
4594, -- Rockscale Cod
|
||||
787, -- Slitherskin Mackerel
|
||||
5468, -- Soft Frenzy Flesh
|
||||
15924, -- Soft-shelled Clam Meat
|
||||
12216, -- Spiced Chili Crab
|
||||
8957, -- Spinefin Halibut
|
||||
6887, -- Spotted Yellowtail
|
||||
5504, -- Tangy Clam Meat
|
||||
12206, -- Tender Crab Meat
|
||||
13755, -- Winter Squid
|
||||
7974, -- Zesty Clam Meat
|
||||
},
|
||||
[FOM_DIET_MEAT] = {
|
||||
21235, -- Winter Veil Roast
|
||||
19995, -- Harvest Boar
|
||||
4457, -- Barbecued Buzzard Wing
|
||||
3173, -- Bear Meat
|
||||
2888, -- Beer Basted Boar Ribs
|
||||
3730, -- Big Bear Meat
|
||||
3726, -- Big Bear Steak
|
||||
3220, -- Blood Sausage
|
||||
2677, -- Boar Ribs
|
||||
3404, -- Buzzard Wing
|
||||
12213, -- Carrion Surprise
|
||||
2679, -- Charred Wolf Meat
|
||||
769, -- Chunk of Boar Meat
|
||||
2673, -- Coyote Meat
|
||||
2684, -- Coyote Steak
|
||||
1081, -- Crisp Spider Meat
|
||||
12224, -- Crispy Bat Wing
|
||||
5479, -- Crispy Lizard Tail
|
||||
2924, -- Crocolisk Meat
|
||||
3662, -- Crocolisk Steak
|
||||
4599, -- Cured Ham Steak
|
||||
17119, -- Deeprun Rat Kabob
|
||||
5478, -- Dig Rat Stew
|
||||
5051, -- Dig Rat
|
||||
12217, -- Dragonbreath Chili
|
||||
2687, -- Dry Pork Ribs
|
||||
9681, -- Grilled King Crawler Legs
|
||||
2287, -- Haunch of Meat
|
||||
12204, -- Heavy Kodo Meat
|
||||
3727, -- Hot Lion Chops
|
||||
13851, -- Hot Wolf Ribs
|
||||
12212, -- Jungle Stew
|
||||
5472, -- Kaldorei Spider Kabob
|
||||
5467, -- Kodo Meat
|
||||
5480, -- Lean Venison
|
||||
1015, -- Lean Wolf Flank
|
||||
12209, -- Lean Wolf Steak
|
||||
3731, -- Lion Meat
|
||||
12223, -- Meaty Bat Wing
|
||||
3770, -- Mutton Chop
|
||||
12037, -- Mystery Meat
|
||||
4739, -- Plainstrider Meat
|
||||
12184, -- Raptor Flesh
|
||||
13759, -- Raw Nightfin Snapper
|
||||
12203, -- Red Wolf Meat
|
||||
12210, -- Roast Raptor
|
||||
2681, -- Roasted Boar Meat
|
||||
5474, -- Roasted Kodo Meat
|
||||
8952, -- Roasted Quail
|
||||
1017, -- Seasoned Wolf Kabob
|
||||
5465, -- Small Spider Leg
|
||||
6890, -- Smoked Bear Meat
|
||||
3729, -- Soothing Turtle Bisque
|
||||
2680, -- Spiced Wolf Meat
|
||||
17222, -- Spider Sausage
|
||||
5471, -- Stag Meat
|
||||
5469, -- Strider Meat
|
||||
5477, -- Strider Stew
|
||||
2672, -- Stringy Wolf Meat
|
||||
2685, -- Succulent Pork Ribs
|
||||
3728, -- Tasty Lion Steak
|
||||
3667, -- Tender Crocolisk Meat
|
||||
12208, -- Tender Wolf Meat
|
||||
18045, -- Tender Wolf Steak
|
||||
5470, -- Thunder Lizard Tail
|
||||
12202, -- Tiger Meat
|
||||
117, -- Tough Jerky
|
||||
3712, -- Turtle Meat
|
||||
12205, -- White Spider Meat
|
||||
3771, -- Wild Hog Shank
|
||||
},
|
||||
[FOM_DIET_BREAD] = {
|
||||
1113, -- Conjured Bread
|
||||
5349, -- Conjured Muffin
|
||||
1487, -- Conjured Pumpernickel
|
||||
1114, -- Conjured Rye
|
||||
8075, -- Conjured Sourdough
|
||||
8076, -- Conjured Sweet Roll
|
||||
22895, -- Conjured Cinnamon Roll
|
||||
83004, -- Conjured Mana Orange
|
||||
19696, -- Harvest Bread
|
||||
21254, -- Winter Veil Cookie
|
||||
2683, -- Crab Cake
|
||||
4541, -- Freshly Baked Bread
|
||||
17197, -- Gingerbread Cookie
|
||||
3666, -- Gooey Spider Cake
|
||||
8950, -- Homemade Cherry Pie
|
||||
4542, -- Moist Cornbread
|
||||
4544, -- Mulgore Spice Bread
|
||||
4601, -- Soft Banana Bread
|
||||
4540, -- Tough Hunk of Bread
|
||||
16169, -- Wild Ricecake
|
||||
},
|
||||
[FOM_DIET_CHEESE] = {
|
||||
8932, -- Alterac Swiss
|
||||
414, -- Dalaran Sharp
|
||||
2070, -- Darnassian Bleu
|
||||
422, -- Dwarven Mild
|
||||
3927, -- Fine Aged Cheddar
|
||||
1707, -- Stormwind Brie
|
||||
},
|
||||
[FOM_DIET_FRUIT] = {
|
||||
19994, -- Harvest Fruit
|
||||
8953, -- Deep Fried Plantains
|
||||
4539, -- Goldenbark Apple
|
||||
16168, -- Heaven Peach
|
||||
4602, -- Moon Harvest Pumpkin
|
||||
4536, -- Shiny Red Apple
|
||||
4538, -- Snapvine Watermelon
|
||||
4537, -- Tel'Abim Banana
|
||||
11950, -- Windblossom Berries
|
||||
},
|
||||
[FOM_DIET_BONUS] = {
|
||||
-- eat for 10 sec to get "well fed" sta/spi bonus
|
||||
2888, -- Beer Basted Boar Ribs
|
||||
11584, -- Cactus Apple Surprise
|
||||
7807, -- Candy Bar
|
||||
7808, -- Chocolate Square
|
||||
12224, -- Crispy Bat Wing
|
||||
17197, -- Gingerbread Cookie
|
||||
6888, -- Herb Baked Egg
|
||||
5472, -- Kaldorei Spider Kabob
|
||||
7806, -- Lollipop
|
||||
5474, -- Roasted Kodo Meat
|
||||
2680, -- Spiced Wolf Meat
|
||||
3220, -- Blood Sausage
|
||||
5525, -- Boiled Clams
|
||||
2684, -- Coyote Steak
|
||||
2683, -- Crab Cake
|
||||
3662, -- Crocolisk Steak
|
||||
2687, -- Dry Pork Ribs
|
||||
5476, -- Fillet of Frenzy
|
||||
724, -- Goretusk Liver Pie
|
||||
5477, -- Strider Stew
|
||||
3726, -- Big Bear Steak
|
||||
5479, -- Crispy Lizard Tail
|
||||
3664, -- Crocolisk Gumbo
|
||||
3665, -- Curiously Tasty Omelet
|
||||
5527, -- Goblin Deviled Clams
|
||||
3666, -- Gooey Spider Cake
|
||||
3727, -- Hot Lion Chops
|
||||
5480, -- Lean Venison
|
||||
12209, -- Lean Wolf Steak
|
||||
3663, -- Murloc Fin Soup
|
||||
1082, -- Redridge Goulash
|
||||
1017, -- Seasoned Wolf Kabob
|
||||
4457, -- Barbecued Buzzard Wing
|
||||
12213, -- Carrion Surprise
|
||||
6038, -- Giant Clam Scorcho
|
||||
13851, -- Hot Wolf Ribs
|
||||
12212, -- Jungle Stew
|
||||
12214, -- Mystery Stew
|
||||
12210, -- Roast Raptor
|
||||
3729, -- Soothing Turtle Bisque
|
||||
3728, -- Tasty Lion Steak
|
||||
16971, -- Clamlette Surprise
|
||||
12215, -- Heavy Kodo Stew
|
||||
12218, -- Monster Omelet
|
||||
12216, -- Spiced Chili Crab
|
||||
17222, -- Spider Sausage
|
||||
18045, -- Tender Wolf Steak
|
||||
-- restores both health and mana
|
||||
2682, -- Cooked Crab Claw
|
||||
3448, -- Senggin Root
|
||||
-- bonus effect with no 10 sec requirement
|
||||
12217, -- Dragonbreath Chili
|
||||
13927, -- Cooked Glossy Mightfish
|
||||
13928, -- Grilled Squid
|
||||
13929, -- Hot Smoked Bass
|
||||
13932, -- Poached Sunscale Salmon
|
||||
13931, -- Nightfin Soup
|
||||
13934, -- Mightfish Steak
|
||||
11950, -- Windblossom Berries
|
||||
18254, -- Runn Tum Tuber Surprise
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,174 @@
|
||||
------------------------------------------------------
|
||||
-- GFWTable.lua
|
||||
-- Utilities for manipulating tables
|
||||
------------------------------------------------------
|
||||
|
||||
GFWTABLE_THIS_VERSION = 6;
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
-- Mean: returns the mean value of a table of numbers
|
||||
function GFWTable_temp_Mean(aTable)
|
||||
if (aTable == nil or table.getn(aTable) == 0) then
|
||||
return nil;
|
||||
end
|
||||
return GFWTable.Sum(aTable) / table.getn(aTable);
|
||||
end
|
||||
|
||||
-- Sum: returns the sum of a table of numbers
|
||||
function GFWTable_temp_Sum(aTable)
|
||||
if (aTable == nil or table.getn(aTable) == 0) then
|
||||
return nil;
|
||||
end
|
||||
local sum = 0;
|
||||
for i=1, table.getn(aTable) do
|
||||
if (tonumber(aTable[i])) then
|
||||
sum = sum + aTable[i];
|
||||
end
|
||||
end
|
||||
return sum;
|
||||
end
|
||||
|
||||
-- Median: returns the median value (most useful in a table of numbers, but usable in any sorted table)
|
||||
function GFWTable_temp_Median(aTable)
|
||||
if (aTable == nil or table.getn(aTable) == 0) then
|
||||
return nil;
|
||||
end
|
||||
if (table.getn(aTable) == 1) then
|
||||
return aTable[1];
|
||||
end
|
||||
local sortedTable = GFWTable.Copy(aTable); -- leave the original table in whatever order it's in
|
||||
table.sort(sortedTable);
|
||||
local count = table.getn(sortedTable);
|
||||
local median;
|
||||
if (math.mod(count, 2) == 0) then -- even table size
|
||||
local middleIndex1 = count / 2;
|
||||
local middleIndex2 = middleIndex1 + 1;
|
||||
median = (sortedTable[middleIndex1] + sortedTable[middleIndex2]) / 2; --average the two middle values
|
||||
else -- the table size is odd
|
||||
local trueMiddleIndex = (count + 1) / 2; -- calculate the middle index
|
||||
median = sortedTable[trueMiddleIndex];
|
||||
end
|
||||
return median;
|
||||
end
|
||||
|
||||
-- Merge: returns the union of two tables (without repeated elements)
|
||||
function GFWTable_temp_Merge(table1, table2)
|
||||
local newTable = { };
|
||||
if (table1) then
|
||||
for i=1, table.getn(table1) do
|
||||
table.insert(newTable, table1[i]);
|
||||
end
|
||||
end
|
||||
if (table2) then
|
||||
for i=1, table.getn(table2) do
|
||||
if (GFWTable.IndexOf(newTable, table2[i]) == 0) then
|
||||
table.insert(newTable, table2[i]);
|
||||
end
|
||||
end
|
||||
end
|
||||
return newTable;
|
||||
end
|
||||
|
||||
-- Diff: returns the difference of two tables (those elements which occur in either but not both)
|
||||
function GFWTable_temp_Diff(table1, table2)
|
||||
local newTable = { };
|
||||
if (table1 == nil) then
|
||||
table1 = {};
|
||||
end
|
||||
if (table2 == nil) then
|
||||
table2 = {};
|
||||
end
|
||||
for i=1, table.getn(table1) do
|
||||
if (GFWTable.IndexOf(table2, table1[i]) == 0) then
|
||||
table.insert(newTable, table1[i]);
|
||||
end
|
||||
end
|
||||
for i=1, table.getn(table2) do
|
||||
if (GFWTable.IndexOf(table1, table2[i]) == 0) then
|
||||
table.insert(newTable, table2[i]);
|
||||
end
|
||||
end
|
||||
return newTable;
|
||||
end
|
||||
|
||||
-- Subtract: returns a table containing those items in table1 not present in table2
|
||||
function GFWTable_temp_Subtract(table1, table2)
|
||||
local newTable = { };
|
||||
if (table1 == nil or table.getn(table1) == 0) then return newTable; end
|
||||
if (table2 == nil or table.getn(table2) == 0) then return table1; end
|
||||
for i=1, table.getn(table1) do
|
||||
if (GFWTable.IndexOf(table2, table1[i]) == 0) then
|
||||
table.insert(newTable, table1[i]);
|
||||
end
|
||||
end
|
||||
return newTable;
|
||||
end
|
||||
|
||||
-- IndexOf: returns the index (1-based) of an item in a table
|
||||
function GFWTable_temp_IndexOf(aTable, item)
|
||||
return GFWTable.KeyOf(aTable, item) or 0;
|
||||
end
|
||||
|
||||
-- KeyOf: returns the key to an item in a table with numeric or non-numeric keys, or nil if not found
|
||||
function GFWTable_temp_KeyOf(aTable, item)
|
||||
if (aTable == nil or type(aTable) ~= "table") then
|
||||
return nil; -- caller probably won't expect this, causing traceable error in their code
|
||||
end
|
||||
for key, value in pairs(aTable) do
|
||||
if (item == value) then
|
||||
return key;
|
||||
end
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
-- Copy: copies one table's elements into a new table (useful if you want to change them while preserving the first table).
|
||||
-- Not a deep copy.
|
||||
function GFWTable_temp_Copy(aTable)
|
||||
local newTable = { };
|
||||
for i=1, table.getn(aTable) do
|
||||
newTable[i] = aTable[i];
|
||||
end
|
||||
return newTable;
|
||||
end
|
||||
|
||||
-- Count: returns number of items in a table regardless of whether it has numeric indices.
|
||||
function GFWTable_temp_Count(aTable)
|
||||
if (aTable == nil or type(aTable) ~= "table") then
|
||||
return nil; -- caller probably won't expect this, causing traceable error in their code
|
||||
end
|
||||
local count = 0;
|
||||
for key, value in pairs(aTable) do
|
||||
count = count + 1;
|
||||
end
|
||||
return count;
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- load only if not already loaded
|
||||
------------------------------------------------------
|
||||
|
||||
if (GFWTable == nil) then
|
||||
GFWTable = {};
|
||||
end
|
||||
local G = GFWTable;
|
||||
if (G.Version == nil or (tonumber(G.Version) ~= nil and G.Version < GFWTABLE_THIS_VERSION)) then
|
||||
|
||||
-- Functions
|
||||
G.Mean = GFWTable_temp_Mean;
|
||||
G.Sum = GFWTable_temp_Sum;
|
||||
G.Median = GFWTable_temp_Median;
|
||||
G.Merge = GFWTable_temp_Merge;
|
||||
G.Diff = GFWTable_temp_Diff;
|
||||
G.Subtract = GFWTable_temp_Subtract;
|
||||
G.IndexOf = GFWTable_temp_IndexOf;
|
||||
G.KeyOf = GFWTable_temp_KeyOf;
|
||||
G.Copy = GFWTable_temp_Copy;
|
||||
G.Count = GFWTable_temp_Count;
|
||||
|
||||
-- Set version number
|
||||
G.Version = GFWTABLE_THIS_VERSION;
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
------------------------------------------------------
|
||||
-- GFWUtils.lua
|
||||
-- Useful utility / debug functions
|
||||
------------------------------------------------------
|
||||
|
||||
GFWUTILS_THIS_VERSION = 8;
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
-- Shortcuts for common text color codes
|
||||
function GFWUtils_temp_HiliteText(text)
|
||||
if (text == nil) then return nil; end
|
||||
return HIGHLIGHT_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
|
||||
end
|
||||
function GFWUtils_temp_RedText(text)
|
||||
if (text == nil) then return nil; end
|
||||
return RED_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
|
||||
end
|
||||
function GFWUtils_temp_GrayText(text)
|
||||
if (text == nil) then return nil; end
|
||||
return GRAY_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
|
||||
end
|
||||
function GFWUtils_temp_LightYellowText(text)
|
||||
if (text == nil) then return nil; end
|
||||
return LIGHTYELLOW_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
|
||||
end
|
||||
|
||||
-- Prints a message to the chat frame
|
||||
function GFWUtils_temp_Print(message, r, g, b)
|
||||
if MTH and MTH.Print then
|
||||
MTH:Print(message)
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage(message, (r or GFW_FONT_COLOR.r), (g or GFW_FONT_COLOR.g), (b or GFW_FONT_COLOR.b));
|
||||
end
|
||||
end
|
||||
|
||||
-- Prints a message to the chat frame once per interval (seconds) or once per session if interval is nil
|
||||
function GFWUtils_temp_PrintOnce(message, interval, r, g, b)
|
||||
if (GFWUtils.PrintOnceCache == nil) then
|
||||
GFWUtils.PrintOnceCache = {};
|
||||
end
|
||||
if (interval == nil and GFWUtils.PrintOnceCache[message]) then
|
||||
return;
|
||||
end
|
||||
if (interval and GFWUtils.PrintOnceCache[message] and GetTime() - GFWUtils.PrintOnceCache[message] < interval) then
|
||||
return;
|
||||
end
|
||||
if MTH and MTH.Print then
|
||||
MTH:Print(message)
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage(message, (r or GFW_FONT_COLOR.r), (g or GFW_FONT_COLOR.g), (b or GFW_FONT_COLOR.b));
|
||||
end
|
||||
GFWUtils.PrintOnceCache[message] = GetTime();
|
||||
end
|
||||
|
||||
-- Prints a message to the chat frame only if Debug is set
|
||||
function GFWUtils_temp_DebugLog(message)
|
||||
if (GFWUtils.Debug) then
|
||||
if MTH and MTH.Print then
|
||||
MTH:Print(message, "debug")
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage(message, GFW_DEBUG_COLOR.r, GFW_DEBUG_COLOR.g, GFW_DEBUG_COLOR.b);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Prints a message in yellow to the floating messages frame
|
||||
function GFWUtils_temp_Note(message)
|
||||
UIErrorsFrame:AddMessage(message, 1.0, 1.0, 0.0, 1.0, UIERRORS_HOLD_TIME);
|
||||
end
|
||||
|
||||
-- Converts string.format to a string.find pattern: "%s hits %s for %d." to "(.+) hits (.+) for (%d+)"
|
||||
-- based on Recap by Gello
|
||||
function GFWUtils_temp_FormatToPattern(formatString)
|
||||
|
||||
local patternString = formatString;
|
||||
|
||||
patternString = string.gsub(patternString, "%%%d+%$([diouXxfgbcsq])", "%%%1"); -- reordering specifiers (e.g. %2$s) stripped
|
||||
patternString = string.gsub(patternString, "([%$%(%)%.%[%]%*%+%-%?%^])", "%%%1"); -- convert regex special characters
|
||||
|
||||
patternString = string.gsub(patternString, "%%c", "(.)"); -- %c to (.)
|
||||
patternString = string.gsub(patternString, "%%s", "(.+)"); -- %s to (.+)
|
||||
patternString = string.gsub(patternString, "%%[du]", "(%%d+)"); -- %d to (%d+)
|
||||
patternString = string.gsub(patternString, "%%([gf])", "(%%d+%%.*%%d*)"); -- %g or %f to (%d+%.*%d*)
|
||||
|
||||
return patternString;
|
||||
|
||||
end
|
||||
|
||||
-- Splits a string into a table of strings separated by 'separator'.
|
||||
-- e.g. Split(aString, ", ") is the reverse of table.concat(aTable, ", ")
|
||||
function GFWUtils_temp_Split(aString, separator)
|
||||
if (aString == nil) then return nil; end
|
||||
|
||||
local t = {};
|
||||
local function helper(segment)
|
||||
table.insert(t, segment);
|
||||
end
|
||||
helper((string.gsub(aString, "(.-)"..separator, helper)));
|
||||
return t;
|
||||
end
|
||||
|
||||
-- Capitalizes the first letter of each word in aString.
|
||||
function GFWUtils_temp_TitleCase(aString)
|
||||
if (aString == nil) then return nil; end
|
||||
local function capWords(first, rest)
|
||||
return string.upper(first)..string.lower(rest);
|
||||
end
|
||||
return string.gsub(aString, "(%w)([%w_']*)", capWords);
|
||||
end
|
||||
|
||||
-- Splits a cash amount into gold, siver, and copper
|
||||
function GFWUtils_temp_GSC(money)
|
||||
if (money == nil) then money = 0; end
|
||||
local g = math.floor(money / 10000);
|
||||
local s = math.floor((money - (g*10000)) / 100);
|
||||
local c = math.floor(money - (g*10000) - (s*100));
|
||||
return g,s,c;
|
||||
end
|
||||
|
||||
-- Formats money text by color for gold, silver, copper
|
||||
-- discards copper for amounts greater than 1g unless second arg evaluates true
|
||||
-- based on Auctioneer
|
||||
function GFWUtils_temp_TextGSC(money, noRound)
|
||||
local GSC_GOLD="ffd100";
|
||||
local GSC_SILVER="e6e6e6";
|
||||
local GSC_COPPER="c8602c";
|
||||
local GSC_START="|cff%s%d%s|r";
|
||||
local GSC_PART=" |cff%s%02d%s|r";
|
||||
local GSC_NONE="|cffa0a0a0none|r";
|
||||
|
||||
local g, s, c = GFWUtils.GSC(money);
|
||||
|
||||
local gsc = "";
|
||||
if (g > 0) then
|
||||
gsc = format(GSC_START, GSC_GOLD, g, "g");
|
||||
if (s > 0) then
|
||||
gsc = gsc..format(GSC_PART, GSC_SILVER, s, "s");
|
||||
if (noRound and c > 0) then
|
||||
gsc = gsc..format(GSC_PART, GSC_COPPER, c, "c");
|
||||
end
|
||||
end
|
||||
elseif (s > 0) then
|
||||
gsc = format(GSC_START, GSC_SILVER, s, "s");
|
||||
if (c > 0) then
|
||||
gsc = gsc..format(GSC_PART, GSC_COPPER, c, "c");
|
||||
end
|
||||
elseif (c > 0) then
|
||||
gsc = gsc..format(GSC_START, GSC_COPPER, c, "c");
|
||||
else
|
||||
gsc = GSC_NONE;
|
||||
end
|
||||
|
||||
return gsc;
|
||||
end
|
||||
|
||||
function GFWUtils_temp_ItemLink(linkInfo)
|
||||
local sName, sLink, iQuality, iLevel, sType, sSubType, iCount = GetItemInfo(linkInfo);
|
||||
if (sName) then
|
||||
local _, _, _, color = GetItemQualityColor(iQuality);
|
||||
local linkFormat = "%s|H%s|h[%s]|h|r";
|
||||
return string.format(linkFormat, color, sLink, sName);
|
||||
else
|
||||
return nil;
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
-- load only if not already loaded
|
||||
------------------------------------------------------
|
||||
|
||||
if (GFWUtils == nil) then
|
||||
GFWUtils = {};
|
||||
end
|
||||
local G = GFWUtils;
|
||||
if (G.Version == nil or (tonumber(G.Version) ~= nil and G.Version < GFWUTILS_THIS_VERSION)) then
|
||||
|
||||
-- Constants
|
||||
GFW_FONT_COLOR = {r=0.25, g=1.0, b=1.0};
|
||||
GFW_DEBUG_COLOR = {r=1.0, g=0.75, b=0.25};
|
||||
G.Debug = false;
|
||||
|
||||
-- Functions
|
||||
G.Hilite = GFWUtils_temp_HiliteText;
|
||||
G.Red = GFWUtils_temp_RedText;
|
||||
G.Gray = GFWUtils_temp_GrayText;
|
||||
G.LtY = GFWUtils_temp_LightYellowText;
|
||||
G.Print = GFWUtils_temp_Print;
|
||||
G.PrintOnce = GFWUtils_temp_PrintOnce;
|
||||
G.DebugLog = GFWUtils_temp_DebugLog;
|
||||
G.Note = GFWUtils_temp_Note;
|
||||
G.FormatToPattern = GFWUtils_temp_FormatToPattern;
|
||||
G.Split = GFWUtils_temp_Split;
|
||||
G.TitleCase = GFWUtils_temp_TitleCase;
|
||||
G.GSC = GFWUtils_temp_GSC;
|
||||
G.TextGSC = GFWUtils_temp_TextGSC;
|
||||
G.ItemLink = GFWUtils_temp_ItemLink;
|
||||
|
||||
-- Set version number
|
||||
G.Version = GFWUTILS_THIS_VERSION;
|
||||
end
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
## Interface: 11200
|
||||
## Version: 11200.2
|
||||
## Title: Fizzwidget Feed-O-Matic
|
||||
## Author: Gazmik Fizzwidget
|
||||
## Notes: Helps a Hunter keep his pets well fed (and the food in his inventory under control)
|
||||
## SavedVariables: FOM_Config, FOM_FoodQuality, FOM_AddedFoods, FOM_RemovedFoods, FOM_Cooking, FOM_QuestFood, FOM_LocaleInfo
|
||||
GFWUtils.lua
|
||||
GFWTable.lua
|
||||
localization.lua
|
||||
FeedOMatic_Emotes.lua
|
||||
FeedOMatic_Foods.lua
|
||||
FeedOMatic.lua
|
||||
@@ -0,0 +1,5 @@
|
||||
<Addon name="Fizzwidget Feed-O-Matic" author="Gazmik Fizzwidget" email="gazmik@fizzwidget.com" url="http://fizzwidget.com/huntershelper/">
|
||||
<Description>Helps a Hunter keep his pets well fed (and the food in his inventory under control).</Description>
|
||||
<CurrentVersion ver="11200.2" />
|
||||
<UpdateFile url="http://fizzwidget.com/UpdateUI.xml" />
|
||||
</Addon>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!--
|
||||
FeedOMatic Module Loader
|
||||
Loads all FeedOMatic addon code and wraps it in the MTH module system
|
||||
-->
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<!-- Load original FeedOMatic addon files -->
|
||||
<Include file="GFWUtils.lua"/>
|
||||
<Include file="GFWTable.lua"/>
|
||||
<Include file="localization.lua"/>
|
||||
<Include file="FeedOMatic_Emotes.lua"/>
|
||||
<Include file="FeedOMatic_Foods.lua"/>
|
||||
<Include file="FeedOMatic.lua"/>
|
||||
<Include file="runtime.xml"/>
|
||||
<Include file="UpdateUI.xml"/>
|
||||
|
||||
<!-- Load ModuleHunt wrapper -->
|
||||
<Include file="module.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,304 @@
|
||||
-----------------------------------------------------
|
||||
-- localization.lua
|
||||
-- English strings by default, localizations override with their own.
|
||||
------------------------------------------------------
|
||||
|
||||
-- Key bindings
|
||||
BINDING_HEADER_FEEDOMATIC = "Fizzwidget Feed-O-Matic";
|
||||
BINDING_NAME_FEEDOMATIC = "Feed Pet";
|
||||
|
||||
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
||||
-- THESE STRINGS MUST BE LOCALIZED for Feed-O-Matic to work properly in other locales.
|
||||
FOM_DIET_MEAT = "meat";
|
||||
FOM_DIET_FISH = "fish";
|
||||
FOM_DIET_BREAD = "bread";
|
||||
FOM_DIET_CHEESE = "cheese";
|
||||
FOM_DIET_FRUIT = "fruit";
|
||||
FOM_DIET_FUNGUS = "fungus";
|
||||
|
||||
-- If the player has a buff whose icon name contains "Ability_Mount" and whose name contains one of these substrings, we assume the player is mounted. We have to use this rather oblique way to check for mounted because some other buffs use the Ability_Mount_* icons. If these aren't localized, we may not recognize when the player is mounted and still try to feed the pet.
|
||||
FOM_MOUNT_NAME_SUBSTRINGS = { "kodo", "wolf", "raptor", "steed", "horse", "ram", "saber", "mechanostrider" };
|
||||
|
||||
-- It's not clear whether the 5th and 6th returns from GetItemInfo() are supposed to be localized... so we have localized keys for them just in case. If these aren't localized, we'll just needlessly search your ammo bags for food.
|
||||
FOM_AMMO_POUCH = "Ammo Pouch";
|
||||
FOM_QUIVER = "Quiver";
|
||||
|
||||
-- From here on down, the localized strings are just for readability... they don't affect whether Feed-O-Matic works.
|
||||
|
||||
-- Two special diets; one is used for tracking food that provides a bonus (or at least, that you don't want to have fed to your pet when the 'savebonus' option is on), and another that's used in the chat-line interface for listing all diets.
|
||||
FOM_DIET_BONUS = "bonus";
|
||||
FOM_DIET_ALL = "all";
|
||||
|
||||
-- Used in tooltips to indicate food quality.
|
||||
FOM_QUALITY_UNKNOWN = "%s can eat this, but hasn't tried it yet.";
|
||||
FOM_QUALITY_UNDER = "%s doesn't like this anymore.";
|
||||
FOM_QUALITY_MIGHT = "%s might eat this.";
|
||||
FOM_QUALITY_WILL = "%s will eat this.";
|
||||
FOM_QUALITY_LIKE = "%s likes to eat this.";
|
||||
FOM_QUALITY_LOVE = "%s loves to eat this.";
|
||||
|
||||
-- User-visible errors
|
||||
FOM_ERROR_NO_PET = "You don't have a pet to feed.";
|
||||
FOM_ERROR_PET_DEAD = "Your pet is dead.";
|
||||
FOM_ERROR_NO_FEEDABLE_PET = "You don't have a feedable pet.";
|
||||
FOM_ERROR_IN_COMBAT = "You can't feed your pet during combat.";
|
||||
FOM_ERROR_FOOD_NOT_FOUND = "%s could not find %s in your pack.";
|
||||
FOM_ERROR_NO_FOOD = "%s could not find any food in your pack.";
|
||||
FOM_ERROR_NO_FOOD_NO_FALLBACK = "%s could not find any food in your pack that you haven't forbidden %s to eat.";
|
||||
|
||||
FOM_PRONOUN_MALE = "him";
|
||||
FOM_PRONOUN_FEMALE = "her";
|
||||
|
||||
-- Feeding status messages
|
||||
FOM_FEEDING_EAT_ANOTHER = "%s doesn't like that food and will try something else...";
|
||||
FOM_FEEDING_FEED_ANOTHER = "needs to feed %s something else...";
|
||||
FOM_FEEDING_EAT = "%s eats a %s from your pack.";
|
||||
FOM_FEEDING_FEED = "feeds %s a %s. ";
|
||||
|
||||
FOM_PET_HUNGRY = "%s is hungry!";
|
||||
FOM_PET_VERY_HUNGRY = "%s is very hungry!";
|
||||
|
||||
-- Beast family names
|
||||
BAT = "Bat";
|
||||
BEAR = "Bear";
|
||||
BOAR = "Boar";
|
||||
CARRION_BIRD = "Carrion Bird";
|
||||
CAT = "Cat";
|
||||
CRAB = "Crab";
|
||||
CROCOLISK = "Crocolisk";
|
||||
GORILLA = "Gorilla";
|
||||
HYENA = "Hyena";
|
||||
OWL = "Owl";
|
||||
RAPTOR = "Raptor";
|
||||
SCORPID = "Scorpid";
|
||||
SPIDER = "Spider";
|
||||
TALLSTRIDER = "Tallstrider";
|
||||
TURTLE = "Turtle";
|
||||
WIND_SERPENT = "Wind Serpent";
|
||||
WOLF = "Wolf";
|
||||
|
||||
FOM_OPTIONS_HEADER = "Feed-O-Matic Options";
|
||||
FOM_OPTIONS_GENERAL = "General options:";
|
||||
FOM_OPTIONS_FOOD_CHOICE = "Avoid foods used in Cooking:";
|
||||
FOM_OPTIONS_FEED_NOTIFY = "Notify when feeding:";
|
||||
FOM_OPTIONS_WARNING = "Warn that your pet needs feeding:";
|
||||
|
||||
FOM_KEEPOPEN = "Try to keep at least";
|
||||
FOM_KEEPOPEN_SLOTS = "slots open in your bags.";
|
||||
FOM_KEEPOPEN_INFO = "(Will choose foods from smaller stacks when low on space, regardless of how well your pet likes them.)";
|
||||
|
||||
FOM_OptionsButtonText = {
|
||||
["Tooltip"] = "Show your pet's opinion of foods in their tooltips",
|
||||
["AvoidQuestFood"] = "Avoid foods needed for quests",
|
||||
["AvoidBonusFood"] = "Avoid foods that have a bonus effect when eaten",
|
||||
["PreferHigherQuality"] = "Prefer foods your pet likes more",
|
||||
["Fallback"] = "Fall back to otherwise-avoided foods if out of others",
|
||||
["SaveForCook_All"] = "all foods used in cooking",
|
||||
["SaveForCook_Green"] = "only foods used in |cff3fbf3f\"easy\"|r or better recipes",
|
||||
["SaveForCook_Yellow"] = "only foods used in |cffffff00\"medium\"|r or better recipes",
|
||||
["SaveForCook_Orange"] = "only foods used in |cffff7f3f\"difficult\"|r recipes",
|
||||
["SaveForCook_None"] = "Don't save foods used in cooking",
|
||||
["IconWarning"] = "Flash icon",
|
||||
["TextWarning"] = "Show text",
|
||||
["AudioWarning"] = "Play sound",
|
||||
["AudioWarningBell"] = "Generic bell sound instead of pet-specific",
|
||||
["AlertEmote"] = "Via emote (seen by others)",
|
||||
["AlertChat"] = "In the chat window (seen by you only)",
|
||||
["AlertNone"] = "Don't notify",
|
||||
["LevelContent"] = "when \"content\"",
|
||||
["LevelUnhappy"] = "when \"unhappy\"",
|
||||
["LevelOff"] = "Don't warn",
|
||||
};
|
||||
------------------------------------------------------
|
||||
|
||||
if (GetLocale() == "frFR") then
|
||||
|
||||
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
||||
-- THESE STRINGS MUST BE LOCALIZED for Feed-O-Matic to work properly in other locales.
|
||||
FOM_DIET_MEAT = "viande";
|
||||
FOM_DIET_FISH = "poisson";
|
||||
FOM_DIET_BREAD = "pain";
|
||||
FOM_DIET_CHEESE = "fromage";
|
||||
FOM_DIET_FRUIT = "fruit";
|
||||
FOM_DIET_FUNGUS = "champignon";
|
||||
|
||||
-- If the player has a buff whose icon name contains "Ability_Mount" and whose name contains one of these substrings, we assume the player is mounted. We have to use this rather oblique way to check for mounted because some other buffs use the Ability_Mount_* icons. If these aren't localized, we may not recognize when the player is mounted and still try to feed the pet.
|
||||
FOM_MOUNT_NAME_SUBSTRINGS = { "kodo", "loup", "raptor", "steed", "cheval", "bélier", "tigre", "mécanotrotteur", };
|
||||
|
||||
-- It's not clear whether the 5th and 6th returns from GetItemInfo() are supposed to be localized... so we have localized keys for them just in case. If these aren't localized, we'll just needlessly search your ammo bags for food.
|
||||
FOM_AMMO_POUCH = "Giberne";
|
||||
FOM_QUIVER = "Carquois";
|
||||
|
||||
|
||||
-- From here on down, the localized strings are just for readability... they don't affect whether Feed-O-Matic works.
|
||||
|
||||
-- Two special diets; one is used for tracking food that provides a bonus (or at least, that you don't want to have fed to your pet when the 'savebonus' option is on), and another that's used in the chat-line interface for listing all diets.
|
||||
FOM_DIET_BONUS = "bonus";
|
||||
FOM_DIET_ALL = "tous";
|
||||
|
||||
-- Used in tooltips to indicate food quality.
|
||||
FOM_QUALITY_UNKNOWN = "%s peut le manger, mais n'a jamais essayé.";
|
||||
FOM_QUALITY_UNDER = "%s n'en mange plus désormais.";
|
||||
FOM_QUALITY_MIGHT = "%s en mangera peut-être.";
|
||||
FOM_QUALITY_WILL = "%s en mangera.";
|
||||
FOM_QUALITY_LIKE = "%s aime en manger.";
|
||||
FOM_QUALITY_LOVE = "%s adore en manger.";
|
||||
|
||||
-- User-visible errors
|
||||
FOM_ERROR_NO_PET = "Vous n'avez pas de familier.";
|
||||
FOM_ERROR_PET_DEAD = "Votre familier est mort.";
|
||||
FOM_ERROR_NO_FEEDABLE_PET = "Vous n'avez pas de familier capable de manger.";
|
||||
FOM_ERROR_FOOD_NOT_FOUND = "%s n'a pas trouvé de %s dans votre sac.";
|
||||
FOM_ERROR_NO_FOOD = "%s n'a pas trouvé de nourriture dans votre sac.";
|
||||
|
||||
-- Feeding status messages
|
||||
FOM_FEEDING_EAT_ANOTHER = "%s n'aime pas cette nourriture et va essayer autre chose..."
|
||||
FOM_FEEDING_FEED_ANOTHER = "cherche autre chose à donner à %s...";
|
||||
FOM_FEEDING_EAT = "%s mange un(e) %s.";
|
||||
FOM_FEEDING_FEED = "donne à %s à manger un(e) %s. ";
|
||||
|
||||
-- Beast family names
|
||||
BAT = "Chauve-souris";
|
||||
BEAR = "Ours";
|
||||
BOAR = "Sanglier";
|
||||
CARRION_BIRD = "Charognard";
|
||||
CAT = "Félin";
|
||||
CRAB = "Crabe";
|
||||
CROCOLISK = "Crocilisque";
|
||||
GORILLA = "Gorille";
|
||||
HYENA = "Hyène";
|
||||
OWL = "Chouette";
|
||||
RAPTOR = "Raptor";
|
||||
SCORPID = "Scorpide";
|
||||
SPIDER = "Araignée";
|
||||
TALLSTRIDER = "Haut-trotteur";
|
||||
TURTLE = "Tortue";
|
||||
WIND_SERPENT = "Serpent des vents";
|
||||
WOLF = "Loup";
|
||||
|
||||
FOM_PET_HUNGRY = "%s a faim!";
|
||||
FOM_PET_VERY_HUNGRY = "%s a très faim!";
|
||||
|
||||
FOM_OPTIONS_HEADER = "Feed-O-Matic Options";
|
||||
FOM_OPTIONS_GENERAL = "Options générales:";
|
||||
FOM_OPTIONS_FOOD_CHOICE = "Eviter la nourriture utilisée en cuisine:";
|
||||
FOM_OPTIONS_FEED_NOTIFY = "Prévenir lorsque votre familier est nourrit:";
|
||||
FOM_OPTIONS_WARNING = "Avertir quand votre familier a besoin d'être nourrit:";
|
||||
|
||||
FOM_KEEPOPEN = "Essayer de garder au moins";
|
||||
FOM_KEEPOPEN_SLOTS = "emplacements de sac libres";
|
||||
FOM_KEEPOPEN_INFO = "(Le familier choisira la nourriture des piles les plus petites, sans tenir compte de ses préférences.)";
|
||||
|
||||
FOM_OptionsButtonText = {
|
||||
["Tooltip"] = "Afficher l'avis de votre familier concernant la nourriture",
|
||||
["AvoidQuestFood"] = "Eviter la nourriture utile dans les quêtes",
|
||||
["AvoidBonusFood"] = "Eviter la nourriture donnant un bonus",
|
||||
["PreferHigherQuality"] = "Privilégier la nourriture que votre familier préfère",
|
||||
["Fallback"] = "Utiliser la nourriture évitée s'il n'y en a plus d'autres",
|
||||
["SaveForCook_All"] = "Toutes nourritures utilisées pour la cuisine",
|
||||
["SaveForCook_Green"] = "si elle est utilisée dans les recettes |cff3fbf3f\"faciles\"|r ou supérieures",
|
||||
["SaveForCook_Yellow"] = "si elle est utilisée dans les recettes |cffffff00\"moyennes\"|r ou supérieures",
|
||||
["SaveForCook_Orange"] = "si elle est utilisée dans les recettes |cffff7f3f\"difficiles\"|r",
|
||||
["SaveForCook_None"] = "Ne pas éviter la nourriture utilisée en cuisine",
|
||||
["IconWarning"] = "Clignoter l'icône",
|
||||
["TextWarning"] = "Afficher un texte",
|
||||
["AudioWarning"] = "Jouer un son",
|
||||
["AudioWarningBell"] = "Un son de cloche au lieu du cri du familier",
|
||||
["AlertEmote"] = "Via emote (visible par les autres)",
|
||||
["AlertChat"] = "Dans la fenêtre de discussion (visible uniquement par vous)",
|
||||
["AlertNone"] = "Ne pas prévenir",
|
||||
["LevelContent"] = "quand \"content\"",
|
||||
["LevelUnhappy"] = "quand \"mécontent\"",
|
||||
["LevelOff"] = "Ne pas avertir",
|
||||
};
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
if (GetLocale() == "deDE") then
|
||||
|
||||
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
||||
-- THESE STRINGS MUST BE LOCALIZED for Feed-O-Matic to work properly in other locales.
|
||||
FOM_DIET_MEAT = "fleisch";
|
||||
FOM_DIET_FISH = "fisch";
|
||||
FOM_DIET_BREAD = "brot";
|
||||
FOM_DIET_CHEESE = "käse";
|
||||
FOM_DIET_FRUIT = "obst";
|
||||
-- FOM_DIET_FUNGUS = "fungus"; -- same as English (?), so we don't need to re-define it.
|
||||
|
||||
-- If the player has a buff whose icon name contains "Ability_Mount" and whose name contains one of these substrings, we assume the player is mounted. We have to use this rather oblique way to check for mounted because some other buffs use the Ability_Mount_* icons. If these aren't localized, we may not recognize when the player is mounted and still try to feed the pet.
|
||||
-- FOM_MOUNT_NAME_SUBSTRINGS = { "kodo", "wolf", "raptor", "steed", "horse", "ram", "saber", "mechanostrider" };
|
||||
|
||||
-- It's not clear whether the 5th and 6th returns from GetItemInfo() are supposed to be localized... so we have localized keys for them just in case.
|
||||
FOM_AMMO_POUCH = "Munitionsbeutel";
|
||||
FOM_QUIVER = "Köcher";
|
||||
|
||||
-- From here on down, the localized strings are just for readability; they don't affect whether Feed-O-Matic works.
|
||||
|
||||
-- Two special diets; one is used for tracking food that provides a bonus (or at least, that you don't want to have fed to your pet when the 'savebonus' option is on), and another that's used in the chat-line interface for listing all diets.
|
||||
-- FOM_DIET_BONUS = "bonus"; -- same as English(?), so we don't need to re-define it.
|
||||
FOM_DIET_ALL = "alles";
|
||||
|
||||
-- Used in tooltips to indicate food quality.
|
||||
FOM_QUALITY_UNKNOWN = "%s kann das fressen, hat es aber noch nicht probiert.";
|
||||
FOM_QUALITY_UNDER = "%s mag das nicht mehr fressen.";
|
||||
FOM_QUALITY_MIGHT = "%s mag das möglicherweise fressen.";
|
||||
FOM_QUALITY_WILL = "%s mag das fressen.";
|
||||
FOM_QUALITY_LIKE = "%s frisst das gerne.";
|
||||
FOM_QUALITY_LOVE = "%s liebt es, das zu fressen.";
|
||||
|
||||
-- User-visible errors
|
||||
FOM_ERROR_NO_PET = "Du hast kein Tier um es zu füttern.";
|
||||
FOM_ERROR_PET_DEAD = "Dein Tier ist tot.";
|
||||
FOM_ERROR_NO_FEEDABLE_PET = "Du hast kein Tier das man füttern kann.";
|
||||
FOM_ERROR_FOOD_NOT_FOUND = "%s kann %s nicht in Deinem Rucksack finden.";
|
||||
FOM_ERROR_NO_FOOD = "%s findet nichts zu fressen in Deinem Rucksack.";
|
||||
|
||||
-- Feeding status messages
|
||||
FOM_FEEDING_EAT_ANOTHER = "%s mag dieses Futter nicht und probiert etwas anderes...";
|
||||
FOM_FEEDING_FEED_ANOTHER = "sucht nach etwas anderem um %s zu füttern...";
|
||||
FOM_FEEDING_EAT = "%s frisst ein %s aus Deinem Rucksack.";
|
||||
FOM_FEEDING_FEED = "füttert %s ein %s. ";
|
||||
|
||||
-- Beast family names
|
||||
BAT = "Fledermaus";
|
||||
BEAR = "Bär";
|
||||
BOAR = "Eber";
|
||||
CARRION_BIRD = "Aasvogel";
|
||||
CAT = "Katze";
|
||||
CRAB = "Krebs";
|
||||
CROCOLISK = "Krokilisk";
|
||||
-- GORILLA = "Gorilla"; -- same as enUS
|
||||
HYENA = "Hyäne";
|
||||
OWL = "Eule";
|
||||
-- RAPTOR = "Raptor"; -- same as enUS
|
||||
SCORPID = "Skorpid";
|
||||
SPIDER = "Spinne";
|
||||
TALLSTRIDER = "Weitschreiter";
|
||||
TURTLE = "Schildkröte";
|
||||
WIND_SERPENT = "Windnatter";
|
||||
-- WOLF = "Wolf"; -- same as enUS
|
||||
|
||||
end
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
if (GetLocale() == "koKR") then
|
||||
|
||||
-- Diet names. These should be the all-lowercase versions of the six diets returned from GetPetFoodTypes(). (Want to get them all nice and quick for your localization? Go tame a bear... they eat anything.)
|
||||
-- THESE STRINGS MUST BE LOCALIZED for Feed-O-Matic to work properly in other locales.
|
||||
-- FOM_DIET_MEAT = "meat";
|
||||
-- FOM_DIET_FISH = "fish";
|
||||
-- FOM_DIET_BREAD = "bread";
|
||||
-- FOM_DIET_CHEESE = "cheese";
|
||||
-- FOM_DIET_FRUIT = "fruit";
|
||||
-- FOM_DIET_FUNGUS = "fungus";
|
||||
|
||||
-- If the player has a buff whose icon name contains "Ability_Mount" and whose name contains one of these substrings, we assume the player is mounted. We have to use this rather oblique way to check for mounted because some other buffs use the Ability_Mount_* icons.
|
||||
-- FOM_MOUNT_NAME_SUBSTRINGS = { "kodo", "wolf", "raptor", "steed", "horse", "ram", "saber", "mechanostrider" };
|
||||
|
||||
-- It's not clear whether the 5th and 6th returns from GetItemInfo() are supposed to be localized... so we have localized keys for them just in case.
|
||||
-- FOM_AMMO_POUCH = "Ammo Pouch";
|
||||
FOM_QUIVER = "화살통";
|
||||
|
||||
end
|
||||
@@ -0,0 +1,340 @@
|
||||
------------------------------------------------------
|
||||
-- MetaHunt: FeedOMatic Module Wrapper
|
||||
-- Modern module abstraction for the FeedOMatic addon
|
||||
------------------------------------------------------
|
||||
|
||||
local MTH_FeedOMatic = {
|
||||
name = "feedomatic",
|
||||
enabled = false,
|
||||
version = "1.0.3",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"MERCHANT_SHOW",
|
||||
"MERCHANT_UPDATE",
|
||||
"MTH_PET_LIVE_STATE_CHANGED",
|
||||
"PET_ATTACK_START",
|
||||
"PET_ATTACK_STOP",
|
||||
"PET_STABLE_SHOW",
|
||||
"PET_STABLE_UPDATE",
|
||||
"TRADE_SKILL_SHOW",
|
||||
"TRADE_SKILL_UPDATE",
|
||||
"CHAT_MSG_SPELL_TRADESKILLS",
|
||||
"CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS",
|
||||
"UI_ERROR_MESSAGE",
|
||||
"PET_BAR_SHOWGRID",
|
||||
"PET_BAR_UPDATE",
|
||||
"PET_UI_UPDATE",
|
||||
"UNIT_HAPPINESS",
|
||||
"PLAYER_REGEN_ENABLED",
|
||||
},
|
||||
initialized = false,
|
||||
variablesLoadedProcessed = false,
|
||||
}
|
||||
|
||||
local MTH_PETL_HOOK_BOUNDARY_KEY = "pet-lifecycle-hooks"
|
||||
local MTH_FeedOMatic_MerchantProbeFrame = nil
|
||||
|
||||
function MTH_FeedOMatic_OnUpdate(elapsed)
|
||||
if not elapsed then
|
||||
return
|
||||
end
|
||||
if not (MTH and MTH.IsModuleEnabled and MTH:IsModuleEnabled("feedomatic", true)) then
|
||||
return
|
||||
end
|
||||
if type(FOM_OnUpdate) == "function" then
|
||||
FOM_OnUpdate(elapsed)
|
||||
end
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_GetRuntimeFrame()
|
||||
return getglobal("Frame_GFW_FeedOMatic")
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_CaptureHookBoundary()
|
||||
if not (MTH and MTH.CaptureHookBoundary) then
|
||||
return
|
||||
end
|
||||
MTH:CaptureHookBoundary(MTH_PETL_HOOK_BOUNDARY_KEY, {
|
||||
{ globalName = "PetAbandon", originalName = "MTH_PETL_Original_PetAbandon" },
|
||||
})
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_RestoreHookBoundary()
|
||||
if not (MTH and MTH.RestoreHookBoundary) then
|
||||
return
|
||||
end
|
||||
MTH:RestoreHookBoundary(MTH_PETL_HOOK_BOUNDARY_KEY)
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_ApplyLegacyHooks()
|
||||
local canTouchPetAbandon = true
|
||||
if MTH and MTH.GetGlobalHookOwner then
|
||||
local abandonOwner = MTH:GetGlobalHookOwner("PetAbandon")
|
||||
if abandonOwner and abandonOwner ~= MTH_PETL_HOOK_BOUNDARY_KEY then
|
||||
canTouchPetAbandon = false
|
||||
end
|
||||
end
|
||||
|
||||
local abandonHook = MTH_PetAbandonHook or FOM_PetAbandon
|
||||
local abandonOriginal = MTH_PETL_Original_PetAbandon or FOM_Original_PetAbandon
|
||||
if type(abandonHook) == "function" and type(abandonOriginal) == "function" then
|
||||
if canTouchPetAbandon and (PetAbandon == abandonOriginal or PetAbandon == abandonHook) then
|
||||
PetAbandon = abandonHook
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_CallLegacyOnEvent(evt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
if type(FOM_OnEvent) ~= "function" then
|
||||
return
|
||||
end
|
||||
|
||||
local frame = MTH_FeedOMatic_GetRuntimeFrame()
|
||||
if not frame then
|
||||
return
|
||||
end
|
||||
|
||||
local oldThis = this
|
||||
local oldEvent = event
|
||||
local oldArg1, oldArg2, oldArg3, oldArg4, oldArg5 = arg1, arg2, arg3, arg4, arg5
|
||||
local oldArg6, oldArg7, oldArg8, oldArg9 = arg6, arg7, arg8, arg9
|
||||
|
||||
this = frame
|
||||
event = evt
|
||||
arg1, arg2, arg3, arg4, arg5 = a1, a2, a3, a4, a5
|
||||
arg6, arg7, arg8, arg9 = a6, a7, a8, a9
|
||||
|
||||
local ok = pcall(function()
|
||||
FOM_OnEvent(evt, a1)
|
||||
end)
|
||||
|
||||
this = oldThis
|
||||
event = oldEvent
|
||||
arg1, arg2, arg3, arg4, arg5 = oldArg1, oldArg2, oldArg3, oldArg4, oldArg5
|
||||
arg6, arg7, arg8, arg9 = oldArg6, oldArg7, oldArg8, oldArg9
|
||||
|
||||
if not ok and MTH and MTH.DebugPrint then
|
||||
MTH:DebugPrint("FeedOMatic legacy OnEvent call failed for event: " .. tostring(evt))
|
||||
end
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_EnsureVariablesLoaded(module)
|
||||
if not module or module.variablesLoadedProcessed then
|
||||
return
|
||||
end
|
||||
|
||||
MTH_FeedOMatic_CallLegacyOnEvent("VARIABLES_LOADED")
|
||||
module.variablesLoadedProcessed = true
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_SyncSavedVariables()
|
||||
if not MTH or not MTH.GetModuleSavedVariables then
|
||||
return
|
||||
end
|
||||
|
||||
local moduleStore = MTH:GetModuleSavedVariables("feedomatic")
|
||||
if not moduleStore.legacy then
|
||||
moduleStore.legacy = {}
|
||||
end
|
||||
|
||||
if type(FOM_Config) == "table" then
|
||||
moduleStore.legacy.FOM_Config = FOM_Config
|
||||
elseif type(moduleStore.legacy.FOM_Config) == "table" then
|
||||
FOM_Config = moduleStore.legacy.FOM_Config
|
||||
end
|
||||
|
||||
if type(FOM_FoodQuality) == "table" then
|
||||
moduleStore.legacy.FOM_FoodQuality = FOM_FoodQuality
|
||||
elseif type(moduleStore.legacy.FOM_FoodQuality) == "table" then
|
||||
FOM_FoodQuality = moduleStore.legacy.FOM_FoodQuality
|
||||
end
|
||||
|
||||
if type(FOM_AddedFoods) == "table" then
|
||||
moduleStore.legacy.FOM_AddedFoods = FOM_AddedFoods
|
||||
elseif type(moduleStore.legacy.FOM_AddedFoods) == "table" then
|
||||
FOM_AddedFoods = moduleStore.legacy.FOM_AddedFoods
|
||||
end
|
||||
|
||||
if type(FOM_RemovedFoods) == "table" then
|
||||
moduleStore.legacy.FOM_RemovedFoods = FOM_RemovedFoods
|
||||
elseif type(moduleStore.legacy.FOM_RemovedFoods) == "table" then
|
||||
FOM_RemovedFoods = moduleStore.legacy.FOM_RemovedFoods
|
||||
end
|
||||
|
||||
if type(FOM_Cooking) == "table" then
|
||||
moduleStore.legacy.FOM_Cooking = FOM_Cooking
|
||||
elseif type(moduleStore.legacy.FOM_Cooking) == "table" then
|
||||
FOM_Cooking = moduleStore.legacy.FOM_Cooking
|
||||
end
|
||||
|
||||
if type(FOM_QuestFood) == "table" then
|
||||
moduleStore.legacy.FOM_QuestFood = FOM_QuestFood
|
||||
elseif type(moduleStore.legacy.FOM_QuestFood) == "table" then
|
||||
FOM_QuestFood = moduleStore.legacy.FOM_QuestFood
|
||||
end
|
||||
|
||||
if type(FOM_LocaleInfo) == "table" then
|
||||
moduleStore.legacy.FOM_LocaleInfo = FOM_LocaleInfo
|
||||
elseif type(moduleStore.legacy.FOM_LocaleInfo) == "table" then
|
||||
FOM_LocaleInfo = moduleStore.legacy.FOM_LocaleInfo
|
||||
end
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_Log(message, severity)
|
||||
if type(MTH_Log) == "function" then
|
||||
local logSeverity = severity or "debug"
|
||||
MTH_Log("[FeedOMatic] " .. tostring(message or ""), logSeverity)
|
||||
end
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_DebugMerchantScan(sourceEvent)
|
||||
if type(MTH_GetMerchantFoodsByDiet) ~= "function" then
|
||||
MTH_FeedOMatic_Log(tostring(sourceEvent) .. ": MTH_GetMerchantFoodsByDiet is not available yet")
|
||||
return
|
||||
end
|
||||
|
||||
local merchantFoods = MTH_GetMerchantFoodsByDiet()
|
||||
local knownCount = 0
|
||||
local unknownCount = 0
|
||||
if type(merchantFoods) == "table" then
|
||||
if type(merchantFoods.items) == "table" then
|
||||
knownCount = table.getn(merchantFoods.items)
|
||||
end
|
||||
if type(merchantFoods.unknown) == "table" then
|
||||
unknownCount = table.getn(merchantFoods.unknown)
|
||||
end
|
||||
end
|
||||
|
||||
local merchantName = UnitName("npc") or UnitName("target") or "unknown"
|
||||
MTH_FeedOMatic_Log(tostring(sourceEvent) .. ": wrapper scan for " .. tostring(merchantName) .. " | known=" .. tostring(knownCount) .. " | unknown=" .. tostring(unknownCount))
|
||||
|
||||
if type(merchantFoods.byDiet) == "table" then
|
||||
for dietName, rows in merchantFoods.byDiet do
|
||||
local dietCount = 0
|
||||
if type(rows) == "table" then
|
||||
dietCount = table.getn(rows)
|
||||
end
|
||||
MTH_FeedOMatic_Log("diet " .. tostring(dietName) .. ": " .. tostring(dietCount) .. " item(s)", "debug")
|
||||
if type(rows) == "table" then
|
||||
for _, row in rows do
|
||||
MTH_FeedOMatic_Log(" - [" .. tostring(row.id) .. "] " .. tostring(row.name) .. " (slot=" .. tostring(row.index) .. ")", "debug")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if unknownCount > 0 and type(merchantFoods.unknown) == "table" then
|
||||
for _, row in merchantFoods.unknown do
|
||||
MTH_FeedOMatic_Log("unknown map: [" .. tostring(row.id) .. "] " .. tostring(row.name) .. " (slot=" .. tostring(row.index) .. ")", "debug")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function MTH_FeedOMatic_SetMerchantProbeEnabled(enabled)
|
||||
if not MTH_FeedOMatic_MerchantProbeFrame then
|
||||
MTH_FeedOMatic_MerchantProbeFrame = CreateFrame("Frame", "MTH_FeedOMatic_MerchantProbeFrame")
|
||||
MTH_FeedOMatic_MerchantProbeFrame:SetScript("OnEvent", function()
|
||||
local evt = event
|
||||
if evt == "MERCHANT_SHOW" or evt == "MERCHANT_UPDATE" then
|
||||
MTH_FeedOMatic_Log("probe event received: " .. tostring(evt), "debug")
|
||||
MTH_FeedOMatic_DebugMerchantScan(evt)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if enabled then
|
||||
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_SHOW")
|
||||
MTH_FeedOMatic_MerchantProbeFrame:RegisterEvent("MERCHANT_UPDATE")
|
||||
MTH_FeedOMatic_Log("merchant probe enabled", "debug")
|
||||
else
|
||||
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_SHOW")
|
||||
MTH_FeedOMatic_MerchantProbeFrame:UnregisterEvent("MERCHANT_UPDATE")
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_FeedOMatic:init()
|
||||
-- FeedOMatic initializes via its VARIABLES_LOADED event
|
||||
-- This is called after the core MTH framework is loaded
|
||||
MTH_FEED_WRAPPER_MODE = true
|
||||
MTH_FOM_WRAPPER_MODE = MTH_FEED_WRAPPER_MODE
|
||||
MTH_FeedOMatic_SyncSavedVariables()
|
||||
|
||||
if not self.initialized and not getglobal("FOM_METAHUNT_ONLOAD_DONE") and FOM_OnLoad then
|
||||
local frame = MTH_FeedOMatic_GetRuntimeFrame()
|
||||
if frame then
|
||||
local oldThis = this
|
||||
this = frame
|
||||
pcall(function()
|
||||
FOM_OnLoad()
|
||||
end)
|
||||
this = oldThis
|
||||
FOM_METAHUNT_ONLOAD_DONE = true
|
||||
end
|
||||
end
|
||||
|
||||
MTH_FeedOMatic_CaptureHookBoundary()
|
||||
|
||||
self.initialized = true
|
||||
if self.enabled then
|
||||
MTH_FeedOMatic_EnsureVariablesLoaded(self)
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_FeedOMatic:setEnabled(enabled)
|
||||
if enabled then
|
||||
if not self.initialized then
|
||||
self:init()
|
||||
end
|
||||
MTH_FeedOMatic_ApplyLegacyHooks()
|
||||
MTH_FeedOMatic_CaptureHookBoundary()
|
||||
MTH_FeedOMatic_SyncSavedVariables()
|
||||
MTH_FeedOMatic_EnsureVariablesLoaded(self)
|
||||
MTH_FeedOMatic_SetMerchantProbeEnabled(false)
|
||||
if FOM_FeedButton then
|
||||
FOM_FeedButton:Show()
|
||||
end
|
||||
else
|
||||
-- Disable FeedOMatic functionality
|
||||
MTH_FeedOMatic_RestoreHookBoundary()
|
||||
if type(FOM_State) == "table" then
|
||||
FOM_State.ShouldFeed = false
|
||||
end
|
||||
MTH_FeedOMatic_SetMerchantProbeEnabled(false)
|
||||
if FOM_FeedButton then
|
||||
FOM_FeedButton:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_FeedOMatic:onEvent(event, arg1, arg2, arg3, arg4, arg5)
|
||||
if event == "VARIABLES_LOADED" then
|
||||
MTH_FeedOMatic_EnsureVariablesLoaded(self)
|
||||
return
|
||||
end
|
||||
|
||||
if event == "MTH_PET_LIVE_STATE_CHANGED" then
|
||||
MTH_FeedOMatic_CallLegacyOnEvent("PET_BAR_UPDATE")
|
||||
MTH_FeedOMatic_CallLegacyOnEvent("PET_UI_UPDATE")
|
||||
MTH_FeedOMatic_CallLegacyOnEvent("UNIT_HAPPINESS", "pet")
|
||||
return
|
||||
end
|
||||
|
||||
MTH_FeedOMatic_CallLegacyOnEvent(event, arg1, arg2, arg3, arg4, arg5)
|
||||
end
|
||||
|
||||
function MTH_FeedOMatic:cleanup()
|
||||
-- Cleanup code when module is unloaded
|
||||
MTH_FeedOMatic_RestoreHookBoundary()
|
||||
if type(FOM_State) == "table" then
|
||||
FOM_State.ShouldFeed = false
|
||||
end
|
||||
MTH_FeedOMatic_SetMerchantProbeEnabled(false)
|
||||
if FOM_FeedButton then
|
||||
FOM_FeedButton:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
-- Register with MTH
|
||||
MTH:RegisterModule("feedomatic", MTH_FeedOMatic)
|
||||
|
||||
MTH_FOM_OnUpdate = MTH_FeedOMatic_OnUpdate
|
||||
@@ -0,0 +1,87 @@
|
||||
------------------------------------------------------
|
||||
Fizzwidget Feed-O-Matic
|
||||
by Gazmik Fizzwidget
|
||||
http://fizzwidget.com
|
||||
gazmik@fizzwidget.com
|
||||
------------------------------------------------------
|
||||
|
||||
As my Hunter friends can readily attest, keeping a wild pet can be a full-time job. Why, just feeding the critter when he gets hungry can throw off your routine -- you've got to rummage around in your bags, find a piece of food, make sure it's appropriate for his diet, and check your aim before tossing it to him (lest you accidentally destroy a tasty morsel). So inconvenient! Not to mention potentially dangerous... you don't want to spend so long digging through your bags that you or your pet become someone else's snack.
|
||||
|
||||
Never fear, Gazmik Fizzwidget is here with a new gadget to automate all your pet-food-management tasks! My incredible Feed-O-Matic features state-of-the-art nutritional analyzers to make sure your pet's hunger is satisfied with a minimum of fuss, advanced selective logic to make your pet doesn't eat anything you have another use for, and a weight optimizer to make sure the food in your bags stays well organized! Just press the "Feed Now" button and it'll intelligently choose a food and accurately toss it to your pet. This is actually one of the first gizmos I started work on... but because I'm a perfectionist I haven't considered it ready for release until now.
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
INSTALLATION: Put this folder into your World Of Warcraft/Interface/AddOns folder and launch WoW.
|
||||
|
||||
USAGE:
|
||||
Makes feeding your pet quick, easy, and fun:
|
||||
- Bind a key to "Feed Pet", and Feed-O-Matic will automatically choose an appropriate food and give it to the pet whenever you press it.
|
||||
- Can use an emote to notify you when it's feeding your pet, with custom randomized messages. See FeedOMatic_Emotes.lua to customize them to your characters!
|
||||
|
||||
Helps you manage all the pet food in your inventory:
|
||||
- Keeps track of which foods your pet likes more, and prioritizes "better" foods when choosing what to feed the pet. Also remembers what foods your pet has "outgrown", and doesn't choose them in the future (unless you've switched to a pet who might have different tastes).
|
||||
- If you're on a quest to collect several of a certain item which also happens to be something your pet likes to eat, Feed-O-Matic can avoid consuming it. (Unless you're carrying more than is needed for the quest or there's nothing else for your pet to eat.)
|
||||
- Feed-O-Matic can keep track of what foods are used by the Cooking recipes you know and avoid choosing food you'd rather cook; this behavior can be customized based on the difficulty of the recipies (so, for example, you can either save all cookable food or only save the foods most likely to increase your Cooking skill).
|
||||
- If you'd prefer to save the better food (that is, those which provide a "well fed" bonus or other effect when eaten) for yourself, Feed-O-Matic can also avoid it when looking for pet food.
|
||||
- All other things being equal, Feed-O-Matic will try to pick foods from smaller stacks, making sure your food supply doesn't take up all your bag space. When your bags get close to full, Feed-O-Matic will start ignoring other criteria and always choosing the smallest stack so that you won't run out of inventory sooner.
|
||||
|
||||
CHAT COMMANDS:
|
||||
`/feedomatic` (or `/fom` or `/feed`) - Show the Options window.
|
||||
or:
|
||||
`/feedomatic` (or `/fom` or `/feed`) <command>
|
||||
where <command> can be any of the following:
|
||||
`help` - Print this helplist.
|
||||
`status` - Check current settings.
|
||||
`reset` - Reset to default settings.
|
||||
`feed` - Feed your pet (automatically finds an appropriate food).
|
||||
`feed <item link>` - Feed your pet a specific food.
|
||||
`add <diet> <item link>` - Add food to the list for a specific diet (meat, fish, fruit, etc).
|
||||
`remove <diet> <item link>` - Remove food from the list.
|
||||
`show <diet>` - Show food list for a specific diet (or for `all`).
|
||||
|
||||
CAVEATS, ETC.:
|
||||
- Feed-O-Matic has a database of many known foods, but it's not guaranteed to be comprehensive. You can use the `add`, `remove`, and `show` commands noted above to manage these lists directly. (Please drop me a line if you find a food that should be on there, or discover that something on the list shouldn't be there.)
|
||||
- Currently, Feed-O-Matic can only update its list of which foods you know how to cook when your Cooking window is open. (So if you read a new recipe, we won't know to preserve the ingredients until you open your Cooking window again.)
|
||||
- Only works in English, French, and German (for now). Localizers interested in helping with other WoW client languages please contact gazmik@fizzwidget.com.
|
||||
|
||||
------------------------------------------------------
|
||||
VERSION HISTORY
|
||||
|
||||
v. 12000.2 - 2006/10/27
|
||||
- Now always prefers conjured foods if available when feeding a pet that can eat them. (This was supposed to have been the case before, but the implementation turned out to be unreliable.)
|
||||
- Fixed some issues which could result in Feed-O-Matic feeding the pet a food you'd told it to avoid, even if the "fall back" option was turned off. Also, a clearer error message is given if "fall back" is off and we can't find any allowed foods.
|
||||
- The various reminder options for when your pet needs feeding (flashing the happiness icon, text messages, sounds) are now suppressed while you or your pet is in combat or if your pet is dead.
|
||||
- Feed-O-Matic posts its own error message if you attempt use it to feed your pet while in combat. (Instead of trying to feed the pet anyway, causing WoW itself to post an error message.)
|
||||
- Added a number of items to the default foods list (including some holiday treats and the new level 55 mage-conjured bread).
|
||||
|
||||
v. 11200.1 - 2006/08/22
|
||||
- Updated TOC to reflect compatibility with WoW patch 1.12.
|
||||
- Updated use of WoW's UnitSex() function to match changes in its behavior from WoW patch 1.11... your pet's gender should be reported correctly again.
|
||||
|
||||
v. 11100.1 - 2006/06/20
|
||||
- Updated TOC to reflect compatibility with WoW patch 1.11. (No actual changes were needed.)
|
||||
- Added French localization by "Artaher Medivh".
|
||||
|
||||
v. 11000.4 - 2006/04/17
|
||||
- Fixed some issues with the tooltip code shared across Fizzwidget addons; Feed-O-Matic's addition to item tooltips should now be able to show up in just about every place you can get an item tooltip.
|
||||
|
||||
v. 11000.3 - 2006/04/11
|
||||
- Feed-O-Matic settings can now be edited via a new Options panel. Typing `/fom` alone shows this panel (the various configuration subcommands, e.g. `/fom alert`, etc., are still available), which controls all aspects of Feed-O-Matic's behavior except for its list of known foods (for now, you'll still need to use slash commands to edit that).
|
||||
- Additional options are available for warning you that your pet needs feeding: besides flashing the default UI's pet happiness icon, Feed-O-Matic can now also alert you via text message or with the sounds of your pet begging for food. (If you don't like these species-specific pet noises, there's also an option to have a simple bell sound as reminder.)
|
||||
- You can now click the default UI's pet happiness icon to invoke Feed-O-Matic's feeding function. (This makes three ways to feed your pet with Feed-O-Matic: click the icon, set up a key for Feed Pet in the standard Key Bindings menu, or type or macro `/fom feed`.) Right-click the icon to show the new Options panel.
|
||||
- Fixed a bug where we could bloat the SavedVariables file when attempting to clean it up upon visiting a stable master. (Now we properly discard data from pets no longer in service.)
|
||||
- Fixed a bug where we'd still keep trying to feed a food to the pet after finding out it's too low level.
|
||||
|
||||
v. 11000.2 - 2006/04/01
|
||||
- Due to changes in WoW patch 1.10, it's no longer possible for UI addons to feed your pet automatically without direct input; the automatic feeding function is thus no longer available in Feed-O-Matic. You may still find Feed-O-Matic quite useful for its ability to automatically choose foods for your pet and feed them at the touch of a button -- the "Feed Pet" button (configurable in WoW's Key Bindings menu) and `/fom feed` chat/macro command still work just great.
|
||||
- As an aid to those suffering auto-feed withdrawal, there's now an option for Feed-O-Matic to provide an extra reminder when your pet needs feeding (in case you find the icon next to your pet's health bar too subtle). This is accessed by the same `/fom level` command that previously controlled automatic feeding; when your pet's happiness falls below the specified level, the happiness icon will blink until you feed him enough to sate his hunger.
|
||||
- Fixed a bug where an error panel could appear when attempting to feed the pet with the `fallback` option turned off and the only foods in your inventory being types you'd prefer to avoid.
|
||||
- KNOWN BUG: The tooltip additions aren't showing up in all cases where they should. Another update to address this issue should be coming along soon.
|
||||
|
||||
v. 11000.1 - 2006/03/28
|
||||
- Updated for compatibility with WoW patch 1.10. (Minor changes were needed.)
|
||||
- Should no longer disconnect if you have feed emotes turned on and you try to feed your pet a Legendary item. (Probably not a bug many experienced, but still...)
|
||||
- Minor improvements to utility code shared across Fizzwidget addons.
|
||||
- KNOWN BUG: The tooltip additions aren't showing up in all cases where they should. Another update to address this issue should be coming along soon.
|
||||
|
||||
See http://fizzwidget.com/notes/feedomatic/ for older release notes.
|
||||
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
FeedOMatic Runtime Frame Loader (MetaHunt)
|
||||
Minimal runtime XML without legacy options window definitions.
|
||||
-->
|
||||
<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="Frame_GFW_FeedOMatic">
|
||||
<Scripts>
|
||||
<OnUpdate>
|
||||
if (MTH_FOM_OnUpdate) then
|
||||
MTH_FOM_OnUpdate(arg1);
|
||||
elseif (FOM_OnUpdate) then
|
||||
FOM_OnUpdate(arg1);
|
||||
end
|
||||
</OnUpdate>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
|
||||
<GameTooltip name="FOMTooltip" frameStrata="TOOLTIP" hidden="true" parent="UIParent" inherits="GameTooltipTemplate">
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
this:SetOwner(UIParent, "ANCHOR_NONE");
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
</GameTooltip>
|
||||
</Ui>
|
||||
@@ -0,0 +1,672 @@
|
||||
local function MTHSmartAmmo_GetSaved()
|
||||
return MTH_SA_GetSavedTable("MTHSmartAmmo")
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_GetModuleStore()
|
||||
if MTH and MTH.GetModuleCharSavedVariables then
|
||||
return MTH:GetModuleCharSavedVariables("smartammo")
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_IsSmartEnabled()
|
||||
local moduleStore = MTHSmartAmmo_GetModuleStore()
|
||||
if type(moduleStore) == "table" and moduleStore.smartEnabled ~= nil then
|
||||
return moduleStore.smartEnabled and true or false
|
||||
end
|
||||
local saved = MTHSmartAmmo_GetSaved()
|
||||
return saved["enabled"]
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_IsReloadEnabled()
|
||||
local moduleStore = MTHSmartAmmo_GetModuleStore()
|
||||
if type(moduleStore) == "table" and moduleStore.reloadEnabled ~= nil then
|
||||
return moduleStore.reloadEnabled and true or false
|
||||
end
|
||||
local saved = MTHSmartAmmo_GetSaved()
|
||||
if saved["reload"] == nil then
|
||||
return true
|
||||
end
|
||||
return saved["reload"] and true or false
|
||||
end
|
||||
|
||||
local MTHSmartAmmo_InitializeHooks
|
||||
MTHSmartAmmo_EnsureHooks = nil
|
||||
|
||||
function MTHSmartAmmo_SetSmartEnabled(enabled, silent)
|
||||
local saved = MTHSmartAmmo_GetSaved()
|
||||
if enabled then
|
||||
saved["enabled"] = 1
|
||||
if MTHSmartAmmo_InitializeHooks then
|
||||
MTHSmartAmmo_InitializeHooks()
|
||||
end
|
||||
if MTHSmartAmmo_EnsureHooks then
|
||||
MTHSmartAmmo_EnsureHooks("SetSmartEnabled")
|
||||
end
|
||||
if not silent and DEFAULT_CHAT_FRAME then
|
||||
MTH_SA_Print("Smart Ammo Enabled.")
|
||||
end
|
||||
else
|
||||
saved["enabled"] = false
|
||||
if not silent and DEFAULT_CHAT_FRAME then
|
||||
MTH_SA_Print("Smart Ammo Disabled.")
|
||||
end
|
||||
end
|
||||
|
||||
local moduleStore = MTHSmartAmmo_GetModuleStore()
|
||||
if type(moduleStore) == "table" then
|
||||
moduleStore.smartEnabled = enabled and true or false
|
||||
end
|
||||
end
|
||||
|
||||
function MTHSmartAmmo_GetSmartEnabled()
|
||||
return MTHSmartAmmo_IsSmartEnabled() and true or false
|
||||
end
|
||||
|
||||
function MTHSmartAmmo_SetReloadEnabled(enabled, silent)
|
||||
local saved = MTHSmartAmmo_GetSaved()
|
||||
if enabled then
|
||||
saved["reload"] = 1
|
||||
else
|
||||
saved["reload"] = false
|
||||
end
|
||||
local moduleStore = MTHSmartAmmo_GetModuleStore()
|
||||
if type(moduleStore) == "table" then
|
||||
moduleStore.reloadEnabled = enabled and true or false
|
||||
end
|
||||
if not silent and DEFAULT_CHAT_FRAME then
|
||||
MTH_SA_Print("Smart Ammo reload fallback " .. (enabled and "Enabled." or "Disabled."))
|
||||
end
|
||||
end
|
||||
|
||||
function MTHSmartAmmo_GetReloadEnabled()
|
||||
return MTHSmartAmmo_IsReloadEnabled() and true or false
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_Log(msg)
|
||||
return
|
||||
end
|
||||
|
||||
local MTHSmartAmmo_CastSpell_Hook
|
||||
local MTHSmartAmmo_UseAction_Hook
|
||||
local MTHSmartAmmo_CastSpellByName_Hook
|
||||
local MTHSmartAmmo_HookEnsureElapsed = 0
|
||||
local MTHSmartAmmo_InCastSpellHook = false
|
||||
local MTHSmartAmmo_InUseActionHook = false
|
||||
local MTHSmartAmmo_InCastSpellByNameHook = false
|
||||
local MTHSmartAmmo_OriginalCastSpell = CastSpell
|
||||
local MTHSmartAmmo_OriginalUseAction = UseAction
|
||||
local MTHSmartAmmo_OriginalCastSpellByName = CastSpellByName
|
||||
|
||||
local function MTHSmartAmmo_AreHooksInstalled()
|
||||
return CastSpell == MTHSmartAmmo_CastSpell_Hook,
|
||||
UseAction == MTHSmartAmmo_UseAction_Hook,
|
||||
CastSpellByName == MTHSmartAmmo_CastSpellByName_Hook
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_ForceHookGlobals()
|
||||
if type(MTHSmartAmmo_CastSpell_Hook) == "function" and CastSpell ~= MTHSmartAmmo_CastSpell_Hook then
|
||||
MTH_SA_CastSpell = CastSpell
|
||||
CastSpell = MTHSmartAmmo_CastSpell_Hook
|
||||
end
|
||||
if type(MTHSmartAmmo_UseAction_Hook) == "function" and UseAction ~= MTHSmartAmmo_UseAction_Hook then
|
||||
MTH_SA_UseAction = UseAction
|
||||
UseAction = MTHSmartAmmo_UseAction_Hook
|
||||
end
|
||||
if type(MTHSmartAmmo_CastSpellByName_Hook) == "function" and CastSpellByName ~= MTHSmartAmmo_CastSpellByName_Hook then
|
||||
MTH_SA_CastSpellByName = CastSpellByName
|
||||
CastSpellByName = MTHSmartAmmo_CastSpellByName_Hook
|
||||
end
|
||||
end
|
||||
|
||||
MTH_SA = {}
|
||||
MTH_SA_List = {}
|
||||
|
||||
MTH_SA_LastCheck = 0
|
||||
|
||||
MTH_SA_Tooltip = CreateFrame("GameTooltip", "MTH_SA_Tooltip", nil, "GameTooltipTemplate")
|
||||
MTH_SA_Tooltip:Hide()
|
||||
|
||||
local _, class = UnitClass("player")
|
||||
|
||||
if class ~= "HUNTER" then
|
||||
return
|
||||
end
|
||||
|
||||
MTH_SA_IsWaitingSwapJunk = nil
|
||||
MTH_SA_IsWaitingSwapGood = nil
|
||||
MTH_SA_AutoShot = nil
|
||||
MTH_SA_LastSpell = nil
|
||||
MTH_SA_UpdateInterval = 0.1
|
||||
MTH_SA_Quantity = 0
|
||||
MTH_SA_LastFallbackAttempt = 0
|
||||
MTH_SA_LastKnownEquippedName = nil
|
||||
MTH_SA_LastFallbackNotice = { key = nil, time = 0 }
|
||||
|
||||
local function MTHSmartAmmo_RefreshAmmoButtonDisplay()
|
||||
local createButtons = getglobal("zButtonAmmo_CreateButtons")
|
||||
local setupSizeAndPosition = getglobal("zButtonAmmo_SetupSizeAndPosition")
|
||||
local ammoButton = getglobal("zButtonAmmo")
|
||||
if type(createButtons) == "function" and ammoButton then
|
||||
createButtons()
|
||||
if type(setupSizeAndPosition) == "function" then
|
||||
setupSizeAndPosition()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_ShowFallbackWarning(previousAmmo, newAmmo)
|
||||
if not previousAmmo or previousAmmo == "" or not newAmmo or newAmmo == "" then
|
||||
return
|
||||
end
|
||||
if previousAmmo == newAmmo then
|
||||
return
|
||||
end
|
||||
|
||||
local now = GetTime() or 0
|
||||
local key = tostring(previousAmmo) .. "=>" .. tostring(newAmmo)
|
||||
if MTH_SA_LastFallbackNotice.key == key and (now - (MTH_SA_LastFallbackNotice.time or 0)) < 1.0 then
|
||||
return
|
||||
end
|
||||
MTH_SA_LastFallbackNotice.key = key
|
||||
MTH_SA_LastFallbackNotice.time = now
|
||||
|
||||
local warning = "YOU RAN OUT OF " .. tostring(previousAmmo) .. ", I EQUIPPED " .. tostring(newAmmo) .. " !"
|
||||
if MTH_SA_Print then
|
||||
MTH_SA_Print(warning)
|
||||
elseif DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
||||
DEFAULT_CHAT_FRAME:AddMessage(warning)
|
||||
end
|
||||
|
||||
if RaidWarningFrame and RaidNotice_AddMessage and ChatTypeInfo and ChatTypeInfo["RAID_WARNING"] then
|
||||
RaidNotice_AddMessage(RaidWarningFrame, warning, ChatTypeInfo["RAID_WARNING"])
|
||||
elseif UIErrorsFrame and UIErrorsFrame.AddMessage then
|
||||
UIErrorsFrame:AddMessage(warning, 1.0, 0.15, 0.15, 1.0)
|
||||
end
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_HandleFallbackResult(previousAmmo)
|
||||
local checkFrame = CreateFrame("Frame")
|
||||
if not checkFrame then
|
||||
return
|
||||
end
|
||||
checkFrame.elapsed = 0
|
||||
checkFrame:SetScript("OnUpdate", function()
|
||||
this.elapsed = (this.elapsed or 0) + (arg1 or 0)
|
||||
if this.elapsed < 0.2 then
|
||||
return
|
||||
end
|
||||
|
||||
local equippedNow = MTH_SA_GetEquippedAmmoName()
|
||||
if equippedNow and equippedNow ~= "" then
|
||||
MTH_SA_LastKnownEquippedName = equippedNow
|
||||
end
|
||||
|
||||
MTHSmartAmmo_RefreshAmmoButtonDisplay()
|
||||
MTHSmartAmmo_ShowFallbackWarning(previousAmmo, equippedNow)
|
||||
|
||||
this:SetScript("OnUpdate", nil)
|
||||
this:Hide()
|
||||
end)
|
||||
end
|
||||
|
||||
local function MTHSmartAmmo_TryFallbackEquip(reason)
|
||||
if not MTH_SA_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
if not MTHSmartAmmo_IsSmartEnabled() then
|
||||
return
|
||||
end
|
||||
if not MTHSmartAmmo_IsReloadEnabled() then
|
||||
return
|
||||
end
|
||||
if MTH_SA_GetEquippedAmmoName() then
|
||||
return
|
||||
end
|
||||
|
||||
local 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 frame = CreateFrame("Frame")
|
||||
frame:RegisterEvent("START_AUTOREPEAT_SPELL")
|
||||
frame:RegisterEvent("STOP_AUTOREPEAT_SPELL")
|
||||
frame:RegisterEvent("SPELLCAST_INTERRUPTED")
|
||||
frame:RegisterEvent("SPELLCAST_FAILED")
|
||||
frame:RegisterEvent("SPELLCAST_STOP")
|
||||
frame:RegisterEvent("SPELLCAST_DELAYED")
|
||||
|
||||
|
||||
frame:SetScript("OnEvent", function()
|
||||
if event == "START_AUTOREPEAT_SPELL" then
|
||||
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 == "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
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
frame:SetScript("OnUpdate", function(self, elapsed)
|
||||
MTHSmartAmmo_HookEnsureElapsed = MTHSmartAmmo_HookEnsureElapsed + (elapsed or 0)
|
||||
if MTHSmartAmmo_HookEnsureElapsed >= 0.5 then
|
||||
MTHSmartAmmo_HookEnsureElapsed = 0
|
||||
if MTH_SA_IsModuleEnabled() then
|
||||
MTHSmartAmmo_InitializeHooks()
|
||||
end
|
||||
end
|
||||
|
||||
MTH_SA_CountEquippedAmmo()
|
||||
if MTH_SA_Quantity == 0 and not MTH_SA_IsWaitingSwapJunk and not MTH_SA_IsWaitingSwapGood then
|
||||
MTHSmartAmmo_TryFallbackEquip("OnUpdate-quantity-zero")
|
||||
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
|
||||
end)
|
||||
|
||||
function MTH_SA_CountEquippedAmmo()
|
||||
local ammo = GetInventoryItemCount("player", 0)
|
||||
local equippedName = MTH_SA_GetEquippedAmmoName()
|
||||
if equippedName and equippedName ~= "" then
|
||||
MTH_SA_LastKnownEquippedName = equippedName
|
||||
end
|
||||
if not ammo then
|
||||
MTH_SA_Quantity=0
|
||||
return
|
||||
elseif ammo ~= MTH_SA_Quantity then
|
||||
MTH_SA_Quantity = ammo
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function MTH_SA_GetEquippedWeaponAmmoType()
|
||||
local itemlink = GetInventoryItemLink("player", 18)
|
||||
if not itemlink then return end
|
||||
local _, _, itemid = string.find(itemlink, "item:(%d+)")
|
||||
if not itemid then return end
|
||||
local _, _, _, _, _, wpntype = GetItemInfo(itemid)
|
||||
if wpntype == MTH_WEAPON_BOWS or wpntype == MTH_WEAPON_CROSSBOWS then
|
||||
return "Arrows"
|
||||
elseif wpntype == MTH_WEAPON_GUNS then
|
||||
return "Bullets"
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_SA_GetEquippedAmmoName()
|
||||
MTH_SA_Tooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
if MTH_SA_Tooltip:SetInventoryItem("player", 0) then
|
||||
return MTH_SA_TooltipTextLeft1:GetText()
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function MTH_SA_GetContainerItemName(bag, slot)
|
||||
if not (bag and slot) then return nil end
|
||||
local item = GetContainerItemLink(bag, slot)
|
||||
local _, _, name = string.find(item or "", "%[(.+)%]")
|
||||
return name
|
||||
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
|
||||
if junk then
|
||||
--DEFAULT_CHAT_FRAME:AddMessage("Time= " .. GetTime()-MTH_SA_AmmoLastSwitch , 0, 1, 1)
|
||||
if GetTime()-MTH_SA_AmmoLastSwitch > 0.5 then
|
||||
--DEFAULT_CHAT_FRAME:AddMessage("JUNK ! GetTime > 0.5 | Equipped=" .. MTH_SA_GetEquippedAmmoName() .. ' | Current=' .. MTH_SA.curname , 0, 1, 1)
|
||||
else
|
||||
--DEFAULT_CHAT_FRAME:AddMessage("JUNK ! GetTime <= 0.5 | Equipped=" .. MTH_SA_GetEquippedAmmoName() .. ' | Current=' .. MTH_SA.curname , 0, 1, 1)
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
--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
|
||||
else
|
||||
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)
|
||||
|
||||
MTH_SA_AmmoLastSwitch = GetTime()
|
||||
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
|
||||
local junkvalue = 999
|
||||
local goodvalue
|
||||
for bag=4, 0, -1 do
|
||||
for slot=GetContainerNumSlots(bag), 1, -1 do
|
||||
item = MTH_SA_GetContainerItemName(bag, slot)
|
||||
|
||||
if item then
|
||||
--DEFAULT_CHAT_FRAME:AddMessage("item = " .. item .. " | value = " .. ammolist[item], 0, 1, 1)
|
||||
value = ammolist[item]
|
||||
if value then
|
||||
|
||||
if not goodvalue and item == curammo then
|
||||
MTH_SA.curvalue = value
|
||||
MTH_SA.curname = item
|
||||
MTH_SA.curbag = bag
|
||||
MTH_SA.curslot = slot
|
||||
goodvalue = value
|
||||
--DEFAULT_CHAT_FRAME:AddMessage("goodvalue A = " .. value , 0, 1, 1)
|
||||
if junkvalue == 1 then
|
||||
return 1
|
||||
end
|
||||
end
|
||||
if value < junkvalue then
|
||||
MTH_SA.junkvalue = item
|
||||
MTH_SA.junkname = item
|
||||
MTH_SA.junkbag = bag
|
||||
MTH_SA.junkslot = slot
|
||||
junkvalue = value
|
||||
--DEFAULT_CHAT_FRAME:AddMessage("junkvalue A = " .. value , 0, 1, 1)
|
||||
if not curammo then
|
||||
MTH_SA.curvalue = value
|
||||
MTH_SA.curname = item
|
||||
MTH_SA.curbag = bag
|
||||
MTH_SA.curslot = slot
|
||||
goodvalue = value
|
||||
--DEFAULT_CHAT_FRAME:AddMessage("goodvalue B = " .. value , 0, 1, 1)
|
||||
end
|
||||
if junkvalue == 1 and goodvalue then
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
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
|
||||
|
||||
function MTH_SA_Check()
|
||||
if not MTH_SA.error and MTH_SA.curname and MTH_SA.junkname then
|
||||
if MTH_SA.curname == MTH_SA_GetContainerItemName(MTH_SA.curbag, MTH_SA.curslot) and
|
||||
MTH_SA.junkname == MTH_SA_GetContainerItemName(MTH_SA.junkbag, MTH_SA.junkslot) then
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
MTHSmartAmmo_CastSpell_Hook = function(spell, tab)
|
||||
if MTHSmartAmmo_InCastSpellHook then
|
||||
if MTHSmartAmmo_OriginalCastSpell then
|
||||
return MTHSmartAmmo_OriginalCastSpell(spell, tab)
|
||||
end
|
||||
return
|
||||
end
|
||||
MTHSmartAmmo_InCastSpellHook = true
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
local result
|
||||
local original = MTH_SA_CastSpell
|
||||
if original == MTHSmartAmmo_CastSpell_Hook or original == nil then
|
||||
original = MTHSmartAmmo_OriginalCastSpell
|
||||
end
|
||||
if original then
|
||||
result = original(spell, tab)
|
||||
end
|
||||
|
||||
MTHSmartAmmo_InCastSpellHook = false
|
||||
return result
|
||||
end
|
||||
|
||||
MTHSmartAmmo_UseAction_Hook = function(slot, checkCursor, onSelf)
|
||||
if MTHSmartAmmo_InUseActionHook then
|
||||
if MTHSmartAmmo_OriginalUseAction then
|
||||
return MTHSmartAmmo_OriginalUseAction(slot, checkCursor, onSelf)
|
||||
end
|
||||
return
|
||||
end
|
||||
MTHSmartAmmo_InUseActionHook = true
|
||||
|
||||
if not GetActionText(slot) and MTHSmartAmmo_IsSmartEnabled() then
|
||||
MTH_SA_Tooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
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
|
||||
end
|
||||
|
||||
local result
|
||||
local original = MTH_SA_UseAction
|
||||
if original == MTHSmartAmmo_UseAction_Hook or original == nil then
|
||||
original = MTHSmartAmmo_OriginalUseAction
|
||||
end
|
||||
if original then
|
||||
result = original(slot, checkCursor, onSelf)
|
||||
end
|
||||
|
||||
MTHSmartAmmo_InUseActionHook = false
|
||||
return result
|
||||
end
|
||||
|
||||
MTHSmartAmmo_CastSpellByName_Hook = function(spell, onSelf)
|
||||
if MTHSmartAmmo_InCastSpellByNameHook then
|
||||
if MTHSmartAmmo_OriginalCastSpellByName then
|
||||
return MTHSmartAmmo_OriginalCastSpellByName(spell, onSelf)
|
||||
end
|
||||
return
|
||||
end
|
||||
MTHSmartAmmo_InCastSpellByNameHook = true
|
||||
|
||||
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
|
||||
|
||||
local result
|
||||
local original = MTH_SA_CastSpellByName
|
||||
if original == MTHSmartAmmo_CastSpellByName_Hook or original == nil then
|
||||
original = MTHSmartAmmo_OriginalCastSpellByName
|
||||
end
|
||||
if original then
|
||||
result = original(spell, onSelf)
|
||||
end
|
||||
|
||||
MTHSmartAmmo_InCastSpellByNameHook = false
|
||||
return result
|
||||
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
|
||||
|
||||
MTHSmartAmmo_EnsureHooks = function(reason)
|
||||
if not MTH_SA_IsModuleEnabled() then
|
||||
return false
|
||||
end
|
||||
if not MTHSmartAmmo_IsSmartEnabled() then
|
||||
return false
|
||||
end
|
||||
|
||||
if MTHSmartAmmo_InitializeHooks then
|
||||
local ok, err = pcall(MTHSmartAmmo_InitializeHooks)
|
||||
if not ok then end
|
||||
end
|
||||
|
||||
local castHook, actionHook, byNameHook = MTHSmartAmmo_AreHooksInstalled()
|
||||
if castHook and actionHook and byNameHook then
|
||||
return true
|
||||
end
|
||||
|
||||
MTHSmartAmmo_ForceHookGlobals()
|
||||
castHook, actionHook, byNameHook = MTHSmartAmmo_AreHooksInstalled()
|
||||
return castHook and actionHook and byNameHook
|
||||
end
|
||||
|
||||
-- Initialize hooks on module load
|
||||
if not MTH_SA_MANAGED_HOOKS then
|
||||
MTHSmartAmmo_InitializeHooks()
|
||||
end
|
||||
|
||||
SLASH_MTHSmartAmmo1 = "/smartammo"
|
||||
SlashCmdList["MTHSmartAmmo"] = function(msg)
|
||||
if not MTH_SA_IsModuleEnabled() then
|
||||
MTH_SA_Print("Smart Ammo is disabled while module 'smartammo' is disabled.")
|
||||
return
|
||||
end
|
||||
|
||||
local saved = MTHSmartAmmo_GetSaved()
|
||||
|
||||
if msg == "status" then
|
||||
local castHook, actionHook, byNameHook = MTHSmartAmmo_AreHooksInstalled()
|
||||
MTH_SA_Print("Smart Ammo status: smart=" .. tostring(saved["enabled"] and true or false) .. ", module=" .. tostring(MTH_SA_IsModuleEnabled()) .. ", hooks=" .. tostring(castHook) .. "/" .. tostring(actionHook) .. "/" .. tostring(byNameHook))
|
||||
return
|
||||
end
|
||||
|
||||
if saved["enabled"] then
|
||||
MTHSmartAmmo_SetSmartEnabled(nil)
|
||||
else
|
||||
MTHSmartAmmo_SetSmartEnabled(1)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
<!--
|
||||
SmartAmmo Module Loader
|
||||
Owns Smart Ammo runtime and hooks as a standalone MetaHunt module
|
||||
-->
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Include file="module.lua"/>
|
||||
<Include file="engine.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,171 @@
|
||||
------------------------------------------------------
|
||||
-- MetaHunt: SmartAmmo Module
|
||||
------------------------------------------------------
|
||||
|
||||
MTH_SA_MANAGED_HOOKS = true
|
||||
|
||||
local MTH_SmartAmmo = {
|
||||
name = "smartammo",
|
||||
enabled = true,
|
||||
version = "1.0.3",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"PLAYER_ENTERING_WORLD",
|
||||
},
|
||||
}
|
||||
|
||||
local MTH_SA_BOUNDARY_KEY = "smartammo.core"
|
||||
|
||||
function MTH_SA_GetSavedTable(tableName)
|
||||
if not MTH or not MTH.GetModuleCharSavedVariables then
|
||||
if type(_G[tableName]) ~= "table" then
|
||||
_G[tableName] = {}
|
||||
end
|
||||
return _G[tableName]
|
||||
end
|
||||
|
||||
local moduleStore = MTH:GetModuleCharSavedVariables("smartammo")
|
||||
if type(moduleStore) ~= "table" then
|
||||
moduleStore = {}
|
||||
end
|
||||
|
||||
if not moduleStore.legacy then
|
||||
moduleStore.legacy = {}
|
||||
end
|
||||
if type(moduleStore.legacy[tableName]) ~= "table" then
|
||||
moduleStore.legacy[tableName] = {}
|
||||
end
|
||||
|
||||
if type(_G[tableName]) == "table" then
|
||||
local legacyTable = moduleStore.legacy[tableName]
|
||||
if not next(legacyTable) then
|
||||
for key, value in pairs(_G[tableName]) do
|
||||
legacyTable[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
_G[tableName] = moduleStore.legacy[tableName]
|
||||
|
||||
return moduleStore.legacy[tableName]
|
||||
end
|
||||
|
||||
function MTH_SA_IsModuleEnabled()
|
||||
if MTH and MTH.IsModuleEnabled then
|
||||
return MTH:IsModuleEnabled("smartammo", true) and true or false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function MTH_SA_Print(msg, severity)
|
||||
if MTH and MTH.Print then
|
||||
MTH:Print(tostring(msg), severity)
|
||||
return
|
||||
end
|
||||
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
||||
DEFAULT_CHAT_FRAME:AddMessage(tostring(msg))
|
||||
end
|
||||
end
|
||||
|
||||
local function MTH_SA_ApplySavedState()
|
||||
if type(MTHSmartAmmo_SetSmartEnabled) ~= "function" then
|
||||
return
|
||||
end
|
||||
|
||||
local saved = MTH_SA_GetSavedTable("MTHSmartAmmo")
|
||||
local moduleStore = MTH and MTH.GetModuleCharSavedVariables and MTH:GetModuleCharSavedVariables("smartammo") or nil
|
||||
if type(moduleStore) == "table" then
|
||||
if moduleStore.smartEnabled ~= nil then
|
||||
saved["enabled"] = moduleStore.smartEnabled and 1 or false
|
||||
end
|
||||
if moduleStore.reloadEnabled ~= nil then
|
||||
saved["reload"] = moduleStore.reloadEnabled and 1 or false
|
||||
end
|
||||
end
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = 1
|
||||
if type(moduleStore) == "table" then
|
||||
moduleStore.smartEnabled = true
|
||||
end
|
||||
end
|
||||
if saved["reload"] == nil and type(moduleStore) == "table" then
|
||||
moduleStore.reloadEnabled = saved["reload"] ~= 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_EnsureHooks) == "function" then
|
||||
MTHSmartAmmo_EnsureHooks("module-apply")
|
||||
end
|
||||
|
||||
if not (MTH and MTH.CaptureHookBoundary) then
|
||||
return
|
||||
end
|
||||
|
||||
local castHook = getglobal("MTHSmartAmmo_CastSpell_Hook")
|
||||
local useActionHook = getglobal("MTHSmartAmmo_UseAction_Hook")
|
||||
local castByNameHook = getglobal("MTHSmartAmmo_CastSpellByName_Hook")
|
||||
if type(castHook) ~= "function" or type(useActionHook) ~= "function" or type(castByNameHook) ~= "function" then
|
||||
return
|
||||
end
|
||||
if CastSpell ~= castHook or UseAction ~= useActionHook or CastSpellByName ~= castByNameHook then
|
||||
return
|
||||
end
|
||||
|
||||
MTH:CaptureHookBoundary(MTH_SA_BOUNDARY_KEY, {
|
||||
{ globalName = "CastSpell", originalName = "MTH_SA_CastSpell" },
|
||||
{ globalName = "UseAction", originalName = "MTH_SA_UseAction" },
|
||||
{ globalName = "CastSpellByName", originalName = "MTH_SA_CastSpellByName" },
|
||||
})
|
||||
end
|
||||
|
||||
local function MTH_SA_RestoreHooks()
|
||||
if MTH and MTH.RestoreHookBoundary and MTH:RestoreHookBoundary(MTH_SA_BOUNDARY_KEY) then
|
||||
return
|
||||
end
|
||||
|
||||
local castHook = getglobal("MTHSmartAmmo_CastSpell_Hook")
|
||||
local useActionHook = getglobal("MTHSmartAmmo_UseAction_Hook")
|
||||
local castByNameHook = getglobal("MTHSmartAmmo_CastSpellByName_Hook")
|
||||
|
||||
if CastSpell == castHook and type(MTH_SA_CastSpell) == "function" then
|
||||
CastSpell = MTH_SA_CastSpell
|
||||
end
|
||||
if UseAction == useActionHook and type(MTH_SA_UseAction) == "function" then
|
||||
UseAction = MTH_SA_UseAction
|
||||
end
|
||||
if CastSpellByName == castByNameHook and type(MTH_SA_CastSpellByName) == "function" then
|
||||
CastSpellByName = MTH_SA_CastSpellByName
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_SmartAmmo:init()
|
||||
MTH_SA_GetSavedTable("MTHSmartAmmo")
|
||||
if self.enabled then
|
||||
MTH_SA_ApplySavedState()
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_SmartAmmo:setEnabled(enabled)
|
||||
if enabled then
|
||||
MTH_SA_ApplySavedState()
|
||||
else
|
||||
MTH_SA_RestoreHooks()
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_SmartAmmo:onEvent(evt)
|
||||
if not self.enabled then
|
||||
return
|
||||
end
|
||||
if evt == "VARIABLES_LOADED" or evt == "PLAYER_ENTERING_WORLD" then
|
||||
MTH_SA_ApplySavedState()
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_SmartAmmo:cleanup()
|
||||
self:setEnabled(false)
|
||||
end
|
||||
|
||||
MTH:RegisterModule("smartammo", MTH_SmartAmmo)
|
||||
@@ -0,0 +1,7 @@
|
||||
<!--
|
||||
MetaHunt Tooltips Module Loader
|
||||
Standalone tooltip augmentation using MetaHunt data only.
|
||||
-->
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Include file="module.lua"/>
|
||||
</Ui>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
||||
Version 2.0 ----> Metahunt integration :-)
|
||||
|
||||
|
||||
Version 1.12.14
|
||||
|
||||
September 15 - 1.12.14
|
||||
-Fixed some translation errors
|
||||
|
||||
September 12 - 1.12.13
|
||||
-ZMarkTarget() should no longer lockup some clients
|
||||
-Fixed some translations
|
||||
|
||||
September 9 - 1.12.12
|
||||
-Should've fixed the AntiDaze lockup, once and for all!
|
||||
|
||||
September 8 - 1.12.11
|
||||
-/zammo has been changed back to a toggle ability
|
||||
-Added Tame Beast, Beast Training, and Beast Lore to the pet buttons
|
||||
-Added the function /script ZMarkTarget()
|
||||
-Altered saved variables for easier patch transitions hopefully (current spell order will be reset)
|
||||
|
||||
August 26 - 1.12.10
|
||||
-Using the ZTrap Key Binding will now put your pet in passive mode as well
|
||||
-More French translations
|
||||
-Split up the localization files for ease of use
|
||||
|
||||
August 25 - 1.12.9
|
||||
-ZTrap buttons will now fade when you enter combat
|
||||
-Added /zhunter to remind you of all of the other slash commands
|
||||
-You can drag food on the ZPet button to feed your pet
|
||||
|
||||
August 25 - 1.12.8
|
||||
-Fixed an error if you only had 1 of the button spells
|
||||
|
||||
August 24 - 1.12.7
|
||||
-Woops... fixed AntiDaze even further
|
||||
|
||||
August 24 - 1.12.6
|
||||
-Fixed the lock up issue with the AntiDaze feature
|
||||
|
||||
August 23 - 1.12.5
|
||||
-Might've fixed some lockup issues
|
||||
-Made the buttons overlap the user interface
|
||||
-More translations
|
||||
|
||||
August 23 - 1.12.4
|
||||
-Added some more translations
|
||||
-Possibly fixed some button load errors
|
||||
|
||||
August 22 - 1.12.3
|
||||
-Updated for Patch 1.12
|
||||
-Should've removed the error for ZPet (Although the button probably still won't work because I still don't have the translations. Let me know if theres an error on the English client)
|
||||
-Added some German translations
|
||||
|
||||
August 21 - 1.12.2
|
||||
-Fixed the aspect bar
|
||||
|
||||
August 21 - 1.12.1
|
||||
-Fixed a problem with the number of buttons displayed
|
||||
|
||||
August 21 - 1.12.0
|
||||
-Altered (and hopefully fixed) all of the spell buttons
|
||||
-Fixed Smart Ammo to work with all ammo
|
||||
-Added a Pet Spell action bar
|
||||
-Added an Anti-Daze feature
|
||||
-Added a feature to automatically change the frenzy timer based on the boss
|
||||
-Added a /script IsPetDead() command
|
||||
@@ -0,0 +1,98 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<Binding name="ZAspect Main" header="ZAspectHeader">
|
||||
zButtonAspect_KeyBinding()
|
||||
</Binding>
|
||||
<Binding name="ZAspect 1" header="ZAspectHeader">
|
||||
zButtonAspect_KeyBinding(1)
|
||||
</Binding>
|
||||
<Binding name="ZAspect 2" header="ZAspectHeader">
|
||||
zButtonAspect_KeyBinding(2)
|
||||
</Binding>
|
||||
<Binding name="ZAspect 3" header="ZAspectHeader">
|
||||
zButtonAspect_KeyBinding(3)
|
||||
</Binding>
|
||||
<Binding name="ZAspect 4" header="ZAspectHeader">
|
||||
zButtonAspect_KeyBinding(4)
|
||||
</Binding>
|
||||
<Binding name="ZAspect 5" header="ZAspectHeader">
|
||||
zButtonAspect_KeyBinding(5)
|
||||
</Binding>
|
||||
<Binding name="ZAspect 6" header="ZAspectHeader">
|
||||
zButtonAspect_KeyBinding(6)
|
||||
</Binding>
|
||||
<Binding name="ZTrack Main" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding()
|
||||
</Binding>
|
||||
<Binding name="ZTrack 1" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(1)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 2" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(2)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 3" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(3)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 4" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(4)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 5" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(5)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 6" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(6)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 7" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(7)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 8" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(8)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 9" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(9)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 10" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(10)
|
||||
</Binding>
|
||||
<Binding name="ZTrack 11" header="ZTrackHeader">
|
||||
zButtonTrack_KeyBinding(11)
|
||||
</Binding>
|
||||
<Binding name="ZTrap Main" header="ZTrapHeader">
|
||||
zButtonTrap_KeyBinding()
|
||||
</Binding>
|
||||
<Binding name="ZTrap 1" header="ZTrapHeader">
|
||||
zButtonTrap_KeyBinding(1)
|
||||
</Binding>
|
||||
<Binding name="ZTrap 2" header="ZTrapHeader">
|
||||
zButtonTrap_KeyBinding(2)
|
||||
</Binding>
|
||||
<Binding name="ZTrap 3" header="ZTrapHeader">
|
||||
zButtonTrap_KeyBinding(3)
|
||||
</Binding>
|
||||
<Binding name="ZTrap 4" header="ZTrapHeader">
|
||||
zButtonTrap_KeyBinding(4)
|
||||
</Binding>
|
||||
<Binding name="ZTrap 5" header="ZTrapHeader">
|
||||
zButtonTrap_KeyBinding(5)
|
||||
</Binding>
|
||||
<Binding name="ZPet Main" header="ZPetHeader">
|
||||
zButtonPet_KeyBinding()
|
||||
</Binding>
|
||||
<Binding name="ZPet 1" header="ZPetHeader">
|
||||
zButtonPet_KeyBinding(1)
|
||||
</Binding>
|
||||
<Binding name="ZPet 2" header="ZPetHeader">
|
||||
zButtonPet_KeyBinding(2)
|
||||
</Binding>
|
||||
<Binding name="ZPet 3" header="ZPetHeader">
|
||||
zButtonPet_KeyBinding(3)
|
||||
</Binding>
|
||||
<Binding name="ZPet 4" header="ZPetHeader">
|
||||
zButtonPet_KeyBinding(4)
|
||||
</Binding>
|
||||
<Binding name="ZPet 5" header="ZPetHeader">
|
||||
zButtonPet_KeyBinding(5)
|
||||
</Binding>
|
||||
<Binding name="ZPet 6" header="ZPetHeader">
|
||||
zButtonPet_KeyBinding(6)
|
||||
</Binding>
|
||||
</Ui>
|
||||
@@ -0,0 +1,237 @@
|
||||
-- Deferred initialization for ZHunterMod
|
||||
-- This file runs at the END after all frames are created and all Lua is parsed
|
||||
|
||||
-- Wrap ZSpellButton_CreateChildren to automatically initialize child buttons
|
||||
local original_CreateChildren = ZSpellButton_CreateChildren
|
||||
function ZSpellButton_CreateChildren(parent, name, count)
|
||||
-- Call original function to create children
|
||||
original_CreateChildren(parent, name, count)
|
||||
|
||||
-- Now initialize each child button's properties
|
||||
if parent and name and count then
|
||||
for i = 1, count do
|
||||
local button = getglobal(name .. i)
|
||||
if button then
|
||||
local oldThis = this
|
||||
local oldEvent = event
|
||||
this = button
|
||||
ZSpellButton_OnLoad()
|
||||
this = oldThis
|
||||
event = oldEvent
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function ZHunterMod_RunButtonInit(frame, onEventFunc)
|
||||
if not (frame and onEventFunc) then
|
||||
return
|
||||
end
|
||||
local oldThis = this
|
||||
local oldEvent = event
|
||||
this = frame
|
||||
ZSpellButtonParent_OnLoad()
|
||||
event = "VARIABLES_LOADED"
|
||||
onEventFunc()
|
||||
this = oldThis
|
||||
event = oldEvent
|
||||
end
|
||||
|
||||
local function ZHunterMod_LogDeferred(msg)
|
||||
local deferredDebug = _G and _G["MTH_ZH_DEFERRED_DEBUG"]
|
||||
if not (MTH and MTH.debug and deferredDebug) then
|
||||
return
|
||||
end
|
||||
MTH_ZH_Print("[ZHUNTER] " .. tostring(msg), "error")
|
||||
end
|
||||
|
||||
local function ZHunterMod_EnsureButtonFrame(buttonName)
|
||||
local frame = getglobal(buttonName)
|
||||
if frame then
|
||||
return frame
|
||||
end
|
||||
if type(CreateFrame) ~= "function" then
|
||||
return nil
|
||||
end
|
||||
local created = CreateFrame("CheckButton", buttonName, UIParent, "ZSpellButtonTemplate")
|
||||
if created then
|
||||
created:ClearAllPoints()
|
||||
if buttonName == "zButtonAspect" then
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", -60, 0)
|
||||
elseif buttonName == "zButtonAmmo" then
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
||||
elseif buttonName == "zButtonTrack" then
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
||||
elseif buttonName == "zButtonTrap" then
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", 60, 0)
|
||||
elseif buttonName == "zButtonPet" then
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", 0, 60)
|
||||
elseif buttonName == "zButtonMounts" then
|
||||
created:SetPoint("TOP", UIParent, "TOP", 0, -410)
|
||||
elseif buttonName == "zButtonCompanions" then
|
||||
created:SetPoint("TOP", UIParent, "TOP", 0, -464)
|
||||
elseif buttonName == "zButtonToys" then
|
||||
created:SetPoint("TOP", UIParent, "TOP", 0, -518)
|
||||
else
|
||||
created:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
||||
end
|
||||
ZHunterMod_LogDeferred("DeferredInit: created missing frame " .. tostring(buttonName))
|
||||
end
|
||||
return created
|
||||
end
|
||||
|
||||
function ZHunterMod_DeferredInit()
|
||||
-- Check if frames were created
|
||||
local pet = ZHunterMod_EnsureButtonFrame("zButtonPet")
|
||||
local aspect = ZHunterMod_EnsureButtonFrame("zButtonAspect")
|
||||
local track = ZHunterMod_EnsureButtonFrame("zButtonTrack")
|
||||
local trap = ZHunterMod_EnsureButtonFrame("zButtonTrap")
|
||||
local ammo = ZHunterMod_EnsureButtonFrame("zButtonAmmo")
|
||||
local mounts = ZHunterMod_EnsureButtonFrame("zButtonMounts")
|
||||
local companions = ZHunterMod_EnsureButtonFrame("zButtonCompanions")
|
||||
local toys = ZHunterMod_EnsureButtonFrame("zButtonToys")
|
||||
|
||||
ZHunterMod_LogDeferred("DeferredInit: Pet=" .. tostring(pet ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Aspect=" .. tostring(aspect ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Track=" .. tostring(track ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Trap=" .. tostring(trap ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Ammo=" .. tostring(ammo ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Mounts=" .. tostring(mounts ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Companions=" .. tostring(companions ~= nil))
|
||||
ZHunterMod_LogDeferred("DeferredInit: Toys=" .. tostring(toys ~= nil))
|
||||
|
||||
-- Continue with all frames that exist; do not hard-abort when one optional frame is missing.
|
||||
local missing = {}
|
||||
if not pet then table.insert(missing, "Pet") end
|
||||
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 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
|
||||
if not toys then table.insert(missing, "Toys") end
|
||||
|
||||
if table.getn(missing) > 0 then
|
||||
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
|
||||
MTH_ZH_Print("zhunter buttons not created - check for addon conflicts!", "error")
|
||||
return
|
||||
end
|
||||
|
||||
-- Initialize each button by calling template OnLoad then button-specific OnEvent
|
||||
-- We set up global 'this' and 'event' for the OnEvent functions (Lua 5.0 style)
|
||||
|
||||
local initialized = 0
|
||||
local function ZHunterMod_SafeRunButtonInit(frame, onEventFunc, buttonTag)
|
||||
if not (frame and onEventFunc) then
|
||||
return false
|
||||
end
|
||||
local ok, err = pcall(ZHunterMod_RunButtonInit, frame, onEventFunc)
|
||||
if not ok then
|
||||
MTH_ZH_Print("[ZHUNTER] DeferredInit failed for " .. tostring(buttonTag) .. ": " .. tostring(err), "error")
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
if pet and zButtonPet_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(pet, zButtonPet_OnEvent, "zButtonPet") then
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if aspect and zButtonAspect_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(aspect, zButtonAspect_OnEvent, "zButtonAspect") then
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if track and zButtonTrack_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(track, zButtonTrack_OnEvent, "zButtonTrack") then
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if trap and zButtonTrap_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(trap, zButtonTrap_OnEvent, "zButtonTrap") then
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if ammo and zButtonAmmo_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(ammo, zButtonAmmo_OnEvent, "zButtonAmmo") then
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if mounts and zButtonMounts_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(mounts, zButtonMounts_OnEvent, "zButtonMounts") then
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if companions and zButtonCompanions_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(companions, zButtonCompanions_OnEvent, "zButtonCompanions") then
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if toys and zButtonToys_OnEvent then
|
||||
if ZHunterMod_SafeRunButtonInit(toys, zButtonToys_OnEvent, "zButtonToys") then
|
||||
initialized = initialized + 1
|
||||
end
|
||||
end
|
||||
|
||||
if initialized <= 0 then
|
||||
MTH_ZH_Print("zhunter buttons not created - check for addon conflicts!", "error")
|
||||
return
|
||||
end
|
||||
|
||||
if type(MTH_ZH_OnDeferredInitComplete) == "function" then
|
||||
local ok, err = pcall(MTH_ZH_OnDeferredInitComplete)
|
||||
if not ok and MTH_DebugFrame and MTH_DebugFrame.AddError then
|
||||
MTH_ZH_Print("[ZHUNTER] DeferredInit callback error: " .. tostring(err), "error")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Smart initialization that handles both initial load and reload
|
||||
local function TryInitialize()
|
||||
-- Check if spell data is available (hunters get aspect of monkey at level 4)
|
||||
-- If player is low level without spells, we still want to initialize
|
||||
local _, _, _, numSpells = GetNumSpellTabs()
|
||||
|
||||
-- Only initialize if we have some basic game data ready
|
||||
if numSpells and numSpells > 0 then
|
||||
ZHunterMod_DeferredInit()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Try immediate initialization (works for /reload)
|
||||
if not TryInitialize() then
|
||||
-- If immediate init failed, we're on initial game load
|
||||
-- Set up event-based initialization
|
||||
local initFrame = CreateFrame("Frame")
|
||||
initFrame:RegisterEvent("PLAYER_LOGIN")
|
||||
initFrame:SetScript("OnEvent", function()
|
||||
if event == "PLAYER_LOGIN" then
|
||||
-- Delay slightly to ensure spell book is ready
|
||||
local elapsed = 0
|
||||
initFrame:SetScript("OnUpdate", function()
|
||||
elapsed = elapsed + arg1
|
||||
if elapsed >= 0.3 then
|
||||
initFrame:SetScript("OnUpdate", nil)
|
||||
ZHunterMod_DeferredInit()
|
||||
-- Master options will be initialized on-demand
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
else
|
||||
-- Immediate init succeeded, do not initialize master options here
|
||||
-- It will be created on-demand when first opened
|
||||
end
|
||||
@@ -0,0 +1,325 @@
|
||||
if not ZHunterMod_Saved then
|
||||
ZHunterMod_Saved = {}
|
||||
end
|
||||
|
||||
BINDING_HEADER_ZAspectHeader = "ZAspect Buttons"
|
||||
BINDING_HEADER_ZTrackHeader = "ZTrack Buttons"
|
||||
BINDING_HEADER_ZTrapHeader = "ZTrap Buttons"
|
||||
BINDING_HEADER_ZPetHeader = "ZPet Buttons"
|
||||
|
||||
function ZHunterMod_AlignButtons()
|
||||
zButtonTrack:ClearAllPoints()
|
||||
zButtonTrack:SetPoint("TOP", zButtonAspect, "BOTTOM", 0, -15)
|
||||
zButtonTrap:ClearAllPoints()
|
||||
zButtonTrap:SetPoint("TOP", zButtonTrack, "BOTTOM", 0, -15)
|
||||
if AutoStripDisplay then
|
||||
AutoStripDisplay:ClearAllPoints()
|
||||
AutoStripDisplay:SetPoint("TOP", zButtonTrap, "BOTTOM", 0, -10)
|
||||
end
|
||||
end
|
||||
|
||||
-- ////////////////////////////////////////////////////////////////
|
||||
-- ENGLISH
|
||||
-- \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
ZHUNTER_MAGMADAR = "Magmadar"
|
||||
ZHUNTER_FLAMEGORE = "Flamegore"
|
||||
ZHUNTER_CHROMMAGUS = "Chrommagus"
|
||||
ZHUNTER_HUHURAN = "Princess Huhuran"
|
||||
ZHUNTER_GLUTH = "Gluth"
|
||||
|
||||
ZHUNTER_YOU = "You"
|
||||
ZHUNTER_HUNTER = "Hunter"
|
||||
ZHUNTER_BOWS = "Bows"
|
||||
ZHUNTER_CROSSBOWS = "Crossbows"
|
||||
ZHUNTER_GUNS = "Guns"
|
||||
ZHUNTER_AFFLICTED_DAZED = "(.+) (.+) afflicted by Dazed"
|
||||
|
||||
ZHUNTER_BULLETS_LIGHT = "Light Shot"
|
||||
ZHUNTER_BULLETS_CRAFTLIGHT = "Crafted Light Shot"
|
||||
ZHUNTER_BULLETS_FLASH = "Flash Pellet"
|
||||
ZHUNTER_BULLETS_HEAVY = "Heavy Shot"
|
||||
ZHUNTER_BULLETS_PEBBLE = "Smooth Pebble"
|
||||
ZHUNTER_BULLETS_CRAFTHEAVY = "Crafted Heavy Shot"
|
||||
ZHUNTER_BULLETS_SOLID = "Solid Shot"
|
||||
ZHUNTER_BULLETS_CRAFTSOLID = "Crafted Solid Shot"
|
||||
ZHUNTER_BULLETS_EXPLODING = "Exploding Shot"
|
||||
ZHUNTER_BULLETS_MITHRILSLUG = "Hi-impact Mithril Slugs"
|
||||
ZHUNTER_BULLETS_ACCURATE = "Accurate Slugs"
|
||||
ZHUNTER_BULLETS_GYROSHOT = "Mithril Gyro-Shot"
|
||||
ZHUNTER_BULLETS_ICETHREADED = "Ice Threaded Bullet"
|
||||
ZHUNTER_BULLETS_THORIUM = "Thorium Shells"
|
||||
ZHUNTER_BULLETS_ROCKSHARD = "Rockshard Pellets"
|
||||
ZHUNTER_BULLETS_CANNONBALL = "Miniature Cannon Balls"
|
||||
|
||||
ZHUNTER_ARROWS_ROUGH = "Rough Arrow"
|
||||
ZHUNTER_ARROWS_SHARP = "Sharp Arrow"
|
||||
ZHUNTER_ARROWS_RAZOR = "Razor Arrow"
|
||||
ZHUNTER_ARROWS_FEATHER = "Feathered Arrow"
|
||||
ZHUNTER_ARROWS_PRECISION = "Precision Arrow"
|
||||
ZHUNTER_ARROWS_JAGGED = "Jagged Arrow"
|
||||
ZHUNTER_ARROWS_ICETHREADED = "Ice Threaded Arrow"
|
||||
ZHUNTER_ARROWS_THORIUM = "Thorium Headed Arrow"
|
||||
ZHUNTER_ARROWS_DOOMSHOT = "Doomshot"
|
||||
|
||||
ZHUNTER_RAPIDFIRE = "Rapid Fire"
|
||||
ZHUNTER_IMPROVEDHAWK = "Quick Shots"
|
||||
ZHUNTER_BERSERKING = "Berserking"
|
||||
ZHUNTER_AUTO = "Auto Shot"
|
||||
ZHUNTER_AIMED = "Aimed Shot"
|
||||
ZHUNTER_SERPENT = "Serpent Sting"
|
||||
ZHUNTER_SCORPID = "Scorpid Sting"
|
||||
ZHUNTER_VIPER = "Viper Sting"
|
||||
ZHUNTER_ARCANE = "Arcane Shot"
|
||||
ZHUNTER_CONCUSSIVE = "Concussive Shot"
|
||||
ZHUNTER_DISTRACTING = "Distracting Shot"
|
||||
ZHUNTER_VOLLEY = "Volley"
|
||||
|
||||
ZHUNTER_TRACK_HUMANOIDS = "Track Humanoids"
|
||||
ZHUNTER_TRACK_HIDDEN = "Track Hidden"
|
||||
ZHUNTER_TRACK_BEASTS = "Track Beasts"
|
||||
ZHUNTER_TRACK_ELEMENTALS = "Track Elementals"
|
||||
ZHUNTER_TRACK_DEMONS = "Track Demons"
|
||||
ZHUNTER_TRACK_DRAGONKIN = "Track Dragonkin"
|
||||
ZHUNTER_TRACK_UNDEAD = "Track Undead"
|
||||
ZHUNTER_TRACK_GIANTS = "Track Giants"
|
||||
ZHUNTER_TRACK_MINERALS = "Find Minerals"
|
||||
ZHUNTER_TRACK_HERBS = "Find Herbs"
|
||||
ZHUNTER_TRACK_TREASURE = "Find Treasure"
|
||||
|
||||
ZHUNTER_TRAP_FREEZING = "Freezing Trap"
|
||||
ZHUNTER_TRAP_FROST = "Frost Trap"
|
||||
ZHUNTER_TRAP_IMMOLATION = "Immolation Trap"
|
||||
ZHUNTER_TRAP_EXPLOSIVE = "Explosive Trap"
|
||||
|
||||
ZHUNTER_ASPECT_HAWK = "Aspect of the Hawk"
|
||||
ZHUNTER_ASPECT_MONKEY = "Aspect of the Monkey"
|
||||
ZHUNTER_ASPECT_CHEETAH = "Aspect of the Cheetah"
|
||||
ZHUNTER_ASPECT_BEAST = "Aspect of the Beast"
|
||||
ZHUNTER_ASPECT_PACK = "Aspect of the Pack"
|
||||
ZHUNTER_ASPECT_WILD = "Aspect of the Wild"
|
||||
|
||||
ZHUNTER_PET_EYES = "Eyes of the Beast"
|
||||
ZHUNTER_PET_DISMISS = "Dismiss Pet"
|
||||
ZHUNTER_PET_MEND = "Mend Pet"
|
||||
ZHUNTER_PET_FEED = "Feed Pet"
|
||||
ZHUNTER_PET_CALL = "Call Pet"
|
||||
ZHUNTER_PET_REVIVE = "Revive Pet"
|
||||
ZHUNTER_PET_LORE = "Beast Lore"
|
||||
ZHUNTER_PET_TRAINING = "Beast Training"
|
||||
ZHUNTER_PET_TAMING = "Tame Beast"
|
||||
|
||||
--------------------------------------------------------------------
|
||||
-- Meta 09 Feb 2026
|
||||
-- Twow spells addition
|
||||
ZHUNTER_PET_POSITION = "Pet Command: Take Position"
|
||||
|
||||
ZHUNTER_ASPECT_WOLF = "Aspect of the Wolf"
|
||||
ZHUNTER_ASPECT_VIPER = "Aspect of the Viper"
|
||||
|
||||
ZHUNTER_STEADY = "Steady Shot"
|
||||
ZHUNTER_BAITED = "Baited Shot"
|
||||
ZHUNTER_INTIMIDATION = "Intimidation"
|
||||
ZHUNTER_KILLCOMMAND = "Kill Command"
|
||||
ZHUNTER_CARVE = "Carve"
|
||||
ZHUNTER_LACERATE = "Lacerate"
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
-- ////////////////////////////////////////////////////////////////
|
||||
-- FRENCH
|
||||
-- \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
-- � = \195\136 � = \195\168
|
||||
-- � = \195\137 � = \195\169
|
||||
-- � = \195\138 � = \195\170
|
||||
-- � = \195\143 � = \195\175
|
||||
-- � = \195\135 � = \195\167
|
||||
|
||||
if ( GetLocale() == "frFR" ) then
|
||||
|
||||
--ZHUNTER_MAGMADAR = "Magmadar"
|
||||
--ZHUNTER_FLAMEGORE = "Flamegore"
|
||||
--ZHUNTER_CHROMMAGUS = "Chrommagus"
|
||||
--ZHUNTER_HUHURAN = "Princess Huhuran"
|
||||
--ZHUNTER_GLUTH = "Gluth"
|
||||
|
||||
ZHUNTER_YOU = "Vous"
|
||||
ZHUNTER_HUNTER = "Chasseur"
|
||||
--ZHUNTER_BOWS = "Bows"
|
||||
ZHUNTER_CROSSBOWS = "Arbal\195\168tes"
|
||||
ZHUNTER_GUNS = "Armes\195\160feus"
|
||||
--ZHUNTER_AFFLICTED_DAZED = "(.+) (.+) afflicted by Dazed"
|
||||
|
||||
ZHUNTER_BULLETS_LIGHT = "Balle l\195\169g\195\168re"
|
||||
ZHUNTER_BULLETS_CRAFTLIGHT = "Balle l\195\169g\195\168re fabriqu\195\169e"
|
||||
ZHUNTER_BULLETS_FLASH = "Bille d'\195\169clair"
|
||||
ZHUNTER_BULLETS_HEAVY = "Balle lourde"
|
||||
ZHUNTER_BULLETS_PEBBLE = "Caillou lisse"
|
||||
ZHUNTER_BULLETS_CRAFTHEAVY = "Balle lourde fabriqu\195\169e"
|
||||
ZHUNTER_BULLETS_SOLID = "Balle dure"
|
||||
ZHUNTER_BULLETS_CRAFTSOLID = "Balle dure fabriqu\195\169e"
|
||||
ZHUNTER_BULLETS_EXPLODING = "Balle explosive"
|
||||
ZHUNTER_BULLETS_MITHRILSLUG = "Balle per\195\167antes en mithril"
|
||||
ZHUNTER_BULLETS_ACCURATE = "Balles de pr\195\169cision"
|
||||
ZHUNTER_BULLETS_GYROSHOT = "Balle gyroscopique en mithril"
|
||||
ZHUNTER_BULLETS_ICETHREADED = "Balle de glace"
|
||||
ZHUNTER_BULLETS_THORIUM = "Obus en thorium"
|
||||
ZHUNTER_BULLETS_ROCKSHARD = "Balle de roche"
|
||||
ZHUNTER_BULLETS_CANNONBALL = "Boulet de canon miniature"
|
||||
|
||||
ZHUNTER_ARROWS_ROUGH = "Fl\195\168che grossi\195\168re"
|
||||
ZHUNTER_ARROWS_SHARP = "Fl\195\168che pointue"
|
||||
ZHUNTER_ARROWS_RAZOR = "Fl\195\168che rasoir"
|
||||
ZHUNTER_ARROWS_FEATHER = "Fl\195\168che \195\160 plumes"
|
||||
ZHUNTER_ARROWS_PRECISION = "Fl\195\168che de pr\195\169cision"
|
||||
ZHUNTER_ARROWS_JAGGED = "Fl\195\168che barbel\195\169e"
|
||||
ZHUNTER_ARROWS_ICETHREADED = "Fl\195\168che de glace"
|
||||
ZHUNTER_ARROWS_THORIUM = "Fl\195\168ches \195\160 pointe de thorium"
|
||||
ZHUNTER_ARROWS_DOOMSHOT = "Tir maudit"
|
||||
|
||||
ZHUNTER_RAPIDFIRE = "Tir rapide"
|
||||
--ZHUNTER_IMPROVEDHAWK = "Quick Shots"
|
||||
--ZHUNTER_BERSERKING = "Berserking"
|
||||
ZHUNTER_AUTO = "Tir automatique"
|
||||
ZHUNTER_AIMED = "Vis\195\169e"
|
||||
ZHUNTER_SERPENT = "Morsure de serpent"
|
||||
ZHUNTER_SCORPID = "Piq\195\187re de scorpide"
|
||||
ZHUNTER_VIPER = "Morsure de vip\195\168re"
|
||||
ZHUNTER_ARCANE = "Tir des arcanes"
|
||||
ZHUNTER_CONCUSSIVE = "Trait de choc"
|
||||
ZHUNTER_DISTRACTING = "Trait provocateur"
|
||||
|
||||
ZHUNTER_TRACK_HUMANOIDS = "Pistage des humano\195\175des"
|
||||
ZHUNTER_TRACK_HIDDEN = "Pistage des camoufl\195\169s"
|
||||
ZHUNTER_TRACK_BEASTS = "Pistage des b\195\170tes"
|
||||
ZHUNTER_TRACK_ELEMENTALS = "Pistage des \195\169l\195\169mentaires"
|
||||
ZHUNTER_TRACK_DEMONS = "Pistage des d\195\169mons"
|
||||
ZHUNTER_TRACK_DRAGONKIN = "Pistage des draconiens"
|
||||
ZHUNTER_TRACK_UNDEAD = "Pistage des morts-vivants"
|
||||
ZHUNTER_TRACK_GIANTS = "Pistage des g\195\169ants"
|
||||
--ZHUNTER_TRACK_MINERALS = "Find Minerals"
|
||||
--ZHUNTER_TRACK_HERBS = "Find Herbs"
|
||||
--ZHUNTER_TRACK_TREASURE = "Find Treasure"
|
||||
|
||||
ZHUNTER_TRAP_FREEZING = "Pi\195\168ge givrant"
|
||||
ZHUNTER_TRAP_FROST = "Pi\195\168ge de givre"
|
||||
ZHUNTER_TRAP_IMMOLATION = "Pi\195\168ge d'Immolation"
|
||||
ZHUNTER_TRAP_EXPLOSIVE = "Pi\195\168ge explosif"
|
||||
|
||||
ZHUNTER_ASPECT_HAWK = "Aspect du faucon"
|
||||
ZHUNTER_ASPECT_MONKEY = "Aspect du singe"
|
||||
ZHUNTER_ASPECT_CHEETAH = "Aspect du gu\195\169pard"
|
||||
ZHUNTER_ASPECT_BEAST = "Aspect de la b\195\170te"
|
||||
ZHUNTER_ASPECT_PACK = "Aspect de la meute"
|
||||
ZHUNTER_ASPECT_WILD = "Aspect de la nature"
|
||||
|
||||
ZHUNTER_PET_EYES = "oeil de la b\195\170te"
|
||||
--ZHUNTER_PET_DISMISS = "Dismiss Pet"
|
||||
--ZHUNTER_PET_MEND = "Mend Pet"
|
||||
--ZHUNTER_PET_FEED = "Feed Pet"
|
||||
--ZHUNTER_PET_CALL = "Call Pet"
|
||||
--ZHUNTER_PET_REVIVE = "Revive Pet"
|
||||
|
||||
end
|
||||
|
||||
-- ////////////////////////////////////////////////////////////////
|
||||
-- GERMAN
|
||||
-- \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
-- � = /195/164
|
||||
-- � = /195/188
|
||||
-- � = /195/182
|
||||
|
||||
if ( GetLocale() == "deDE" ) then
|
||||
|
||||
ZHUNTER_MAGMADAR = "Magmadar"
|
||||
ZHUNTER_FLAMEGORE = "Flammenmaul"
|
||||
ZHUNTER_CHROMMAGUS = "Chrommagus"
|
||||
ZHUNTER_HUHURAN = "Prinzessin Huhuran"
|
||||
--ZHUNTER_GLUTH = "Gluth"
|
||||
|
||||
ZHUNTER_YOU = "Ihr"
|
||||
ZHUNTER_HUNTER = "J\195\164ger"
|
||||
ZHUNTER_BOWS = "B\195\182gen"
|
||||
ZHUNTER_CROSSBOWS = "Armbr\195\188ste"
|
||||
ZHUNTER_GUNS = "Schusswaffen"
|
||||
ZHUNTER_AFFLICTED_DAZED = "(.+) (.+) ersch\195\188ttert"
|
||||
|
||||
ZHUNTER_BULLETS_LIGHT = "Leichtes Geschoss"
|
||||
ZHUNTER_BULLETS_CRAFTLIGHT = "Gefertigtes leichtes Geschoss"
|
||||
ZHUNTER_BULLETS_FLASH = "Blitzk\195\188gelchen"
|
||||
ZHUNTER_BULLETS_HEAVY = "Schweres Geschoss"
|
||||
ZHUNTER_BULLETS_PEBBLE = "Glatter Kiesel"
|
||||
ZHUNTER_BULLETS_CRAFTHEAVY = "Gefertigtes schweres Geschoss"
|
||||
ZHUNTER_BULLETS_SOLID = "Robustes Geschoss"
|
||||
ZHUNTER_BULLETS_CRAFTSOLID = "Gefertigtes robustes Geschoss"
|
||||
ZHUNTER_BULLETS_EXPLODING = "Explosivgeschoss"
|
||||
ZHUNTER_BULLETS_MITHRILSLUG = "Stark einschlagende Mithrilpatronen"
|
||||
ZHUNTER_BULLETS_ACCURATE = "Genaue Patronen"
|
||||
ZHUNTER_BULLETS_GYROSHOT = "Gyro-Mithrilgeschoss"
|
||||
ZHUNTER_BULLETS_ICETHREADED = "Eisgewirkte Kugel"
|
||||
ZHUNTER_BULLETS_THORIUM = "Thoriumpatronen"
|
||||
ZHUNTER_BULLETS_ROCKSHARD = "Felssplitterk\195\188gelchen"
|
||||
ZHUNTER_BULLETS_CANNONBALL = "Miniaturkanonenkugeln"
|
||||
|
||||
ZHUNTER_ARROWS_ROUGH = "Rauer Pfeil"
|
||||
ZHUNTER_ARROWS_SHARP = "Scharfer Pfeil"
|
||||
ZHUNTER_ARROWS_RAZOR = "Schneidenpfeil"
|
||||
ZHUNTER_ARROWS_FEATHER = "Gefiederter Pfeil"
|
||||
ZHUNTER_ARROWS_PRECISION = "Pr\195\164zisionspfeil"
|
||||
ZHUNTER_ARROWS_JAGGED = "Gezackter Pfeil"
|
||||
ZHUNTER_ARROWS_ICETHREADED = "Eisgewirkter Pfeil"
|
||||
ZHUNTER_ARROWS_THORIUM = "Thoriumpfeile"
|
||||
ZHUNTER_ARROWS_DOOMSHOT = "Verdammnisgeschoss"
|
||||
|
||||
ZHUNTER_RAPIDFIRE = "Schnellfeuer"
|
||||
ZHUNTER_IMPROVEDHAWK = "Schnelle Sch\195\188sse"
|
||||
ZHUNTER_BERSERKING = "Berserker"
|
||||
ZHUNTER_AUTO = "Autom. Schuss"
|
||||
ZHUNTER_AIMED = "Gezielter Schuss"
|
||||
ZHUNTER_SERPENT = "Schlangenbiss"
|
||||
ZHUNTER_SCORPID = "Skorpidstich"
|
||||
ZHUNTER_VIPER = "Vipernbiss"
|
||||
ZHUNTER_ARCANE = "Arkaner Schuss"
|
||||
ZHUNTER_CONCUSSIVE = "Ersch\195\188tternder Schuss"
|
||||
ZHUNTER_DISTRACTING = "Ablenkender Schuss"
|
||||
|
||||
ZHUNTER_TRACK_HUMANOIDS = "Humanoide aufsp\195\188ren"
|
||||
ZHUNTER_TRACK_HIDDEN = "Verborgenes aufsp\195\188ren"
|
||||
ZHUNTER_TRACK_BEASTS = "Wildtiere aufsp\195\188ren"
|
||||
ZHUNTER_TRACK_ELEMENTALS = "Elementare aufsp\195\188ren"
|
||||
ZHUNTER_TRACK_DEMONS = "D\195\164monen aufsp\195\188ren"
|
||||
ZHUNTER_TRACK_DRAGONKIN = "Drachkin aufsp\195\188ren"
|
||||
ZHUNTER_TRACK_UNDEAD = "Untote aufsp\195\188ren"
|
||||
ZHUNTER_TRACK_GIANTS = "Riesen aufsp\195\188ren"
|
||||
ZHUNTER_TRACK_MINERALS = "Mineraliensuche"
|
||||
ZHUNTER_TRACK_HERBS = "Kr\195\164utersuche"
|
||||
ZHUNTER_TRACK_TREASURE = "Schatzsucher"
|
||||
|
||||
ZHUNTER_TRAP_FREEZING = "Eisk\195\164ltefalle"
|
||||
ZHUNTER_TRAP_FROST = "Frostfalle"
|
||||
ZHUNTER_TRAP_IMMOLATION = "Feuerbrandfalle"
|
||||
ZHUNTER_TRAP_EXPLOSIVE = "Sprengfalle"
|
||||
|
||||
ZHUNTER_ASPECT_HAWK = "Aspekt des Falken"
|
||||
ZHUNTER_ASPECT_MONKEY = "Aspekt des Affen"
|
||||
ZHUNTER_ASPECT_CHEETAH = "Aspekt des Geparden"
|
||||
ZHUNTER_ASPECT_BEAST = "Aspekt des Wildtiers"
|
||||
ZHUNTER_ASPECT_PACK = "Aspekt des Rudels"
|
||||
ZHUNTER_ASPECT_WILD = "Aspekt der Wildnis"
|
||||
|
||||
ZHUNTER_PET_EYES = "Augen des Wildtiers"
|
||||
ZHUNTER_PET_DISMISS = "Tier freigeben"
|
||||
ZHUNTER_PET_MEND = "Tier heilen"
|
||||
ZHUNTER_PET_FEED = "Tier f\195\188ttern"
|
||||
ZHUNTER_PET_CALL = "Tier rufen"
|
||||
ZHUNTER_PET_REVIVE = "Tier wiederbeleben"
|
||||
ZHUNTER_PET_TAMING = "Wildtier z\195\164hmen"
|
||||
ZHUNTER_PET_TRAINING = "Wildtierausbildung"
|
||||
|
||||
ZHUNTER_PET_POSITION = "Pet Command: Take Position"
|
||||
|
||||
end
|
||||
@@ -0,0 +1,149 @@
|
||||
if not ZHunterMod_Saved then
|
||||
ZHunterMod_Saved = {}
|
||||
end
|
||||
|
||||
BINDING_HEADER_ZAspectHeader = "ZAspect Buttons"
|
||||
BINDING_HEADER_ZTrackHeader = "ZTrack Buttons"
|
||||
BINDING_HEADER_ZTrapHeader = "ZTrap Buttons"
|
||||
BINDING_HEADER_ZPetHeader = "ZPet Buttons"
|
||||
BINDING_HEADER_ZAmmoHeader = "ZAmmo Buttons"
|
||||
BINDING_HEADER_ZMountsHeader = "ZMounts Buttons"
|
||||
BINDING_HEADER_ZCompanionsHeader = "ZCompanions Buttons"
|
||||
BINDING_HEADER_ZToysHeader = "ZToys Buttons"
|
||||
|
||||
ZHunterModTooltip = CreateFrame("GameTooltip", "ZHunterModTooltip", nil, "GameTooltipTemplate")
|
||||
|
||||
function MTH_ZH_IsModuleEnabled()
|
||||
if not (MTH and MTH.IsModuleEnabled) then
|
||||
return true
|
||||
end
|
||||
return MTH:IsModuleEnabled("zhunter", true)
|
||||
end
|
||||
|
||||
function MTH_ZH_GetSavedRoot()
|
||||
if type(ZHunterMod_Saved) ~= "table" then
|
||||
ZHunterMod_Saved = {}
|
||||
end
|
||||
return ZHunterMod_Saved
|
||||
end
|
||||
|
||||
function MTH_ZH_GetSavedTable(key)
|
||||
local root = MTH_ZH_GetSavedRoot()
|
||||
if type(key) ~= "string" or key == "" then
|
||||
return root
|
||||
end
|
||||
if type(root[key]) ~= "table" then
|
||||
root[key] = {}
|
||||
end
|
||||
return root[key]
|
||||
end
|
||||
|
||||
local function MTH_ZH_MigrateButtonSavedKeys_Replace()
|
||||
local root = MTH_ZH_GetSavedRoot()
|
||||
if type(root) ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
local mapping = {
|
||||
{"ZHunterButtonAspect", "zButtonAspect"},
|
||||
{"ZHunterButtonTrack", "zButtonTrack"},
|
||||
{"ZHunterButtonTrap", "zButtonTrap"},
|
||||
{"ZHunterButtonAmmo", "zButtonAmmo"},
|
||||
{"ZHunterButtonPet", "zButtonPet"},
|
||||
{"ZHunterButtonMounts", "zButtonMounts"},
|
||||
{"ZHunterButtonCompanions", "zButtonCompanions"},
|
||||
{"ZHunterButtonToys", "zButtonToys"},
|
||||
}
|
||||
|
||||
for i = 1, table.getn(mapping) do
|
||||
local oldKey = mapping[i][1]
|
||||
local newKey = mapping[i][2]
|
||||
if root[oldKey] ~= nil then
|
||||
root[newKey] = root[oldKey]
|
||||
root[oldKey] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
MTH_ZH_MigrateButtonSavedKeys_Replace()
|
||||
|
||||
function MTH_ZH_Print(message, severity)
|
||||
if type(MTH_Log) == "function" then
|
||||
MTH_Log(message, severity)
|
||||
return
|
||||
end
|
||||
if MTH and MTH.Print then
|
||||
MTH:Print(message, severity)
|
||||
return
|
||||
end
|
||||
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("[MetaHunt] " .. tostring(message or ""), 1, 0.9, 0.3)
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_ZH_HandleDisabledSlash(message, tableKey, fieldKey)
|
||||
if MTH_ZH_IsModuleEnabled() then
|
||||
return false
|
||||
end
|
||||
|
||||
if type(tableKey) == "string" and tableKey ~= "" then
|
||||
if fieldKey then
|
||||
local tbl = MTH_ZH_GetSavedTable(tableKey)
|
||||
tbl[fieldKey] = nil
|
||||
else
|
||||
local root = MTH_ZH_GetSavedRoot()
|
||||
root[tableKey] = nil
|
||||
end
|
||||
end
|
||||
|
||||
if message then
|
||||
MTH_ZH_Print(message)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ZHunterMod_AlignButtons()
|
||||
zButtonAmmo:ClearAllPoints()
|
||||
zButtonAmmo:SetPoint("TOP", zButtonAspect, "BOTTOM", 0, -15)
|
||||
zButtonTrack:ClearAllPoints()
|
||||
zButtonTrack:SetPoint("TOP", zButtonAmmo, "BOTTOM", 0, -15)
|
||||
zButtonTrap:ClearAllPoints()
|
||||
zButtonTrap:SetPoint("TOP", zButtonTrack, "BOTTOM", 0, -15)
|
||||
zButtonPet:ClearAllPoints()
|
||||
zButtonPet:SetPoint("TOP", zButtonTrap, "BOTTOM", 0, -15)
|
||||
zButtonMounts:ClearAllPoints()
|
||||
zButtonMounts:SetPoint("TOP", zButtonPet, "BOTTOM", 0, -15)
|
||||
zButtonCompanions:ClearAllPoints()
|
||||
zButtonCompanions:SetPoint("TOP", zButtonMounts, "BOTTOM", 0, -15)
|
||||
zButtonToys:ClearAllPoints()
|
||||
zButtonToys:SetPoint("TOP", zButtonCompanions, "BOTTOM", 0, -15)
|
||||
if AutoStripDisplay then
|
||||
AutoStripDisplay:ClearAllPoints()
|
||||
AutoStripDisplay:SetPoint("TOP", zButtonToys, "BOTTOM", 0, -10)
|
||||
end
|
||||
end
|
||||
|
||||
function ZMarkTarget()
|
||||
if not MTH_ZH_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
if not UnitExists("target") then return end
|
||||
for i=1, 40 do
|
||||
if not UnitDebuff("target", i) then break end
|
||||
ZHunterModTooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
ZHunterModTooltip:SetUnitDebuff("target", i)
|
||||
local spell = ZHunterModTooltipTextLeft1:GetText()
|
||||
if spell == ZHUNTER_HUNTERSMARK then
|
||||
return
|
||||
end
|
||||
end
|
||||
CastSpellByName(ZHUNTER_HUNTERSMARK)
|
||||
return 1
|
||||
end
|
||||
|
||||
SLASH_ZHunterMod1 = "/zhunter"
|
||||
SlashCmdList["ZHunterMod"] = function(msg)
|
||||
MTH_ZH_Print("Possible Slash Commands: \"/zammo\", \"/zaspect\", \"/ztrack\", \"/ztrap\", \"/zpet\", \"/zmounts\", \"/zcompanions\", \"/zminipets\", \"/ztoys\", \"/zstrip\", \"/zantidaze\"")
|
||||
end
|
||||
@@ -0,0 +1,508 @@
|
||||
-- MAX_SPELLS = 1024
|
||||
|
||||
local function ZSpellButton_ApplySavedVisibility(parent, foundCount)
|
||||
if not parent then
|
||||
return
|
||||
end
|
||||
|
||||
local shouldShow = true
|
||||
if foundCount and tonumber(foundCount) then
|
||||
if tonumber(foundCount) <= 0 then
|
||||
shouldShow = false
|
||||
end
|
||||
end
|
||||
|
||||
if type(MTH_ZH_GetSavedTable) == "function" and parent.name then
|
||||
local saved = MTH_ZH_GetSavedTable(parent.name)
|
||||
if saved then
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
shouldShow = false
|
||||
end
|
||||
if saved["parent"] and saved["parent"]["hide"] then
|
||||
shouldShow = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if shouldShow then
|
||||
parent:Show()
|
||||
else
|
||||
parent:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function ZSpellButton_SetButtons(parent, spells)
|
||||
--DEFAULT_CHAT_FRAME:AddMessage(" Parent = "..parent.name, 0, 1, 1)
|
||||
if not (parent and parent.count and parent.name and spells) then return end
|
||||
parent.spells = spells
|
||||
|
||||
if type(parent.customSetButtons) == "function" then
|
||||
local customFound = parent.customSetButtons(parent, spells)
|
||||
ZSpellButton_ApplySavedVisibility(parent, customFound)
|
||||
return customFound
|
||||
end
|
||||
|
||||
if not GetSpellName(1, "spell") then
|
||||
parent:RegisterEvent("SPELLS_CHANGED")
|
||||
return -1
|
||||
end
|
||||
local spell, finished, temp
|
||||
local info = {}
|
||||
-- Find All Spell IDs
|
||||
for i=1, MAX_SPELLS do
|
||||
spell = GetSpellName(i, "spell")
|
||||
if not spell or finished then
|
||||
break
|
||||
end
|
||||
finished = 1
|
||||
for i2=1, table.getn(spells) do
|
||||
if not info[i2] then
|
||||
finished = nil
|
||||
if spells[i2] == spell then
|
||||
temp = i
|
||||
while spells[i2] == spell do
|
||||
temp = temp + 1
|
||||
spell = GetSpellName(temp, "spell")
|
||||
end
|
||||
info[i2] = (temp-1)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Hide All Children
|
||||
for i=1, parent.count do
|
||||
local child = getglobal(parent.name..i)
|
||||
child:Hide()
|
||||
child.id = nil
|
||||
child.icon = nil
|
||||
child.isspell = nil
|
||||
end
|
||||
local button
|
||||
local count = 1
|
||||
-- Set Children IDs
|
||||
for i, v in info do
|
||||
if count > parent.count then break end
|
||||
button = getglobal(parent.name..count)
|
||||
button.id = v
|
||||
button.isspell=1
|
||||
ZSpellButton_UpdateButton(button)
|
||||
button:Show()
|
||||
-- Set The Parent To The First Spell
|
||||
if count == 1 then
|
||||
parent.id = v
|
||||
parent.isspell=1
|
||||
ZSpellButton_UpdateButton(parent)
|
||||
parent:Enable()
|
||||
end
|
||||
count = count + 1
|
||||
end
|
||||
local foundCount = count - 1
|
||||
ZSpellButton_ApplySavedVisibility(parent, foundCount)
|
||||
return foundCount
|
||||
end
|
||||
|
||||
local function ZHunterMod_UpdateButtonCount(parent, found)
|
||||
return
|
||||
end
|
||||
|
||||
function ZSpellButton_SetExpandDirection(parent, direction)
|
||||
local button = getglobal(parent.name.."1")
|
||||
local offset = parent:GetWidth() / 36
|
||||
local circleVisible = true
|
||||
if type(MTH_ZH_GetSavedTable) == "function" and parent and parent.name then
|
||||
local saved = MTH_ZH_GetSavedTable(parent.name)
|
||||
if saved and saved["parent"] and saved["parent"]["circle"] ~= nil then
|
||||
circleVisible = saved["parent"]["circle"] and true or false
|
||||
end
|
||||
end
|
||||
if parent and parent.circle then
|
||||
if circleVisible then
|
||||
parent.circle:Show()
|
||||
else
|
||||
parent.circle:Hide()
|
||||
end
|
||||
end
|
||||
if circleVisible then
|
||||
offset = offset * 5
|
||||
else
|
||||
offset = offset * 3
|
||||
end
|
||||
button:ClearAllPoints()
|
||||
if direction == "TOP" then
|
||||
button:SetPoint("BOTTOM", parent, "TOP", 0, offset)
|
||||
elseif direction == "BOTTOM" then
|
||||
button:SetPoint("TOP", parent, "BOTTOM", 0, -1 * offset)
|
||||
elseif direction == "LEFT" then
|
||||
button:SetPoint("RIGHT", parent, "LEFT", -1 * offset, 0)
|
||||
elseif direction == "RIGHT" then
|
||||
button:SetPoint("LEFT", parent, "RIGHT", offset, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButton_ArrangeChildren(parent, rows, count, horizontal, vertical)
|
||||
if not (parent and parent.count and parent.name) then return end
|
||||
local left, right, top, bottom = "LEFT", "RIGHT", "TOP", "BOTTOM"
|
||||
local xoffset = parent:GetWidth() / 36
|
||||
xoffset = xoffset * 3
|
||||
local yoffset = -1 * xoffset
|
||||
if horizontal then
|
||||
left, right = "RIGHT", "LEFT"
|
||||
xoffset = xoffset * -1
|
||||
end
|
||||
if vertical then
|
||||
top, bottom = "BOTTOM", "TOP"
|
||||
yoffset = yoffset * -1
|
||||
end
|
||||
if count > parent.count then
|
||||
count = parent.count
|
||||
end
|
||||
local cols = ceil(count / rows)
|
||||
local temp = 1
|
||||
local button
|
||||
for i=2, parent.count do
|
||||
button = getglobal(parent.name..i)
|
||||
if i > count then
|
||||
button:Hide()
|
||||
else
|
||||
if button.id then
|
||||
button:Show()
|
||||
end
|
||||
button:ClearAllPoints()
|
||||
if temp >= cols then
|
||||
button:SetPoint(top, getglobal(parent.name..(i-temp)), bottom, 0, yoffset)
|
||||
temp = 1
|
||||
else
|
||||
button:SetPoint(left, getglobal(parent.name..(i-1)), right, xoffset, 0)
|
||||
temp = temp + 1
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButton_SetSize(parent, size, setChildren)
|
||||
local bgscale = 64 / 36
|
||||
local cdscale = 0.75 / 36
|
||||
if setChildren then
|
||||
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)
|
||||
end
|
||||
else
|
||||
local cscale = 100/36
|
||||
local cxscale = 20 / 36
|
||||
local cyscale = -22 / 36
|
||||
local circleVisible = true
|
||||
if type(MTH_ZH_GetSavedTable) == "function" and parent and parent.name then
|
||||
local saved = MTH_ZH_GetSavedTable(parent.name)
|
||||
if saved and saved["parent"] and saved["parent"]["circle"] ~= nil then
|
||||
circleVisible = saved["parent"]["circle"] and true or false
|
||||
end
|
||||
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()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButton_UpdateButton(button)
|
||||
local texture
|
||||
if not button then
|
||||
button = this
|
||||
end
|
||||
if not (button.id and button.icontexture) then
|
||||
return
|
||||
end
|
||||
texture = button.icon or GetSpellTexture(button.id, "spell")
|
||||
button.icontexture:SetTexture(texture)
|
||||
button.icontexture:Show()
|
||||
end
|
||||
|
||||
function ZSpellButton_UpdateCooldown(button)
|
||||
if not button then
|
||||
button = this
|
||||
end
|
||||
if not button.id or not button.isspell then return end
|
||||
local start, duration, enable = GetSpellCooldown(button.id, "spell")
|
||||
CooldownFrame_SetTimer(button.cooldown, start, duration, enable)
|
||||
if not button.customcolor then
|
||||
local r, g, b = 1.0, 1.0, 1.0
|
||||
if enable ~= 1 then
|
||||
r, g, b = 0.4, 0.4, 0.4
|
||||
end
|
||||
button.icontexture:SetVertexColor(r, g, b)
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButton_CreateChildren(parent, name, count)
|
||||
if not (parent and name and count) then return end
|
||||
parent.children = CreateFrame("Frame", parent:GetName().."Children", UIParent)
|
||||
parent.count = count
|
||||
parent.name = name
|
||||
local button
|
||||
for i=1, count do
|
||||
button = CreateFrame("CheckButton", parent.name..i, parent.children, "ZSpellButtonChildTemplate")
|
||||
button.parent = parent
|
||||
end
|
||||
if type(ZSpellButton_ApplyChildrenExpanded) == "function" then
|
||||
ZSpellButton_ApplyChildrenExpanded(parent)
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButton_OnLoad()
|
||||
this:RegisterEvent("SPELL_UPDATE_COOLDOWN")
|
||||
this:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||||
local name = this:GetName()
|
||||
this.icontexture = getglobal(name.."IconTexture")
|
||||
this.cooldown = getglobal(name.."Cooldown")
|
||||
this.background = getglobal(name.."Background")
|
||||
end
|
||||
|
||||
function ZSpellButton_OnEvent()
|
||||
if event == "SPELL_UPDATE_COOLDOWN" then
|
||||
ZSpellButton_UpdateCooldown()
|
||||
end
|
||||
end
|
||||
|
||||
local function ZSpellButton_EnsureParentFlags(parent)
|
||||
if not (parent and parent.name) then
|
||||
return
|
||||
end
|
||||
local saved = MTH_ZH_GetSavedTable(parent.name)
|
||||
if parent.tooltip == nil and saved["tooltip"] ~= nil then
|
||||
parent.tooltip = saved["tooltip"] and true or false
|
||||
end
|
||||
if parent.hideonclick == nil and saved["children"] and saved["children"]["hideonclick"] ~= nil then
|
||||
parent.hideonclick = saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButton_GetChildrenExpanded(parent)
|
||||
if not (parent and parent.name) then
|
||||
return true
|
||||
end
|
||||
local saved = MTH_ZH_GetSavedTable(parent.name)
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
end
|
||||
if saved["children"]["expanded"] == nil then
|
||||
saved["children"]["expanded"] = 1
|
||||
end
|
||||
local expanded = saved["children"]["expanded"] ~= false and saved["children"]["expanded"] ~= 0
|
||||
return expanded
|
||||
end
|
||||
|
||||
function ZSpellButton_SetChildrenExpanded(parent, expanded)
|
||||
if not (parent and parent.name) then
|
||||
return
|
||||
end
|
||||
local saved = MTH_ZH_GetSavedTable(parent.name)
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
end
|
||||
if expanded then
|
||||
saved["children"]["expanded"] = 1
|
||||
if parent.children then
|
||||
parent.children:Show()
|
||||
end
|
||||
else
|
||||
saved["children"]["expanded"] = 0
|
||||
if parent.children then
|
||||
parent.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
function ZSpellButton_OnEnter()
|
||||
ZSpellButton_EnsureParentFlags(this.parent)
|
||||
if this.parent.tooltip then
|
||||
GameTooltip:SetOwner(this, "ANCHOR_TOPRIGHT")
|
||||
if this.isspell then
|
||||
GameTooltip:SetSpell(this.id, "spell")
|
||||
else
|
||||
GameTooltip:SetText(this.ammocount .. " x "..this.ammolink, 1, 1, 1)
|
||||
--GameTooltip:AddLine("Q="..this.ammocount)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButton_OnClick()
|
||||
ZSpellButton_EnsureParentFlags(this.parent)
|
||||
this:SetChecked(0)
|
||||
if type(this.parent.beforeclick) == "function" then
|
||||
if this.parent.beforeclick(this) then
|
||||
return
|
||||
end
|
||||
end
|
||||
if this.isspell then
|
||||
CastSpell(this.id, "spell")
|
||||
else
|
||||
PickupContainerItem(this.ammobag,this.ammoslot)
|
||||
EquipCursorItem(0)
|
||||
|
||||
-- Update parent button immediately to show newly equipped ammo
|
||||
if not this.isspell then
|
||||
this.parent.id = this.ammoid
|
||||
this.parent.icon = this.icon
|
||||
this.parent.isspell = nil
|
||||
this.parent.ammoname = this.ammoname
|
||||
this.parent.ammobrol = this.ammobrol
|
||||
this.parent.ammoqual = this.ammoqual
|
||||
this.parent.ammolvl = this.ammolvl
|
||||
this.parent.ammotype = this.ammotype
|
||||
this.parent.ammobag = this.ammobag
|
||||
this.parent.ammoslot = this.ammoslot
|
||||
this.parent.ammoid = this.ammoid
|
||||
this.parent.ammolink = this.ammolink
|
||||
this.parent.ammocount = this.ammocount
|
||||
if type(this.parent.customUpdateButton) == "function" then
|
||||
this.parent.customUpdateButton(this.parent)
|
||||
else
|
||||
ZSpellButton_UpdateButton(this.parent)
|
||||
end
|
||||
end
|
||||
end
|
||||
if type(this.parent.afterclick) == "function" then
|
||||
if this.parent.afterclick(this) then
|
||||
return
|
||||
end
|
||||
end
|
||||
if this.parent.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(this.parent, false)
|
||||
elseif this.parent.children then
|
||||
this.parent.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButtonParent_OnLoad()
|
||||
this:RegisterEvent("SPELL_UPDATE_COOLDOWN")
|
||||
this:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
||||
this:RegisterForDrag("LeftButton")
|
||||
this:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||||
local name = this:GetName()
|
||||
this.icontexture = getglobal(name.."IconTexture")
|
||||
this.cooldown = getglobal(name.."Cooldown")
|
||||
this.background = getglobal(name.."Background")
|
||||
this.circle = getglobal(name.."Circle")
|
||||
-- Keep enabled so empty buttons can be moved on low-level characters.
|
||||
this:Enable()
|
||||
end
|
||||
|
||||
function ZSpellButtonParent_OnEvent()
|
||||
if event == "SPELL_UPDATE_COOLDOWN" then
|
||||
ZSpellButton_UpdateCooldown()
|
||||
elseif event == "LEARNED_SPELL_IN_TAB" then
|
||||
if this.name and this.count and this.spells then
|
||||
local found = ZSpellButton_SetButtons(this, this.spells)
|
||||
ZHunterMod_UpdateButtonCount(this, found)
|
||||
end
|
||||
elseif event == "SPELLS_CHANGED" then
|
||||
this.found = ZSpellButton_SetButtons(this, this.spells)
|
||||
ZHunterMod_UpdateButtonCount(this, this.found)
|
||||
if this.found == 0 then
|
||||
this:Hide()
|
||||
end
|
||||
if this.found > -1 then
|
||||
this:UnregisterEvent("SPELLS_CHANGED")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButtonParent_OnEnter(frame)
|
||||
if not frame then
|
||||
frame = this
|
||||
end
|
||||
ZSpellButton_EnsureParentFlags(frame)
|
||||
if frame.tooltip and frame.id then
|
||||
GameTooltip:SetOwner(frame, "ANCHOR_TOPLEFT")
|
||||
local msg, rank
|
||||
|
||||
if frame.isspell then
|
||||
msg, rank = GetSpellName(frame.id, "spell")
|
||||
if string.len(rank) > 0 then
|
||||
msg = msg.." ("..rank..")"
|
||||
end
|
||||
else
|
||||
msg = frame.ammoname
|
||||
end
|
||||
|
||||
GameTooltip:SetText(msg, 1, 1, 1)
|
||||
GameTooltip:AddLine("Alt+Drag To Move This Button")
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function ZSpellButtonParent_OnClick()
|
||||
ZSpellButton_EnsureParentFlags(this)
|
||||
this:SetChecked(0)
|
||||
if arg1 == "RightButton" then
|
||||
local showChildren = not this.children:IsVisible()
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(this, showChildren)
|
||||
elseif showChildren then
|
||||
this.children:Show()
|
||||
else
|
||||
this.children:Hide()
|
||||
end
|
||||
else
|
||||
if type(this.beforeclick) == "function" then
|
||||
if this.beforeclick(this) then
|
||||
return
|
||||
end
|
||||
end
|
||||
if this.isspell then
|
||||
if not this.id then
|
||||
return
|
||||
end
|
||||
CastSpell(this.id, "spell")
|
||||
else
|
||||
if not (this.ammobag and this.ammoslot) then
|
||||
return
|
||||
end
|
||||
PickupContainerItem(this.ammobag,this.ammoslot)
|
||||
EquipCursorItem(0)
|
||||
end
|
||||
if type(this.afterclick) == "function" then
|
||||
if this.afterclick(this) then
|
||||
return
|
||||
end
|
||||
end
|
||||
if this.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(this, false)
|
||||
elseif this.children then
|
||||
this.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,124 @@
|
||||
<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">
|
||||
|
||||
<CheckButton name="ZSpellButtonTemplate" toplevel="true" frameStrata="MEDIUM" movable="true" parent="UIParent" virtual="true">
|
||||
<Size>
|
||||
<AbsDimension x="36" y="36"/>
|
||||
</Size>
|
||||
<Layers>
|
||||
<Layer level="BORDER">
|
||||
<Texture name="$parentIconTexture" setAllPoints="true" hidden="true"/>
|
||||
</Layer>
|
||||
<Layer level="ARTWORK">
|
||||
<Texture name="$parentBackground" file="Interface\Buttons\UI-Quickslot2">
|
||||
<Size>
|
||||
<AbsDimension x="64" y="64"/>
|
||||
</Size>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Frames>
|
||||
<Model name="$parentCooldown" inherits="CooldownFrameTemplate"/>
|
||||
<Frame setAllPoints="true">
|
||||
<Layers>
|
||||
<Layer level="OVERLAY">
|
||||
<Texture name="$parentCircle" file="Interface\Minimap\MiniMap-TrackingBorder">
|
||||
<Size>
|
||||
<AbsDimension x="100" y="100"/>
|
||||
</Size>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="20" y="-22"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
</Frame>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnClick>
|
||||
ZSpellButtonParent_OnClick()
|
||||
</OnClick>
|
||||
<OnEnter>
|
||||
ZSpellButtonParent_OnEnter()
|
||||
</OnEnter>
|
||||
<OnLeave>
|
||||
GameTooltip:Hide()
|
||||
</OnLeave>
|
||||
<OnMouseUp>
|
||||
if ( this.isMoving ) then
|
||||
this:StopMovingOrSizing()
|
||||
this.isMoving = false
|
||||
end
|
||||
</OnMouseUp>
|
||||
<OnDragStart>
|
||||
if IsAltKeyDown() then
|
||||
this:StartMoving()
|
||||
this.isMoving = true
|
||||
end
|
||||
</OnDragStart>
|
||||
<OnDragStop>
|
||||
this:StopMovingOrSizing()
|
||||
this.isMoving = false
|
||||
</OnDragStop>
|
||||
</Scripts>
|
||||
<NormalTexture file=""/>
|
||||
<PushedTexture file="Interface\Buttons\UI-Quickslot-Depress"/>
|
||||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
|
||||
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
|
||||
</CheckButton>
|
||||
|
||||
<CheckButton name="ZSpellButtonChildTemplate" toplevel="true" frameStrata="MEDIUM" movable="true" hidden="true" virtual="true">
|
||||
<Size>
|
||||
<AbsDimension x="36" y="36"/>
|
||||
</Size>
|
||||
<Layers>
|
||||
<Layer level="BORDER">
|
||||
<Texture name="$parentIconTexture" setAllPoints="true" hidden="true"/>
|
||||
</Layer>
|
||||
<Layer level="ARTWORK">
|
||||
<Texture name="$parentBackground" file="Interface\Buttons\UI-Quickslot2">
|
||||
<Size>
|
||||
<AbsDimension x="64" y="64"/>
|
||||
</Size>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Frames>
|
||||
<Model name="$parentCooldown" inherits="CooldownFrameTemplate"/>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnClick>
|
||||
ZSpellButton_OnClick()
|
||||
</OnClick>
|
||||
<OnEnter>
|
||||
ZSpellButton_OnEnter()
|
||||
</OnEnter>
|
||||
<OnLeave>
|
||||
GameTooltip:Hide()
|
||||
</OnLeave>
|
||||
</Scripts>
|
||||
<NormalTexture file=""/>
|
||||
<PushedTexture file="Interface\Buttons\UI-Quickslot-Depress"/>
|
||||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
|
||||
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
|
||||
</CheckButton>
|
||||
|
||||
</Ui>
|
||||
@@ -0,0 +1,50 @@
|
||||
<!--
|
||||
zhunter Module Loader
|
||||
Loads all zhunter addon code and wraps it in the MTH module system
|
||||
-->
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/">
|
||||
<!-- Load module wrapper first so module registration is always available -->
|
||||
<Include file="module.lua"/>
|
||||
|
||||
<!-- Load localization first -->
|
||||
<Include file="Localization.lua"/>
|
||||
|
||||
<!-- Load button template XML first (creates frame definitions) -->
|
||||
<Include file="ZSpellButtonTemplate.xml"/>
|
||||
|
||||
<!-- Load individual button XMLs (creates all button frame instances) -->
|
||||
<Include file="zButtonAspect.xml"/>
|
||||
<Include file="zButtonTrack.xml"/>
|
||||
<Include file="zButtonTrap.xml"/>
|
||||
<Include file="zButtonAmmo.xml"/>
|
||||
<Include file="zButtonPet.xml"/>
|
||||
<Include file="zButtonMounts.xml"/>
|
||||
<Include file="zButtonCompanions.xml"/>
|
||||
<Include file="zButtonToys.xml"/>
|
||||
|
||||
<!-- Load main ZHunterMod.lua FIRST so ZHunterMod_Saved table exists before button files use it -->
|
||||
<Include file="ZHunterMod.lua"/>
|
||||
|
||||
<!-- NOW load all Lua files (which use the frames created above) -->
|
||||
<Include file="ZSpellButtonTemplate.lua"/>
|
||||
|
||||
<!-- Load individual button Lua files -->
|
||||
<Include file="zButtonAspect.lua"/>
|
||||
|
||||
<Include file="zButtonTrack.lua"/>
|
||||
|
||||
<Include file="zButtonTrap.lua"/>
|
||||
|
||||
<Include file="zButtonAmmo.lua"/>
|
||||
|
||||
<Include file="zButtonPet.lua"/>
|
||||
|
||||
<Include file="zButtonMounts.lua"/>
|
||||
|
||||
<Include file="zButtonCompanions.lua"/>
|
||||
|
||||
<Include file="zButtonToys.lua"/>
|
||||
|
||||
<!-- Deferred initialization - runs LAST after all parsing is complete -->
|
||||
<Include file="DeferredInit.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,326 @@
|
||||
------------------------------------------------------
|
||||
-- MetaHunt: zhunter Module Wrapper
|
||||
-- Modern module abstraction for the zhunter addon
|
||||
------------------------------------------------------
|
||||
|
||||
MTH_ZH_MANAGED_HOOKS = true
|
||||
|
||||
local MTH_ZHunter = {
|
||||
name = "zhunter",
|
||||
enabled = true,
|
||||
version = "1.0.3",
|
||||
events = {
|
||||
"VARIABLES_LOADED",
|
||||
"PLAYER_ENTERING_WORLD",
|
||||
"MTH_PET_LIVE_STATE_CHANGED",
|
||||
},
|
||||
features = {
|
||||
aspect = true,
|
||||
tracking = true,
|
||||
traps = true,
|
||||
ammo = true,
|
||||
pet = true,
|
||||
}
|
||||
}
|
||||
|
||||
local function MTH_ZH_Log(msg)
|
||||
if not (MTH and MTH.debug) then
|
||||
return
|
||||
end
|
||||
MTH:Print("[ZH MODULE] " .. tostring(msg), "debug")
|
||||
end
|
||||
|
||||
local MTH_ZH_PostLoginRestoreFrame = nil
|
||||
local MTH_ZH_BootstrapFrame = nil
|
||||
local MTH_ZH_SyncSavedVariables
|
||||
local MTH_ZH_SetButtonsVisible
|
||||
local MTH_ZH_SetAuxFramesVisible
|
||||
local MTH_ZH_RestoreRuntimeFeatureFlags
|
||||
local MTH_ZH_ApplyEnabledRuntimeState
|
||||
local MTH_ZH_QueuePostLoginRestore
|
||||
|
||||
local function MTH_ZH_ApplyDefaultWidgetSpawnLayoutOnce()
|
||||
local savedRoot = nil
|
||||
if type(MTH_ZH_GetSavedRoot) == "function" then
|
||||
savedRoot = MTH_ZH_GetSavedRoot()
|
||||
elseif type(ZHunterMod_Saved) == "table" then
|
||||
savedRoot = ZHunterMod_Saved
|
||||
end
|
||||
|
||||
if type(savedRoot) ~= "table" then
|
||||
return false
|
||||
end
|
||||
|
||||
if savedRoot["_mth_widget_spawn_layout_v1"] then
|
||||
return false
|
||||
end
|
||||
|
||||
local orderedButtons = {
|
||||
"zButtonAspect",
|
||||
"zButtonAmmo",
|
||||
"zButtonTrack",
|
||||
"zButtonTrap",
|
||||
"zButtonPet",
|
||||
"zButtonMounts",
|
||||
"zButtonCompanions",
|
||||
"zButtonToys",
|
||||
}
|
||||
|
||||
local startY = -140
|
||||
local stepY = -54
|
||||
|
||||
local orderedCount = table.getn(orderedButtons)
|
||||
for i = 1, orderedCount do
|
||||
if not getglobal(orderedButtons[i]) then
|
||||
MTH_ZH_Log("skipped one-time default widget spawn layout (missing frame: " .. tostring(orderedButtons[i]) .. ")")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, orderedCount do
|
||||
local buttonName = orderedButtons[i]
|
||||
local button = getglobal(buttonName)
|
||||
if button then
|
||||
button:ClearAllPoints()
|
||||
button:SetPoint("TOP", UIParent, "TOP", 0, startY + ((i - 1) * stepY))
|
||||
end
|
||||
end
|
||||
|
||||
savedRoot["_mth_widget_spawn_layout_v1"] = 1
|
||||
MTH_ZH_Log("applied one-time default widget spawn layout")
|
||||
return true
|
||||
end
|
||||
|
||||
function MTH_ZH_OnDeferredInitComplete()
|
||||
if not (MTH and MTH.IsModuleEnabled and MTH:IsModuleEnabled("zhunter", true)) then
|
||||
if MTH_ZH_SetButtonsVisible then
|
||||
MTH_ZH_SetButtonsVisible(false)
|
||||
end
|
||||
if MTH_ZH_SetAuxFramesVisible then
|
||||
MTH_ZH_SetAuxFramesVisible(false)
|
||||
end
|
||||
MTH_ZH_Log("deferred init applied disabled-state hide")
|
||||
return
|
||||
end
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
MTH_ZH_ApplyDefaultWidgetSpawnLayoutOnce()
|
||||
MTH_ZH_RestoreRuntimeFeatureFlags()
|
||||
MTH_ZH_QueuePostLoginRestore("deferred-init")
|
||||
end
|
||||
|
||||
MTH_ZH_QueuePostLoginRestore = function(tag)
|
||||
if not MTH_ZH_PostLoginRestoreFrame then
|
||||
MTH_ZH_PostLoginRestoreFrame = CreateFrame("Frame", "MTH_ZH_PostLoginRestoreFrame")
|
||||
if not MTH_ZH_PostLoginRestoreFrame then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
MTH_ZH_PostLoginRestoreFrame._mthElapsed = 0
|
||||
MTH_ZH_PostLoginRestoreFrame:SetScript("OnUpdate", function()
|
||||
this._mthElapsed = (this._mthElapsed or 0) + (arg1 or 0)
|
||||
if this._mthElapsed < 0.2 then
|
||||
return
|
||||
end
|
||||
|
||||
this:SetScript("OnUpdate", nil)
|
||||
if not (MTH and MTH.IsModuleEnabled and MTH:IsModuleEnabled("zhunter", true)) then
|
||||
return
|
||||
end
|
||||
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
MTH_ZH_RestoreRuntimeFeatureFlags()
|
||||
MTH_ZH_Log("post-login restore applied: " .. tostring(tag))
|
||||
end)
|
||||
end
|
||||
|
||||
local function MTH_ZH_EnsureBootstrapRestoreFrame()
|
||||
if MTH_ZH_BootstrapFrame then
|
||||
return MTH_ZH_BootstrapFrame
|
||||
end
|
||||
|
||||
MTH_ZH_BootstrapFrame = CreateFrame("Frame", "MTH_ZH_BootstrapRestoreFrame")
|
||||
if not MTH_ZH_BootstrapFrame then
|
||||
return nil
|
||||
end
|
||||
|
||||
MTH_ZH_BootstrapFrame:RegisterEvent("VARIABLES_LOADED")
|
||||
MTH_ZH_BootstrapFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
MTH_ZH_BootstrapFrame:SetScript("OnEvent", function()
|
||||
if not (MTH and MTH.IsModuleEnabled and MTH:IsModuleEnabled("zhunter", true)) then
|
||||
return
|
||||
end
|
||||
|
||||
if event == "VARIABLES_LOADED" then
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
return
|
||||
end
|
||||
|
||||
if event == "PLAYER_ENTERING_WORLD" then
|
||||
MTH_ZH_ApplyEnabledRuntimeState("bootstrap:" .. tostring(event))
|
||||
MTH_ZH_QueuePostLoginRestore("bootstrap:" .. tostring(event))
|
||||
this:UnregisterAllEvents()
|
||||
this:SetScript("OnEvent", nil)
|
||||
end
|
||||
end)
|
||||
|
||||
return MTH_ZH_BootstrapFrame
|
||||
end
|
||||
|
||||
MTH_ZH_ApplyEnabledRuntimeState = function(source)
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
MTH_ZH_SetButtonsVisible(true)
|
||||
MTH_ZH_SetAuxFramesVisible(true)
|
||||
MTH_ZH_RestoreRuntimeFeatureFlags()
|
||||
end
|
||||
|
||||
MTH_ZH_SyncSavedVariables = function()
|
||||
if not MTH or not MTH.GetModuleCharSavedVariables then
|
||||
return
|
||||
end
|
||||
|
||||
local moduleStore = MTH:GetModuleCharSavedVariables("zhunter")
|
||||
|
||||
if type(ZHunterMod_Saved) == "table" then
|
||||
if MTH_CharSavedVariables and MTH_CharSavedVariables.modules then
|
||||
MTH_CharSavedVariables.modules.zhunter = ZHunterMod_Saved
|
||||
end
|
||||
elseif type(moduleStore) == "table" then
|
||||
ZHunterMod_Saved = moduleStore
|
||||
end
|
||||
end
|
||||
|
||||
MTH_ZH_SetButtonsVisible = function(visible)
|
||||
local buttonNames = {
|
||||
"zButtonAspect",
|
||||
"zButtonTrack",
|
||||
"zButtonTrap",
|
||||
"zButtonAmmo",
|
||||
"zButtonPet",
|
||||
"zButtonMounts",
|
||||
"zButtonCompanions",
|
||||
"zButtonToys",
|
||||
}
|
||||
|
||||
local function MTH_ZH_SetChildButtonsVisible(parentButton, parentName, show)
|
||||
if not parentButton then
|
||||
return
|
||||
end
|
||||
|
||||
local showChildren = false
|
||||
if show then
|
||||
if type(ZSpellButton_GetChildrenExpanded) == "function" then
|
||||
showChildren = ZSpellButton_GetChildrenExpanded(parentButton)
|
||||
else
|
||||
showChildren = true
|
||||
end
|
||||
end
|
||||
|
||||
if parentButton.children then
|
||||
if showChildren then
|
||||
parentButton.children:Show()
|
||||
else
|
||||
parentButton.children:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
if not parentButton.count then
|
||||
return
|
||||
end
|
||||
|
||||
local baseName = parentButton.name or parentName
|
||||
if not baseName then
|
||||
return
|
||||
end
|
||||
|
||||
for index = 1, parentButton.count do
|
||||
local child = getglobal(baseName .. index)
|
||||
if child then
|
||||
if showChildren then
|
||||
if child.id then
|
||||
child:Show()
|
||||
else
|
||||
child:Hide()
|
||||
end
|
||||
else
|
||||
child:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, buttonName in ipairs(buttonNames) do
|
||||
local button = getglobal(buttonName)
|
||||
if button then
|
||||
MTH_ZH_SetChildButtonsVisible(button, buttonName, visible)
|
||||
if visible then
|
||||
button:Show()
|
||||
else
|
||||
button:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
MTH_ZH_SetAuxFramesVisible = function(visible)
|
||||
return
|
||||
end
|
||||
|
||||
local function MTH_ZH_ClearRuntimeFeatureFlags()
|
||||
return
|
||||
end
|
||||
|
||||
MTH_ZH_RestoreRuntimeFeatureFlags = function()
|
||||
return
|
||||
end
|
||||
|
||||
function MTH_ZHunter:init()
|
||||
-- ZHunterMod initializes via the game events
|
||||
-- Features: Aspect, Tracking, Trap, Ammo, Pet management buttons
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
MTH_ZH_EnsureBootstrapRestoreFrame()
|
||||
if self.enabled then
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_ZHunter:setEnabled(enabled)
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
if enabled then
|
||||
MTH_ZH_EnsureBootstrapRestoreFrame()
|
||||
MTH_ZH_ApplyEnabledRuntimeState("setEnabled")
|
||||
else
|
||||
MTH_ZH_ClearRuntimeFeatureFlags()
|
||||
MTH_ZH_SetButtonsVisible(false)
|
||||
MTH_ZH_SetAuxFramesVisible(false)
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_ZHunter:onEvent(evt, arg1, arg2)
|
||||
if not self.enabled then
|
||||
return
|
||||
end
|
||||
if evt == "MTH_PET_LIVE_STATE_CHANGED" then
|
||||
if type(zButtonPet_RefreshLiveState) == "function" then
|
||||
zButtonPet_RefreshLiveState(arg1, arg2)
|
||||
end
|
||||
return
|
||||
end
|
||||
if evt == "VARIABLES_LOADED" then
|
||||
MTH_ZH_SyncSavedVariables()
|
||||
MTH_ZH_RestoreRuntimeFeatureFlags()
|
||||
return
|
||||
end
|
||||
if evt == "PLAYER_ENTERING_WORLD" then
|
||||
MTH_ZH_ApplyEnabledRuntimeState("event:" .. tostring(evt))
|
||||
MTH_ZH_QueuePostLoginRestore(evt)
|
||||
end
|
||||
end
|
||||
|
||||
function MTH_ZHunter:cleanup()
|
||||
-- Cleanup code when module is unloaded
|
||||
self:setEnabled(false)
|
||||
end
|
||||
|
||||
-- Register with MTH
|
||||
MTH:RegisterModule("zhunter", MTH_ZHunter)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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="zButtonAmmoFrame">
|
||||
</Frame>
|
||||
<CheckButton name="zButtonAmmo" inherits="ZSpellButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</CheckButton>
|
||||
</Ui>
|
||||
@@ -0,0 +1,281 @@
|
||||
local function zButtonAspect_GetRoot()
|
||||
return MTH_ZH_GetSavedRoot()
|
||||
end
|
||||
|
||||
local root = zButtonAspect_GetRoot()
|
||||
if not root["zButtonAspect"] then
|
||||
root["zButtonAspect"] = {}
|
||||
root["zButtonAspect"]["spells"] = {1, 2, 3, 4, 5, 6, 7}
|
||||
root["zButtonAspect"]["rows"] = 1
|
||||
root["zButtonAspect"]["horizontal"] = nil
|
||||
root["zButtonAspect"]["vertical"] = nil
|
||||
root["zButtonAspect"]["firstbutton"] = "RIGHT"
|
||||
root["zButtonAspect"]["enabled"] = 1
|
||||
root["zButtonAspect"]["tooltip"] = 1
|
||||
root["zButtonAspect"]["parent"] = {}
|
||||
root["zButtonAspect"]["parent"]["size"] = 36
|
||||
root["zButtonAspect"]["parent"]["hide"] = nil
|
||||
root["zButtonAspect"]["parent"]["circle"] = 1
|
||||
root["zButtonAspect"]["children"] = {}
|
||||
root["zButtonAspect"]["children"]["size"] = 36
|
||||
root["zButtonAspect"]["children"]["hideonclick"] = 1
|
||||
end
|
||||
|
||||
ZHunterMod_Aspect_Spells = {
|
||||
ZHUNTER_ASPECT_HAWK,
|
||||
ZHUNTER_ASPECT_MONKEY,
|
||||
ZHUNTER_ASPECT_WOLF,
|
||||
ZHUNTER_ASPECT_CHEETAH,
|
||||
ZHUNTER_ASPECT_PACK,
|
||||
ZHUNTER_ASPECT_WILD,
|
||||
ZHUNTER_ASPECT_BEAST
|
||||
}
|
||||
|
||||
local ZHUNTER_ASPECT_MAX = table.getn(ZHunterMod_Aspect_Spells)
|
||||
|
||||
local function zButtonAspect_GetSaved()
|
||||
local currentRoot = zButtonAspect_GetRoot()
|
||||
if not currentRoot["zButtonAspect"] then
|
||||
currentRoot["zButtonAspect"] = {}
|
||||
end
|
||||
return currentRoot["zButtonAspect"]
|
||||
end
|
||||
|
||||
local function zButtonAspect_EnsureConfig()
|
||||
local saved = zButtonAspect_GetSaved()
|
||||
saved["count"] = nil
|
||||
if saved["rows"] == nil then
|
||||
saved["rows"] = 1
|
||||
end
|
||||
if saved["firstbutton"] == nil then
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
end
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = 1
|
||||
end
|
||||
if saved["tooltip"] == nil then
|
||||
saved["tooltip"] = 1
|
||||
end
|
||||
if not saved["parent"] then
|
||||
saved["parent"] = {}
|
||||
end
|
||||
if saved["parent"]["size"] == nil then
|
||||
saved["parent"]["size"] = 36
|
||||
end
|
||||
if saved["parent"]["circle"] == nil then
|
||||
saved["parent"]["circle"] = 1
|
||||
end
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
end
|
||||
if saved["children"]["size"] == nil then
|
||||
saved["children"]["size"] = 36
|
||||
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
|
||||
for i = 1, ZHUNTER_ASPECT_MAX do
|
||||
if not tonumber(saved["spells"][i]) then
|
||||
saved["spells"][i] = i
|
||||
end
|
||||
if saved["visible"][i] == nil then
|
||||
saved["visible"][i] = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonAspect_ApplyRuntimeSettings()
|
||||
if not zButtonAspect then
|
||||
return
|
||||
end
|
||||
local saved = zButtonAspect_GetSaved()
|
||||
zButtonAspect.tooltip = saved["tooltip"] and true or false
|
||||
zButtonAspect.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
function zButtonAspect_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
function zButtonAspect_OnEvent()
|
||||
if event == "VARIABLES_LOADED" then
|
||||
if not zButtonAspect then
|
||||
return
|
||||
end
|
||||
if UnitClass("player") ~= ZHUNTER_HUNTER then
|
||||
zButtonAspect:UnregisterAllEvents()
|
||||
zButtonAspect:Hide()
|
||||
return
|
||||
end
|
||||
zButtonAspect_CreateButtons()
|
||||
zButtonAspectAdjustment = CreateFrame("Frame", "zButtonAspectAdjustment")
|
||||
zButtonAspectAdjustment:RegisterEvent("PLAYER_AURAS_CHANGED")
|
||||
zButtonAspectAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonAspectAdjustment:SetScript("OnEvent", zButtonAspectAdjustment_OnEvent)
|
||||
zButtonAspect_Tooltip = CreateFrame("GameTooltip", "zButtonAspect_Tooltip", nil, "GameTooltipTemplate")
|
||||
zButtonAspect_SetupSizeAndPosition()
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonAspect_CreateButtons()
|
||||
zButtonAspect_EnsureConfig()
|
||||
local saved = zButtonAspect_GetSaved()
|
||||
|
||||
ZSpellButton_CreateChildren(zButtonAspect, "zButtonAspect", ZHUNTER_ASPECT_MAX)
|
||||
local info = {}
|
||||
local infoIndex = 1
|
||||
for i=1, table.getn(ZHunterMod_Aspect_Spells) do
|
||||
if not tonumber(saved["spells"][i]) then
|
||||
info = ZHunterMod_Aspect_Spells
|
||||
saved["spells"] = {1, 2, 3, 4, 5, 6, 7}
|
||||
break
|
||||
end
|
||||
local spellIndex = saved["spells"][i]
|
||||
if saved["visible"][spellIndex] ~= false then
|
||||
info[infoIndex] = ZHunterMod_Aspect_Spells[spellIndex]
|
||||
infoIndex = infoIndex + 1
|
||||
end
|
||||
end
|
||||
zButtonAspect.found = ZSpellButton_SetButtons(zButtonAspect, info)
|
||||
zButtonAspect_ApplyRuntimeSettings()
|
||||
end
|
||||
|
||||
function zButtonAspect_SetupSizeAndPosition()
|
||||
zButtonAspect_EnsureConfig()
|
||||
local saved = zButtonAspect_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonAspect and zButtonAspect.Hide then
|
||||
zButtonAspect:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
local displayCount = zButtonAspect.found or ZHUNTER_ASPECT_MAX
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
end
|
||||
ZSpellButton_SetSize(zButtonAspect, saved["parent"]["size"])
|
||||
ZSpellButton_SetSize(zButtonAspect, saved["children"]["size"], 1)
|
||||
ZSpellButton_SetExpandDirection(zButtonAspect, saved["firstbutton"])
|
||||
ZSpellButton_ArrangeChildren(zButtonAspect, saved["rows"],
|
||||
displayCount, saved["horizontal"],
|
||||
saved["vertical"])
|
||||
end
|
||||
|
||||
function zButtonAspect_Reset()
|
||||
local currentRoot = zButtonAspect_GetRoot()
|
||||
currentRoot["zButtonAspect"] = {}
|
||||
local saved = zButtonAspect_GetSaved()
|
||||
saved["spells"] = {1, 2, 3, 4, 5, 6, 7}
|
||||
saved["rows"] = 1
|
||||
saved["horizontal"] = nil
|
||||
saved["vertical"] = nil
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
saved["enabled"] = 1
|
||||
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
|
||||
saved["visible"] = {1, 1, 1, 1, 1, 1, 1}
|
||||
zButtonAspect_EnsureConfig()
|
||||
end
|
||||
|
||||
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 not zButtonAspect1.id then
|
||||
return
|
||||
end
|
||||
local buttontextures = {}
|
||||
local button
|
||||
for i=1, zButtonAspect.count do
|
||||
button = getglobal(zButtonAspect.name..i)
|
||||
button.icon = nil
|
||||
if button.id then
|
||||
buttontextures[GetSpellTexture(button.id, "spell")] = button
|
||||
end
|
||||
end
|
||||
local i = 1
|
||||
local texture = GetSpellTexture(zButtonAspect1.id, "spell")
|
||||
local buff = UnitBuff("player", i)
|
||||
local spellname, buffname
|
||||
zButtonAspect.id = zButtonAspect1.id
|
||||
while buff do
|
||||
if texture == buff and zButtonAspect2.id then
|
||||
zButtonAspect.id = zButtonAspect2.id
|
||||
end
|
||||
if buttontextures[buff] then
|
||||
zButtonAspect_Tooltip:SetOwner(this, "ANCHOR_NONE")
|
||||
zButtonAspect_Tooltip:SetUnitBuff("player", i)
|
||||
buffname = zButtonAspect_TooltipTextLeft1:GetText()
|
||||
spellname = GetSpellName(buttontextures[buff].id, "spell")
|
||||
if buffname == spellname then
|
||||
buttontextures[buff].icon = "Interface\\Icons\\Spell_Nature_WispSplode"
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
buff = UnitBuff("player", i)
|
||||
end
|
||||
ZSpellButton_UpdateButton(zButtonAspect)
|
||||
ZSpellButton_UpdateCooldown(zButtonAspect)
|
||||
for i=1, zButtonAspect.count do
|
||||
button = getglobal(zButtonAspect.name..i)
|
||||
if button.id then
|
||||
ZSpellButton_UpdateButton(button)
|
||||
end
|
||||
end
|
||||
if GameTooltip:IsOwned(zButtonAspect) then
|
||||
ZSpellButtonParent_OnEnter(zButtonAspect)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonAspect_KeyBinding(index)
|
||||
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local button
|
||||
if index then
|
||||
button = getglobal("zButtonAspect"..index)
|
||||
else
|
||||
button = zButtonAspect
|
||||
end
|
||||
if button.id then
|
||||
CastSpell(button.id, "spell")
|
||||
if zButtonAspect.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(zButtonAspect, false)
|
||||
elseif zButtonAspect.children then
|
||||
zButtonAspect.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_zButtonAspect1 = "/ZAspect"
|
||||
SlashCmdList["zButtonAspect"] = function(msg)
|
||||
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Aspect button is disabled while module 'zhunter' is disabled.") then
|
||||
return
|
||||
end
|
||||
if msg == "reset" then
|
||||
zButtonAspect_Reset()
|
||||
zButtonAspect:ClearAllPoints()
|
||||
zButtonAspect:SetPoint("CENTER", UIParent, "CENTER", -60, 0)
|
||||
elseif msg == "options" then
|
||||
MTH_OpenOptions("Aspect")
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
|
||||
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="zButtonAspectFrame">
|
||||
</Frame>
|
||||
<CheckButton name="zButtonAspect" inherits="ZSpellButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="-60" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</CheckButton>
|
||||
</Ui>
|
||||
@@ -0,0 +1,323 @@
|
||||
local function zButtonCompanions_GetRoot()
|
||||
return MTH_ZH_GetSavedRoot()
|
||||
end
|
||||
|
||||
local root = zButtonCompanions_GetRoot()
|
||||
if not root["zButtonCompanions"] then
|
||||
root["zButtonCompanions"] = {}
|
||||
root["zButtonCompanions"]["spells"] = {}
|
||||
root["zButtonCompanions"]["rows"] = 1
|
||||
root["zButtonCompanions"]["horizontal"] = nil
|
||||
root["zButtonCompanions"]["vertical"] = nil
|
||||
root["zButtonCompanions"]["firstbutton"] = "RIGHT"
|
||||
root["zButtonCompanions"]["enabled"] = 0
|
||||
root["zButtonCompanions"]["tooltip"] = 1
|
||||
root["zButtonCompanions"]["parent"] = {}
|
||||
root["zButtonCompanions"]["parent"]["size"] = 36
|
||||
root["zButtonCompanions"]["parent"]["hide"] = nil
|
||||
root["zButtonCompanions"]["parent"]["circle"] = 1
|
||||
root["zButtonCompanions"]["children"] = {}
|
||||
root["zButtonCompanions"]["children"]["size"] = 36
|
||||
root["zButtonCompanions"]["children"]["hideonclick"] = 1
|
||||
end
|
||||
|
||||
local ZHUNTER_COMPANIONS_BUTTON_MAX = 80
|
||||
|
||||
local function zButtonCompanions_GetSaved()
|
||||
local currentRoot = zButtonCompanions_GetRoot()
|
||||
if not currentRoot["zButtonCompanions"] then
|
||||
currentRoot["zButtonCompanions"] = {}
|
||||
end
|
||||
return currentRoot["zButtonCompanions"]
|
||||
end
|
||||
|
||||
local function zButtonCompanions_EnsureConfig()
|
||||
local saved = zButtonCompanions_GetSaved()
|
||||
saved["count"] = nil
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = 0
|
||||
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["parent"] then
|
||||
saved["parent"] = {}
|
||||
end
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
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["children"]["size"] then
|
||||
saved["children"]["size"] = 36
|
||||
end
|
||||
if not saved["rows"] or saved["rows"] < 1 then
|
||||
saved["rows"] = 1
|
||||
end
|
||||
if not saved["firstbutton"] then
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonCompanions_ApplyRuntimeSettings()
|
||||
if not zButtonCompanions then
|
||||
return
|
||||
end
|
||||
local saved = zButtonCompanions_GetSaved()
|
||||
zButtonCompanions.tooltip = saved["tooltip"] and true or false
|
||||
zButtonCompanions.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
local function zButtonCompanions_NormalizeTabName(value)
|
||||
local text = string.lower(tostring(value or ""))
|
||||
text = string.gsub(text, "%s+", "")
|
||||
text = string.gsub(text, "[^%a]", "")
|
||||
while string.sub(text, 1, 1) == "z" and string.len(text) > 1 do
|
||||
text = string.sub(text, 2)
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
local function zButtonCompanions_FindTabBounds()
|
||||
if type(GetNumSpellTabs) ~= "function" or type(GetSpellTabInfo) ~= "function" then
|
||||
return nil, nil
|
||||
end
|
||||
local tabCount = GetNumSpellTabs() or 0
|
||||
for tabIndex = 1, tabCount do
|
||||
local tabName, _, tabOffset, tabEntries = GetSpellTabInfo(tabIndex)
|
||||
local normalized = zButtonCompanions_NormalizeTabName(tabName)
|
||||
if string.find(normalized, "companion", 1, true) or string.find(normalized, "minipet", 1, true) then
|
||||
return tonumber(tabOffset) or 0, tonumber(tabEntries) or 0
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
local function zButtonCompanions_CollectTabSpellIds()
|
||||
local tabOffset, tabEntries = zButtonCompanions_FindTabBounds()
|
||||
if not tabOffset or not tabEntries or tabEntries <= 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local spellIds = {}
|
||||
local bookType = BOOKTYPE_SPELL or "spell"
|
||||
local maxIndex = tabOffset + tabEntries
|
||||
for spellIndex = tabOffset + 1, maxIndex do
|
||||
local spellName = GetSpellName(spellIndex, bookType)
|
||||
if spellName and spellName ~= "" then
|
||||
table.insert(spellIds, spellIndex)
|
||||
end
|
||||
end
|
||||
return spellIds
|
||||
end
|
||||
|
||||
local function zButtonCompanions_ApplySpellIds(spellIds)
|
||||
if not zButtonCompanions then
|
||||
return 0
|
||||
end
|
||||
|
||||
local parent = zButtonCompanions
|
||||
local childCount = parent.count or ZHUNTER_COMPANIONS_BUTTON_MAX
|
||||
|
||||
for i = 1, childCount do
|
||||
local child = getglobal("zButtonCompanions" .. i)
|
||||
if child then
|
||||
child:Hide()
|
||||
child.id = nil
|
||||
child.icon = nil
|
||||
child.isspell = nil
|
||||
end
|
||||
end
|
||||
|
||||
local found = 0
|
||||
for i = 1, table.getn(spellIds) do
|
||||
if found >= childCount then
|
||||
break
|
||||
end
|
||||
local spellId = spellIds[i]
|
||||
if spellId then
|
||||
found = found + 1
|
||||
local child = getglobal("zButtonCompanions" .. found)
|
||||
if child then
|
||||
child.id = spellId
|
||||
child.isspell = 1
|
||||
ZSpellButton_UpdateButton(child)
|
||||
child:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if found > 0 then
|
||||
parent.id = spellIds[1]
|
||||
parent.isspell = 1
|
||||
ZSpellButton_UpdateButton(parent)
|
||||
parent:Enable()
|
||||
parent:Show()
|
||||
else
|
||||
parent.id = nil
|
||||
parent:Hide()
|
||||
end
|
||||
|
||||
return found
|
||||
end
|
||||
|
||||
local function zButtonCompanions_RefreshSpells()
|
||||
if not zButtonCompanions then
|
||||
return 0
|
||||
end
|
||||
local saved = zButtonCompanions_GetSaved()
|
||||
local spellIds = zButtonCompanions_CollectTabSpellIds()
|
||||
local spellNames = {}
|
||||
local bookType = BOOKTYPE_SPELL or "spell"
|
||||
for i = 1, table.getn(spellIds) do
|
||||
local n = GetSpellName(spellIds[i], bookType)
|
||||
if n and n ~= "" then
|
||||
table.insert(spellNames, n)
|
||||
end
|
||||
end
|
||||
saved["spellIds"] = spellIds
|
||||
saved["spells"] = spellNames
|
||||
zButtonCompanions.spells = spellNames
|
||||
zButtonCompanions.found = zButtonCompanions_ApplySpellIds(spellIds)
|
||||
zButtonCompanions_ApplyRuntimeSettings()
|
||||
return zButtonCompanions.found or 0
|
||||
end
|
||||
|
||||
function zButtonCompanions_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
function zButtonCompanions_OnEvent()
|
||||
if event == "VARIABLES_LOADED" then
|
||||
if not zButtonCompanions then
|
||||
return
|
||||
end
|
||||
if UnitClass("player") ~= ZHUNTER_HUNTER then
|
||||
zButtonCompanions:UnregisterAllEvents()
|
||||
zButtonCompanions:Hide()
|
||||
return
|
||||
end
|
||||
zButtonCompanions_CreateButtons()
|
||||
zButtonCompanionsAdjustment = CreateFrame("Frame", "zButtonCompanionsAdjustment")
|
||||
zButtonCompanionsAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonCompanionsAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonCompanionsAdjustment:SetScript("OnEvent", zButtonCompanionsAdjustment_OnEvent)
|
||||
zButtonCompanions_SetupSizeAndPosition()
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonCompanions_CreateButtons()
|
||||
zButtonCompanions_EnsureConfig()
|
||||
|
||||
if not zButtonCompanions._mthChildrenCreated then
|
||||
ZSpellButton_CreateChildren(zButtonCompanions, "zButtonCompanions", ZHUNTER_COMPANIONS_BUTTON_MAX)
|
||||
zButtonCompanions._mthChildrenCreated = 1
|
||||
end
|
||||
|
||||
zButtonCompanions_RefreshSpells()
|
||||
end
|
||||
|
||||
function zButtonCompanions_SetupSizeAndPosition()
|
||||
local saved = zButtonCompanions_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonCompanions and zButtonCompanions.Hide then
|
||||
zButtonCompanions:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
local displayCount = zButtonCompanions.found or 0
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
end
|
||||
ZSpellButton_SetSize(zButtonCompanions, saved["parent"]["size"])
|
||||
ZSpellButton_SetSize(zButtonCompanions, saved["children"]["size"], 1)
|
||||
ZSpellButton_SetExpandDirection(zButtonCompanions, saved["firstbutton"])
|
||||
ZSpellButton_ArrangeChildren(zButtonCompanions, saved["rows"],
|
||||
displayCount, saved["horizontal"],
|
||||
saved["vertical"])
|
||||
end
|
||||
|
||||
function zButtonCompanions_Reset()
|
||||
local currentRoot = zButtonCompanions_GetRoot()
|
||||
currentRoot["zButtonCompanions"] = {}
|
||||
local saved = zButtonCompanions_GetSaved()
|
||||
saved["spells"] = {}
|
||||
saved["rows"] = 1
|
||||
saved["horizontal"] = nil
|
||||
saved["vertical"] = nil
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
saved["enabled"] = 1
|
||||
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
|
||||
zButtonCompanions_EnsureConfig()
|
||||
end
|
||||
|
||||
function zButtonCompanionsAdjustment_OnEvent()
|
||||
if not zButtonCompanions then
|
||||
return
|
||||
end
|
||||
zButtonCompanions_RefreshSpells()
|
||||
zButtonCompanions_SetupSizeAndPosition()
|
||||
if GameTooltip:IsOwned(zButtonCompanions) then
|
||||
ZSpellButtonParent_OnEnter(zButtonCompanions)
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonCompanions_KeyBinding(index)
|
||||
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local button
|
||||
if index then
|
||||
button = getglobal("zButtonCompanions"..index)
|
||||
else
|
||||
button = zButtonCompanions
|
||||
end
|
||||
if button and button.id then
|
||||
CastSpell(button.id, "spell")
|
||||
if zButtonCompanions.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(zButtonCompanions, false)
|
||||
elseif zButtonCompanions.children then
|
||||
zButtonCompanions.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_zButtonCompanions1 = "/ZCompanions"
|
||||
SLASH_zButtonCompanions2 = "/ZMinipets"
|
||||
SlashCmdList["zButtonCompanions"] = function(msg)
|
||||
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Companions button is disabled while module 'zhunter' is disabled.") then
|
||||
return
|
||||
end
|
||||
if msg == "reset" then
|
||||
zButtonCompanions_Reset()
|
||||
zButtonCompanions:ClearAllPoints()
|
||||
zButtonCompanions:SetPoint("TOP", UIParent, "TOP", 0, -464)
|
||||
zButtonCompanions_RefreshSpells()
|
||||
zButtonCompanions_SetupSizeAndPosition()
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"reset\"")
|
||||
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="zButtonCompanionsFrame">
|
||||
</Frame>
|
||||
<CheckButton name="zButtonCompanions" inherits="ZSpellButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="-180"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</CheckButton>
|
||||
</Ui>
|
||||
@@ -0,0 +1,322 @@
|
||||
local function zButtonMounts_GetRoot()
|
||||
return MTH_ZH_GetSavedRoot()
|
||||
end
|
||||
|
||||
local root = zButtonMounts_GetRoot()
|
||||
if not root["zButtonMounts"] then
|
||||
root["zButtonMounts"] = {}
|
||||
root["zButtonMounts"]["spells"] = {}
|
||||
root["zButtonMounts"]["rows"] = 1
|
||||
root["zButtonMounts"]["horizontal"] = nil
|
||||
root["zButtonMounts"]["vertical"] = nil
|
||||
root["zButtonMounts"]["firstbutton"] = "RIGHT"
|
||||
root["zButtonMounts"]["enabled"] = 0
|
||||
root["zButtonMounts"]["tooltip"] = 1
|
||||
root["zButtonMounts"]["parent"] = {}
|
||||
root["zButtonMounts"]["parent"]["size"] = 36
|
||||
root["zButtonMounts"]["parent"]["hide"] = nil
|
||||
root["zButtonMounts"]["parent"]["circle"] = 1
|
||||
root["zButtonMounts"]["children"] = {}
|
||||
root["zButtonMounts"]["children"]["size"] = 36
|
||||
root["zButtonMounts"]["children"]["hideonclick"] = 1
|
||||
end
|
||||
|
||||
local ZHUNTER_MOUNTS_BUTTON_MAX = 80
|
||||
|
||||
local function zButtonMounts_GetSaved()
|
||||
local currentRoot = zButtonMounts_GetRoot()
|
||||
if not currentRoot["zButtonMounts"] then
|
||||
currentRoot["zButtonMounts"] = {}
|
||||
end
|
||||
return currentRoot["zButtonMounts"]
|
||||
end
|
||||
|
||||
local function zButtonMounts_EnsureConfig()
|
||||
local saved = zButtonMounts_GetSaved()
|
||||
saved["count"] = nil
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = 0
|
||||
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["parent"] then
|
||||
saved["parent"] = {}
|
||||
end
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
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["children"]["size"] then
|
||||
saved["children"]["size"] = 36
|
||||
end
|
||||
if not saved["rows"] or saved["rows"] < 1 then
|
||||
saved["rows"] = 1
|
||||
end
|
||||
if not saved["firstbutton"] then
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonMounts_ApplyRuntimeSettings()
|
||||
if not zButtonMounts then
|
||||
return
|
||||
end
|
||||
local saved = zButtonMounts_GetSaved()
|
||||
zButtonMounts.tooltip = saved["tooltip"] and true or false
|
||||
zButtonMounts.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
local function zButtonMounts_NormalizeTabName(value)
|
||||
local text = string.lower(tostring(value or ""))
|
||||
text = string.gsub(text, "%s+", "")
|
||||
text = string.gsub(text, "[^%a]", "")
|
||||
while string.sub(text, 1, 1) == "z" and string.len(text) > 1 do
|
||||
text = string.sub(text, 2)
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
local function zButtonMounts_FindTabBounds()
|
||||
if type(GetNumSpellTabs) ~= "function" or type(GetSpellTabInfo) ~= "function" then
|
||||
return nil, nil
|
||||
end
|
||||
local tabCount = GetNumSpellTabs() or 0
|
||||
for tabIndex = 1, tabCount do
|
||||
local tabName, _, tabOffset, tabEntries = GetSpellTabInfo(tabIndex)
|
||||
local normalized = zButtonMounts_NormalizeTabName(tabName)
|
||||
if string.find(normalized, "mount", 1, true) then
|
||||
return tonumber(tabOffset) or 0, tonumber(tabEntries) or 0
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
local function zButtonMounts_CollectTabSpellIds()
|
||||
local tabOffset, tabEntries = zButtonMounts_FindTabBounds()
|
||||
if not tabOffset or not tabEntries or tabEntries <= 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local spellIds = {}
|
||||
local bookType = BOOKTYPE_SPELL or "spell"
|
||||
local maxIndex = tabOffset + tabEntries
|
||||
for spellIndex = tabOffset + 1, maxIndex do
|
||||
local spellName = GetSpellName(spellIndex, bookType)
|
||||
if spellName and spellName ~= "" then
|
||||
table.insert(spellIds, spellIndex)
|
||||
end
|
||||
end
|
||||
return spellIds
|
||||
end
|
||||
|
||||
local function zButtonMounts_ApplySpellIds(spellIds)
|
||||
if not zButtonMounts then
|
||||
return 0
|
||||
end
|
||||
|
||||
local parent = zButtonMounts
|
||||
local childCount = parent.count or ZHUNTER_MOUNTS_BUTTON_MAX
|
||||
|
||||
for i = 1, childCount do
|
||||
local child = getglobal("zButtonMounts" .. i)
|
||||
if child then
|
||||
child:Hide()
|
||||
child.id = nil
|
||||
child.icon = nil
|
||||
child.isspell = nil
|
||||
end
|
||||
end
|
||||
|
||||
local found = 0
|
||||
for i = 1, table.getn(spellIds) do
|
||||
if found >= childCount then
|
||||
break
|
||||
end
|
||||
local spellId = spellIds[i]
|
||||
if spellId then
|
||||
found = found + 1
|
||||
local child = getglobal("zButtonMounts" .. found)
|
||||
if child then
|
||||
child.id = spellId
|
||||
child.isspell = 1
|
||||
ZSpellButton_UpdateButton(child)
|
||||
child:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if found > 0 then
|
||||
parent.id = spellIds[1]
|
||||
parent.isspell = 1
|
||||
ZSpellButton_UpdateButton(parent)
|
||||
parent:Enable()
|
||||
parent:Show()
|
||||
else
|
||||
parent.id = nil
|
||||
parent:Hide()
|
||||
end
|
||||
|
||||
return found
|
||||
end
|
||||
|
||||
local function zButtonMounts_RefreshSpells()
|
||||
if not zButtonMounts then
|
||||
return 0
|
||||
end
|
||||
local saved = zButtonMounts_GetSaved()
|
||||
local spellIds = zButtonMounts_CollectTabSpellIds()
|
||||
local spellNames = {}
|
||||
local bookType = BOOKTYPE_SPELL or "spell"
|
||||
for i = 1, table.getn(spellIds) do
|
||||
local n = GetSpellName(spellIds[i], bookType)
|
||||
if n and n ~= "" then
|
||||
table.insert(spellNames, n)
|
||||
end
|
||||
end
|
||||
saved["spellIds"] = spellIds
|
||||
saved["spells"] = spellNames
|
||||
zButtonMounts.spells = spellNames
|
||||
zButtonMounts.found = zButtonMounts_ApplySpellIds(spellIds)
|
||||
zButtonMounts_ApplyRuntimeSettings()
|
||||
return zButtonMounts.found or 0
|
||||
end
|
||||
|
||||
function zButtonMounts_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
function zButtonMounts_OnEvent()
|
||||
if event == "VARIABLES_LOADED" then
|
||||
if not zButtonMounts then
|
||||
return
|
||||
end
|
||||
if UnitClass("player") ~= ZHUNTER_HUNTER then
|
||||
zButtonMounts:UnregisterAllEvents()
|
||||
zButtonMounts:Hide()
|
||||
return
|
||||
end
|
||||
zButtonMounts_CreateButtons()
|
||||
zButtonMountsAdjustment = CreateFrame("Frame", "zButtonMountsAdjustment")
|
||||
zButtonMountsAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonMountsAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonMountsAdjustment:SetScript("OnEvent", zButtonMountsAdjustment_OnEvent)
|
||||
zButtonMounts_SetupSizeAndPosition()
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonMounts_CreateButtons()
|
||||
zButtonMounts_EnsureConfig()
|
||||
|
||||
if not zButtonMounts._mthChildrenCreated then
|
||||
ZSpellButton_CreateChildren(zButtonMounts, "zButtonMounts", ZHUNTER_MOUNTS_BUTTON_MAX)
|
||||
zButtonMounts._mthChildrenCreated = 1
|
||||
end
|
||||
|
||||
zButtonMounts_RefreshSpells()
|
||||
end
|
||||
|
||||
function zButtonMounts_SetupSizeAndPosition()
|
||||
local saved = zButtonMounts_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonMounts and zButtonMounts.Hide then
|
||||
zButtonMounts:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
local displayCount = zButtonMounts.found or 0
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
end
|
||||
ZSpellButton_SetSize(zButtonMounts, saved["parent"]["size"])
|
||||
ZSpellButton_SetSize(zButtonMounts, saved["children"]["size"], 1)
|
||||
ZSpellButton_SetExpandDirection(zButtonMounts, saved["firstbutton"])
|
||||
ZSpellButton_ArrangeChildren(zButtonMounts, saved["rows"],
|
||||
displayCount, saved["horizontal"],
|
||||
saved["vertical"])
|
||||
end
|
||||
|
||||
function zButtonMounts_Reset()
|
||||
local currentRoot = zButtonMounts_GetRoot()
|
||||
currentRoot["zButtonMounts"] = {}
|
||||
local saved = zButtonMounts_GetSaved()
|
||||
saved["spells"] = {}
|
||||
saved["rows"] = 1
|
||||
saved["horizontal"] = nil
|
||||
saved["vertical"] = nil
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
saved["enabled"] = 1
|
||||
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
|
||||
zButtonMounts_EnsureConfig()
|
||||
end
|
||||
|
||||
function zButtonMountsAdjustment_OnEvent()
|
||||
if not zButtonMounts then
|
||||
return
|
||||
end
|
||||
zButtonMounts_RefreshSpells()
|
||||
zButtonMounts_SetupSizeAndPosition()
|
||||
if GameTooltip:IsOwned(zButtonMounts) then
|
||||
ZSpellButtonParent_OnEnter(zButtonMounts)
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonMounts_KeyBinding(index)
|
||||
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local button
|
||||
if index then
|
||||
button = getglobal("zButtonMounts"..index)
|
||||
else
|
||||
button = zButtonMounts
|
||||
end
|
||||
if button and button.id then
|
||||
CastSpell(button.id, "spell")
|
||||
if zButtonMounts.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(zButtonMounts, false)
|
||||
elseif zButtonMounts.children then
|
||||
zButtonMounts.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_zButtonMounts1 = "/ZMounts"
|
||||
SlashCmdList["zButtonMounts"] = function(msg)
|
||||
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Mounts button is disabled while module 'zhunter' is disabled.") then
|
||||
return
|
||||
end
|
||||
if msg == "reset" then
|
||||
zButtonMounts_Reset()
|
||||
zButtonMounts:ClearAllPoints()
|
||||
zButtonMounts:SetPoint("TOP", UIParent, "TOP", 0, -410)
|
||||
zButtonMounts_RefreshSpells()
|
||||
zButtonMounts_SetupSizeAndPosition()
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"reset\"")
|
||||
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="zButtonMountsFrame">
|
||||
</Frame>
|
||||
<CheckButton name="zButtonMounts" inherits="ZSpellButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="-120"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</CheckButton>
|
||||
</Ui>
|
||||
@@ -0,0 +1,454 @@
|
||||
local function zButtonPet_GetRoot()
|
||||
return MTH_ZH_GetSavedRoot()
|
||||
end
|
||||
|
||||
local root = zButtonPet_GetRoot()
|
||||
|
||||
-- Initialize with defaults only if not already configured
|
||||
if not root["zButtonPet"] then
|
||||
root["zButtonPet"] = {}
|
||||
root["zButtonPet"]["pet"] = {}
|
||||
root["zButtonPet"]["pet"]["happiness"] = nil
|
||||
root["zButtonPet"]["pet"]["status"] = nil
|
||||
root["zButtonPet"]["pet"]["dead"] = nil
|
||||
root["zButtonPet"]["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
root["zButtonPet"]["rows"] = 1
|
||||
root["zButtonPet"]["horizontal"] = nil
|
||||
root["zButtonPet"]["vertical"] = nil
|
||||
root["zButtonPet"]["firstbutton"] = "RIGHT"
|
||||
root["zButtonPet"]["enabled"] = 1
|
||||
root["zButtonPet"]["tooltip"] = 1
|
||||
root["zButtonPet"]["parent"] = {}
|
||||
root["zButtonPet"]["parent"]["size"] = 36
|
||||
root["zButtonPet"]["parent"]["hide"] = nil
|
||||
root["zButtonPet"]["parent"]["circle"] = 1
|
||||
root["zButtonPet"]["children"] = {}
|
||||
root["zButtonPet"]["children"]["size"] = 36
|
||||
root["zButtonPet"]["children"]["hideonclick"] = 1
|
||||
end
|
||||
root["zButtonPet"]["food"] = {}
|
||||
|
||||
ZHunterMod_Pet_Spells = {
|
||||
ZHUNTER_PET_EYES,
|
||||
ZHUNTER_PET_DISMISS,
|
||||
ZHUNTER_PET_MEND,
|
||||
ZHUNTER_PET_FEED,
|
||||
ZHUNTER_PET_CALL,
|
||||
ZHUNTER_PET_REVIVE,
|
||||
ZHUNTER_PET_LORE,
|
||||
ZHUNTER_PET_TRAINING,
|
||||
ZHUNTER_PET_TAMING,
|
||||
ZHUNTER_PET_POSITION
|
||||
}
|
||||
|
||||
local ZHUNTER_PET_MAX = table.getn(ZHunterMod_Pet_Spells)
|
||||
|
||||
local function zButtonPet_GetSaved()
|
||||
local currentRoot = zButtonPet_GetRoot()
|
||||
if not currentRoot["zButtonPet"] then
|
||||
currentRoot["zButtonPet"] = {}
|
||||
end
|
||||
return currentRoot["zButtonPet"]
|
||||
end
|
||||
|
||||
local function zButtonPet_EnsureConfig()
|
||||
local saved = zButtonPet_GetSaved()
|
||||
saved["count"] = nil
|
||||
if not saved["pet"] then
|
||||
saved["pet"] = {}
|
||||
end
|
||||
if saved["pet"]["happiness"] == nil then
|
||||
saved["pet"]["happiness"] = nil
|
||||
end
|
||||
if saved["pet"]["status"] == nil then
|
||||
saved["pet"]["status"] = nil
|
||||
end
|
||||
if saved["pet"]["dead"] == nil then
|
||||
saved["pet"]["dead"] = nil
|
||||
end
|
||||
if not saved["parent"] then
|
||||
saved["parent"] = {}
|
||||
end
|
||||
if saved["parent"]["size"] == nil then
|
||||
saved["parent"]["size"] = 36
|
||||
end
|
||||
if saved["parent"]["hide"] == nil then
|
||||
saved["parent"]["hide"] = nil
|
||||
end
|
||||
if saved["parent"]["circle"] == nil then
|
||||
saved["parent"]["circle"] = 1
|
||||
end
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = 1
|
||||
end
|
||||
if saved["tooltip"] == nil then
|
||||
saved["tooltip"] = 1
|
||||
end
|
||||
if saved["rows"] == nil then
|
||||
saved["rows"] = 1
|
||||
end
|
||||
if saved["horizontal"] == nil then
|
||||
saved["horizontal"] = nil
|
||||
end
|
||||
if saved["vertical"] == nil then
|
||||
saved["vertical"] = nil
|
||||
end
|
||||
if saved["firstbutton"] == nil then
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
end
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
end
|
||||
if saved["children"]["size"] == nil then
|
||||
saved["children"]["size"] = 36
|
||||
end
|
||||
if saved["children"]["hideonclick"] == nil then
|
||||
saved["children"]["hideonclick"] = 1
|
||||
end
|
||||
if saved["food"] == nil then
|
||||
saved["food"] = {}
|
||||
end
|
||||
if not saved["spells"] then
|
||||
saved["spells"] = {}
|
||||
end
|
||||
if not saved["visible"] then
|
||||
saved["visible"] = {}
|
||||
end
|
||||
for i = 1, ZHUNTER_PET_MAX do
|
||||
if not tonumber(saved["spells"][i]) then
|
||||
saved["spells"][i] = i
|
||||
end
|
||||
if saved["visible"][i] == nil then
|
||||
saved["visible"][i] = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonPet_ApplyRuntimeSettings()
|
||||
if not zButtonPet then
|
||||
return
|
||||
end
|
||||
local saved = zButtonPet_GetSaved()
|
||||
zButtonPet.tooltip = saved["tooltip"] and true or false
|
||||
zButtonPet.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
function zButtonPet_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
function zButtonPet_OnEvent()
|
||||
if event == "VARIABLES_LOADED" then
|
||||
if not zButtonPet then
|
||||
return
|
||||
end
|
||||
if UnitClass("player") ~= ZHUNTER_HUNTER then
|
||||
zButtonPet:UnregisterAllEvents()
|
||||
zButtonPet:Hide()
|
||||
return
|
||||
end
|
||||
zButtonPet_CreateButtons()
|
||||
zButtonPet.beforeclick = zButtonPetAdjustment_BeforeClick
|
||||
zButtonPet.afterclick = zButtonPet_AfterClick
|
||||
zButtonPetAdjustment = CreateFrame("Frame", "zButtonPetAdjustment")
|
||||
zButtonPetAdjustment:RegisterEvent("UNIT_HEALTH")
|
||||
zButtonPetAdjustment:RegisterEvent("UNIT_HAPPINESS")
|
||||
zButtonPetAdjustment:RegisterEvent("UNIT_PET")
|
||||
zButtonPetAdjustment:RegisterEvent("PET_BAR_UPDATE")
|
||||
zButtonPetAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonPetAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonPetAdjustment:SetScript("OnEvent", zButtonPetAdjustment_OnEvent)
|
||||
zButtonPet_Tooltip = CreateFrame("GameTooltip", "zButtonPet_Tooltip", nil, "GameTooltipTemplate")
|
||||
zButtonPet_SetupSizeAndPosition()
|
||||
zButtonPetAdjustment_OnEvent()
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonPet_CreateButtons()
|
||||
zButtonPet_EnsureConfig()
|
||||
local saved = zButtonPet_GetSaved()
|
||||
|
||||
ZSpellButton_CreateChildren(zButtonPet, "zButtonPet", ZHUNTER_PET_MAX)
|
||||
local info = {}
|
||||
local infoIndex = 1
|
||||
for i=1, table.getn(ZHunterMod_Pet_Spells) do
|
||||
if not tonumber(saved["spells"][i]) then
|
||||
info = ZHunterMod_Pet_Spells
|
||||
saved["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
break
|
||||
end
|
||||
local spellIndex = saved["spells"][i]
|
||||
if saved["visible"][spellIndex] ~= false then
|
||||
info[infoIndex] = ZHunterMod_Pet_Spells[spellIndex]
|
||||
infoIndex = infoIndex + 1
|
||||
end
|
||||
end
|
||||
zButtonPet.found = ZSpellButton_SetButtons(zButtonPet, info)
|
||||
zButtonPet_ApplyRuntimeSettings()
|
||||
end
|
||||
|
||||
function zButtonPet_SetupSizeAndPosition()
|
||||
local saved = zButtonPet_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonPet and zButtonPet.Hide then
|
||||
zButtonPet:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
local displayCount = zButtonPet.found or ZHUNTER_PET_MAX
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
end
|
||||
ZSpellButton_SetSize(zButtonPet, saved["parent"]["size"])
|
||||
ZSpellButton_SetSize(zButtonPet, saved["children"]["size"], 1)
|
||||
ZSpellButton_SetExpandDirection(zButtonPet, saved["firstbutton"])
|
||||
ZSpellButton_ArrangeChildren(zButtonPet, saved["rows"],
|
||||
displayCount, saved["horizontal"],
|
||||
saved["vertical"])
|
||||
end
|
||||
|
||||
function zButtonPet_Reset()
|
||||
local currentRoot = zButtonPet_GetRoot()
|
||||
currentRoot["zButtonPet"] = {}
|
||||
local saved = zButtonPet_GetSaved()
|
||||
saved["pet"] = {}
|
||||
saved["pet"]["happiness"] = nil
|
||||
saved["pet"]["status"] = nil
|
||||
saved["pet"]["dead"] = nil
|
||||
saved["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
saved["rows"] = 1
|
||||
saved["horizontal"] = nil
|
||||
saved["vertical"] = nil
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
saved["enabled"] = 1
|
||||
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
|
||||
saved["visible"] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
|
||||
zButtonPet_EnsureConfig()
|
||||
end
|
||||
|
||||
function IsPetDead()
|
||||
local saved = zButtonPet_GetSaved()
|
||||
return saved["pet"] and saved["pet"]["dead"]
|
||||
end
|
||||
|
||||
local function zButtonPet_GetCorePetInfo()
|
||||
if type(MTH_GetCurrentPetInfo) == "function" then
|
||||
local info = MTH_GetCurrentPetInfo()
|
||||
if type(info) == "table" then
|
||||
return info
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function zButtonPet_RefreshSavedPetState(saved, corePetInfo)
|
||||
local hasLivePet = false
|
||||
if type(UnitExists) == "function" then
|
||||
hasLivePet = UnitExists("pet") and true or false
|
||||
elseif type(corePetInfo) == "table" and corePetInfo.liveExists ~= nil then
|
||||
hasLivePet = corePetInfo.liveExists and true or false
|
||||
end
|
||||
|
||||
if not hasLivePet then
|
||||
saved["pet"]["status"] = nil
|
||||
saved["pet"]["dead"] = nil
|
||||
saved["pet"]["happiness"] = nil
|
||||
return false
|
||||
end
|
||||
|
||||
local currentHealth = (corePetInfo and tonumber(corePetInfo.health)) or (type(UnitHealth) == "function" and UnitHealth("pet")) or nil
|
||||
local currentHealthMax = (corePetInfo and tonumber(corePetInfo.healthMax)) or (type(UnitHealthMax) == "function" and UnitHealthMax("pet")) or nil
|
||||
local isDead = (corePetInfo and corePetInfo.dead) and true or false
|
||||
if not isDead and type(UnitIsDead) == "function" then
|
||||
isDead = UnitIsDead("pet") and true or false
|
||||
end
|
||||
if isDead then
|
||||
saved["pet"]["dead"] = 1
|
||||
else
|
||||
saved["pet"]["dead"] = nil
|
||||
end
|
||||
|
||||
local happiness = corePetInfo and corePetInfo.happiness or nil
|
||||
if happiness == nil and type(GetPetHappiness) == "function" then
|
||||
happiness = GetPetHappiness()
|
||||
end
|
||||
saved["pet"]["happiness"] = happiness
|
||||
|
||||
if isDead then
|
||||
saved["pet"]["status"] = 1
|
||||
elseif currentHealth and currentHealthMax and currentHealthMax > 0 then
|
||||
if (currentHealth / currentHealthMax) > 0.75 then
|
||||
saved["pet"]["status"] = 2
|
||||
else
|
||||
saved["pet"]["status"] = 1
|
||||
end
|
||||
else
|
||||
saved["pet"]["status"] = 2
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function zButtonPetAdjustment_BeforeClick()
|
||||
if CursorHasItem() then
|
||||
DropItemOnUnit("pet")
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonPet_RefreshParentSpell()
|
||||
if not zButtonPet or not zButtonPet.count then
|
||||
return
|
||||
end
|
||||
zButtonPet_EnsureConfig()
|
||||
local saved = zButtonPet_GetSaved()
|
||||
local corePetInfo = zButtonPet_GetCorePetInfo()
|
||||
local hasCurrentPet = nil
|
||||
local hasLivePet = nil
|
||||
if type(corePetInfo) == "table" and corePetInfo.exists ~= nil then
|
||||
hasCurrentPet = corePetInfo.exists and true or false
|
||||
end
|
||||
if type(corePetInfo) == "table" and corePetInfo.liveExists ~= nil then
|
||||
hasLivePet = corePetInfo.liveExists and true or false
|
||||
end
|
||||
zButtonPet_RefreshSavedPetState(saved, corePetInfo)
|
||||
|
||||
local status, happiness, dead
|
||||
local spells = {}
|
||||
local name
|
||||
local choice
|
||||
for i=1, zButtonPet.count do
|
||||
local button
|
||||
button = getglobal(zButtonPet.name..i)
|
||||
if button and button.id then
|
||||
name = GetSpellName(button.id, "spell")
|
||||
spells[name] = button
|
||||
if not choice and (name == ZHUNTER_PET_DISMISS or name == ZHUNTER_PET_EYES or name == ZHUNTER_PET_POSITION) then
|
||||
choice = button
|
||||
end
|
||||
end
|
||||
end
|
||||
status = saved["pet"]["status"]
|
||||
happiness = saved["pet"]["happiness"]
|
||||
dead = saved["pet"]["dead"]
|
||||
local id = zButtonPet.id
|
||||
name = nil
|
||||
|
||||
if hasCurrentPet == false and hasLivePet == false then
|
||||
name = ZHUNTER_PET_TAMING
|
||||
elseif not status then
|
||||
name = ZHUNTER_PET_CALL
|
||||
elseif dead then
|
||||
name = ZHUNTER_PET_REVIVE
|
||||
elseif status == 1 then
|
||||
name = ZHUNTER_PET_MEND
|
||||
elseif happiness ~= 3 then
|
||||
name = ZHUNTER_PET_FEED
|
||||
elseif choice then
|
||||
id = choice.id
|
||||
end
|
||||
|
||||
if name and spells[name] then
|
||||
id = spells[name].id
|
||||
elseif name then
|
||||
local fallbackId = zButtonPet_FindSpellIdByName(name)
|
||||
if fallbackId then
|
||||
id = fallbackId
|
||||
end
|
||||
end
|
||||
zButtonPet.id = id
|
||||
ZSpellButton_UpdateButton(zButtonPet)
|
||||
ZSpellButton_UpdateCooldown(zButtonPet)
|
||||
if GameTooltip:IsOwned(zButtonPet) then
|
||||
ZSpellButtonParent_OnEnter(zButtonPet)
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonPet_AfterClick()
|
||||
zButtonPet_RefreshParentSpell()
|
||||
end
|
||||
|
||||
function zButtonPet_RefreshLiveState(_liveState, _source)
|
||||
zButtonPet_RefreshParentSpell()
|
||||
end
|
||||
|
||||
function zButtonPetAdjustment_OnEvent()
|
||||
if not zButtonPet or not zButtonPet.count then
|
||||
return
|
||||
end
|
||||
|
||||
if (event == "UNIT_HEALTH" or event == "UNIT_HAPPINESS") and arg1 and arg1 ~= "pet" then
|
||||
return
|
||||
end
|
||||
if event == "UNIT_PET" and arg1 and arg1 ~= "player" then
|
||||
return
|
||||
end
|
||||
zButtonPet_RefreshParentSpell()
|
||||
end
|
||||
|
||||
function zButtonPet_KeyBinding(index)
|
||||
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local button
|
||||
if index then
|
||||
button = getglobal("zButtonPet"..index)
|
||||
else
|
||||
button = zButtonPet
|
||||
end
|
||||
if button.id then
|
||||
CastSpell(button.id, "spell")
|
||||
if zButtonPet.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(zButtonPet, false)
|
||||
elseif zButtonPet.children then
|
||||
zButtonPet.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonPet_FeedPet()
|
||||
|
||||
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
|
||||
if msg == "reset" then
|
||||
zButtonPet_Reset()
|
||||
zButtonPet:ClearAllPoints()
|
||||
zButtonPet:SetPoint("CENTER", UIParent, "CENTER", 0, 60)
|
||||
elseif msg == "options" then
|
||||
MTH_OpenOptions("Pet")
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
|
||||
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="zButtonPetFrame">
|
||||
</Frame>
|
||||
<CheckButton name="zButtonPet" inherits="ZSpellButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="60"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</CheckButton>
|
||||
</Ui>
|
||||
@@ -0,0 +1,322 @@
|
||||
local function zButtonToys_GetRoot()
|
||||
return MTH_ZH_GetSavedRoot()
|
||||
end
|
||||
|
||||
local root = zButtonToys_GetRoot()
|
||||
if not root["zButtonToys"] then
|
||||
root["zButtonToys"] = {}
|
||||
root["zButtonToys"]["spells"] = {}
|
||||
root["zButtonToys"]["rows"] = 1
|
||||
root["zButtonToys"]["horizontal"] = nil
|
||||
root["zButtonToys"]["vertical"] = nil
|
||||
root["zButtonToys"]["firstbutton"] = "RIGHT"
|
||||
root["zButtonToys"]["enabled"] = 0
|
||||
root["zButtonToys"]["tooltip"] = 1
|
||||
root["zButtonToys"]["parent"] = {}
|
||||
root["zButtonToys"]["parent"]["size"] = 36
|
||||
root["zButtonToys"]["parent"]["hide"] = nil
|
||||
root["zButtonToys"]["parent"]["circle"] = 1
|
||||
root["zButtonToys"]["children"] = {}
|
||||
root["zButtonToys"]["children"]["size"] = 36
|
||||
root["zButtonToys"]["children"]["hideonclick"] = 1
|
||||
end
|
||||
|
||||
local ZHUNTER_TOYS_BUTTON_MAX = 80
|
||||
|
||||
local function zButtonToys_GetSaved()
|
||||
local currentRoot = zButtonToys_GetRoot()
|
||||
if not currentRoot["zButtonToys"] then
|
||||
currentRoot["zButtonToys"] = {}
|
||||
end
|
||||
return currentRoot["zButtonToys"]
|
||||
end
|
||||
|
||||
local function zButtonToys_EnsureConfig()
|
||||
local saved = zButtonToys_GetSaved()
|
||||
saved["count"] = nil
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = 0
|
||||
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["parent"] then
|
||||
saved["parent"] = {}
|
||||
end
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
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["children"]["size"] then
|
||||
saved["children"]["size"] = 36
|
||||
end
|
||||
if not saved["rows"] or saved["rows"] < 1 then
|
||||
saved["rows"] = 1
|
||||
end
|
||||
if not saved["firstbutton"] then
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonToys_ApplyRuntimeSettings()
|
||||
if not zButtonToys then
|
||||
return
|
||||
end
|
||||
local saved = zButtonToys_GetSaved()
|
||||
zButtonToys.tooltip = saved["tooltip"] and true or false
|
||||
zButtonToys.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
local function zButtonToys_NormalizeTabName(value)
|
||||
local text = string.lower(tostring(value or ""))
|
||||
text = string.gsub(text, "%s+", "")
|
||||
text = string.gsub(text, "[^%a]", "")
|
||||
while string.sub(text, 1, 1) == "z" and string.len(text) > 1 do
|
||||
text = string.sub(text, 2)
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
local function zButtonToys_FindTabBounds()
|
||||
if type(GetNumSpellTabs) ~= "function" or type(GetSpellTabInfo) ~= "function" then
|
||||
return nil, nil
|
||||
end
|
||||
local tabCount = GetNumSpellTabs() or 0
|
||||
for tabIndex = 1, tabCount do
|
||||
local tabName, _, tabOffset, tabEntries = GetSpellTabInfo(tabIndex)
|
||||
local normalized = zButtonToys_NormalizeTabName(tabName)
|
||||
if string.find(normalized, "toy", 1, true) then
|
||||
return tonumber(tabOffset) or 0, tonumber(tabEntries) or 0
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
local function zButtonToys_CollectTabSpellIds()
|
||||
local tabOffset, tabEntries = zButtonToys_FindTabBounds()
|
||||
if not tabOffset or not tabEntries or tabEntries <= 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local spellIds = {}
|
||||
local bookType = BOOKTYPE_SPELL or "spell"
|
||||
local maxIndex = tabOffset + tabEntries
|
||||
for spellIndex = tabOffset + 1, maxIndex do
|
||||
local spellName = GetSpellName(spellIndex, bookType)
|
||||
if spellName and spellName ~= "" then
|
||||
table.insert(spellIds, spellIndex)
|
||||
end
|
||||
end
|
||||
return spellIds
|
||||
end
|
||||
|
||||
local function zButtonToys_ApplySpellIds(spellIds)
|
||||
if not zButtonToys then
|
||||
return 0
|
||||
end
|
||||
|
||||
local parent = zButtonToys
|
||||
local childCount = parent.count or ZHUNTER_TOYS_BUTTON_MAX
|
||||
|
||||
for i = 1, childCount do
|
||||
local child = getglobal("zButtonToys" .. i)
|
||||
if child then
|
||||
child:Hide()
|
||||
child.id = nil
|
||||
child.icon = nil
|
||||
child.isspell = nil
|
||||
end
|
||||
end
|
||||
|
||||
local found = 0
|
||||
for i = 1, table.getn(spellIds) do
|
||||
if found >= childCount then
|
||||
break
|
||||
end
|
||||
local spellId = spellIds[i]
|
||||
if spellId then
|
||||
found = found + 1
|
||||
local child = getglobal("zButtonToys" .. found)
|
||||
if child then
|
||||
child.id = spellId
|
||||
child.isspell = 1
|
||||
ZSpellButton_UpdateButton(child)
|
||||
child:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if found > 0 then
|
||||
parent.id = spellIds[1]
|
||||
parent.isspell = 1
|
||||
ZSpellButton_UpdateButton(parent)
|
||||
parent:Enable()
|
||||
parent:Show()
|
||||
else
|
||||
parent.id = nil
|
||||
parent:Hide()
|
||||
end
|
||||
|
||||
return found
|
||||
end
|
||||
|
||||
local function zButtonToys_RefreshSpells()
|
||||
if not zButtonToys then
|
||||
return 0
|
||||
end
|
||||
local saved = zButtonToys_GetSaved()
|
||||
local spellIds = zButtonToys_CollectTabSpellIds()
|
||||
local spellNames = {}
|
||||
local bookType = BOOKTYPE_SPELL or "spell"
|
||||
for i = 1, table.getn(spellIds) do
|
||||
local n = GetSpellName(spellIds[i], bookType)
|
||||
if n and n ~= "" then
|
||||
table.insert(spellNames, n)
|
||||
end
|
||||
end
|
||||
saved["spellIds"] = spellIds
|
||||
saved["spells"] = spellNames
|
||||
zButtonToys.spells = spellNames
|
||||
zButtonToys.found = zButtonToys_ApplySpellIds(spellIds)
|
||||
zButtonToys_ApplyRuntimeSettings()
|
||||
return zButtonToys.found or 0
|
||||
end
|
||||
|
||||
function zButtonToys_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
function zButtonToys_OnEvent()
|
||||
if event == "VARIABLES_LOADED" then
|
||||
if not zButtonToys then
|
||||
return
|
||||
end
|
||||
if UnitClass("player") ~= ZHUNTER_HUNTER then
|
||||
zButtonToys:UnregisterAllEvents()
|
||||
zButtonToys:Hide()
|
||||
return
|
||||
end
|
||||
zButtonToys_CreateButtons()
|
||||
zButtonToysAdjustment = CreateFrame("Frame", "zButtonToysAdjustment")
|
||||
zButtonToysAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonToysAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonToysAdjustment:SetScript("OnEvent", zButtonToysAdjustment_OnEvent)
|
||||
zButtonToys_SetupSizeAndPosition()
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonToys_CreateButtons()
|
||||
zButtonToys_EnsureConfig()
|
||||
|
||||
if not zButtonToys._mthChildrenCreated then
|
||||
ZSpellButton_CreateChildren(zButtonToys, "zButtonToys", ZHUNTER_TOYS_BUTTON_MAX)
|
||||
zButtonToys._mthChildrenCreated = 1
|
||||
end
|
||||
|
||||
zButtonToys_RefreshSpells()
|
||||
end
|
||||
|
||||
function zButtonToys_SetupSizeAndPosition()
|
||||
local saved = zButtonToys_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonToys and zButtonToys.Hide then
|
||||
zButtonToys:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
local displayCount = zButtonToys.found or 0
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
end
|
||||
ZSpellButton_SetSize(zButtonToys, saved["parent"]["size"])
|
||||
ZSpellButton_SetSize(zButtonToys, saved["children"]["size"], 1)
|
||||
ZSpellButton_SetExpandDirection(zButtonToys, saved["firstbutton"])
|
||||
ZSpellButton_ArrangeChildren(zButtonToys, saved["rows"],
|
||||
displayCount, saved["horizontal"],
|
||||
saved["vertical"])
|
||||
end
|
||||
|
||||
function zButtonToys_Reset()
|
||||
local currentRoot = zButtonToys_GetRoot()
|
||||
currentRoot["zButtonToys"] = {}
|
||||
local saved = zButtonToys_GetSaved()
|
||||
saved["spells"] = {}
|
||||
saved["rows"] = 1
|
||||
saved["horizontal"] = nil
|
||||
saved["vertical"] = nil
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
saved["enabled"] = 1
|
||||
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
|
||||
zButtonToys_EnsureConfig()
|
||||
end
|
||||
|
||||
function zButtonToysAdjustment_OnEvent()
|
||||
if not zButtonToys then
|
||||
return
|
||||
end
|
||||
zButtonToys_RefreshSpells()
|
||||
zButtonToys_SetupSizeAndPosition()
|
||||
if GameTooltip:IsOwned(zButtonToys) then
|
||||
ZSpellButtonParent_OnEnter(zButtonToys)
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonToys_KeyBinding(index)
|
||||
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local button
|
||||
if index then
|
||||
button = getglobal("zButtonToys"..index)
|
||||
else
|
||||
button = zButtonToys
|
||||
end
|
||||
if button and button.id then
|
||||
CastSpell(button.id, "spell")
|
||||
if zButtonToys.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(zButtonToys, false)
|
||||
elseif zButtonToys.children then
|
||||
zButtonToys.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_zButtonToys1 = "/ZToys"
|
||||
SlashCmdList["zButtonToys"] = function(msg)
|
||||
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Toys button is disabled while module 'zhunter' is disabled.") then
|
||||
return
|
||||
end
|
||||
if msg == "reset" then
|
||||
zButtonToys_Reset()
|
||||
zButtonToys:ClearAllPoints()
|
||||
zButtonToys:SetPoint("TOP", UIParent, "TOP", 0, -518)
|
||||
zButtonToys_RefreshSpells()
|
||||
zButtonToys_SetupSizeAndPosition()
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"reset\"")
|
||||
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="zButtonToysFrame">
|
||||
</Frame>
|
||||
<CheckButton name="zButtonToys" inherits="ZSpellButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="-240"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</CheckButton>
|
||||
</Ui>
|
||||
@@ -0,0 +1,260 @@
|
||||
local function zButtonTrack_GetRoot()
|
||||
return MTH_ZH_GetSavedRoot()
|
||||
end
|
||||
|
||||
local root = zButtonTrack_GetRoot()
|
||||
if not root["zButtonTrack"] then
|
||||
root["zButtonTrack"] = {}
|
||||
root["zButtonTrack"]["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
|
||||
root["zButtonTrack"]["rows"] = 1
|
||||
root["zButtonTrack"]["horizontal"] = nil
|
||||
root["zButtonTrack"]["vertical"] = nil
|
||||
root["zButtonTrack"]["firstbutton"] = "RIGHT"
|
||||
root["zButtonTrack"]["enabled"] = 1
|
||||
root["zButtonTrack"]["tooltip"] = 1
|
||||
root["zButtonTrack"]["parent"] = {}
|
||||
root["zButtonTrack"]["parent"]["size"] = 36
|
||||
root["zButtonTrack"]["parent"]["hide"] = nil
|
||||
root["zButtonTrack"]["parent"]["circle"] = 1
|
||||
root["zButtonTrack"]["children"] = {}
|
||||
root["zButtonTrack"]["children"]["size"] = 36
|
||||
root["zButtonTrack"]["children"]["hideonclick"] = 1
|
||||
end
|
||||
|
||||
ZHunterMod_Track_Spells = {
|
||||
ZHUNTER_TRACK_HIDDEN,
|
||||
ZHUNTER_TRACK_HUMANOIDS,
|
||||
ZHUNTER_TRACK_UNDEAD,
|
||||
ZHUNTER_TRACK_BEASTS,
|
||||
ZHUNTER_TRACK_DEMONS,
|
||||
ZHUNTER_TRACK_ELEMENTALS,
|
||||
ZHUNTER_TRACK_DRAGONKIN,
|
||||
ZHUNTER_TRACK_GIANTS,
|
||||
ZHUNTER_TRACK_MINERALS,
|
||||
ZHUNTER_TRACK_HERBS,
|
||||
ZHUNTER_TRACK_TREASURE
|
||||
}
|
||||
|
||||
local ZHUNTER_TRACK_MAX = table.getn(ZHunterMod_Track_Spells)
|
||||
|
||||
local function zButtonTrack_GetSaved()
|
||||
local currentRoot = zButtonTrack_GetRoot()
|
||||
if not currentRoot["zButtonTrack"] then
|
||||
currentRoot["zButtonTrack"] = {}
|
||||
end
|
||||
return currentRoot["zButtonTrack"]
|
||||
end
|
||||
|
||||
local function zButtonTrack_EnsureConfig()
|
||||
local saved = zButtonTrack_GetSaved()
|
||||
saved["count"] = nil
|
||||
if saved["rows"] == nil then
|
||||
saved["rows"] = 1
|
||||
end
|
||||
if saved["firstbutton"] == nil then
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
end
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = 1
|
||||
end
|
||||
if saved["tooltip"] == nil then
|
||||
saved["tooltip"] = 1
|
||||
end
|
||||
if not saved["parent"] then
|
||||
saved["parent"] = {}
|
||||
end
|
||||
if saved["parent"]["size"] == nil then
|
||||
saved["parent"]["size"] = 36
|
||||
end
|
||||
if saved["parent"]["circle"] == nil then
|
||||
saved["parent"]["circle"] = 1
|
||||
end
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
end
|
||||
if saved["children"]["size"] == nil then
|
||||
saved["children"]["size"] = 36
|
||||
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
|
||||
for i = 1, ZHUNTER_TRACK_MAX do
|
||||
if not tonumber(saved["spells"][i]) then
|
||||
saved["spells"][i] = i
|
||||
end
|
||||
if saved["visible"][i] == nil then
|
||||
saved["visible"][i] = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonTrack_ApplyRuntimeSettings()
|
||||
if not zButtonTrack then
|
||||
return
|
||||
end
|
||||
local saved = zButtonTrack_GetSaved()
|
||||
zButtonTrack.tooltip = saved["tooltip"] and true or false
|
||||
zButtonTrack.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
function zButtonTrack_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
function zButtonTrack_OnEvent()
|
||||
if event == "VARIABLES_LOADED" then
|
||||
if not zButtonTrack then
|
||||
return
|
||||
end
|
||||
if UnitClass("player") ~= ZHUNTER_HUNTER then
|
||||
zButtonTrack:UnregisterAllEvents()
|
||||
zButtonTrack:Hide()
|
||||
return
|
||||
end
|
||||
zButtonTrack_CreateButtons()
|
||||
zButtonTrackAdjustment = CreateFrame("Frame", "zButtonTrackAdjustment")
|
||||
zButtonTrackAdjustment:RegisterEvent("PLAYER_AURAS_CHANGED")
|
||||
zButtonTrackAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonTrackAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonTrackAdjustment:RegisterEvent("CHARACTER_POINTS_CHANGED")
|
||||
zButtonTrackAdjustment:SetScript("OnEvent", zButtonTrackAdjustment_OnEvent)
|
||||
zButtonTrack_SetupSizeAndPosition()
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonTrack_CreateButtons()
|
||||
zButtonTrack_EnsureConfig()
|
||||
local saved = zButtonTrack_GetSaved()
|
||||
|
||||
ZSpellButton_CreateChildren(zButtonTrack, "zButtonTrack", ZHUNTER_TRACK_MAX)
|
||||
local info = {}
|
||||
local infoIndex = 1
|
||||
for i=1, table.getn(ZHunterMod_Track_Spells) do
|
||||
if not tonumber(saved["spells"][i]) then
|
||||
info = ZHunterMod_Track_Spells
|
||||
saved["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
|
||||
break
|
||||
end
|
||||
local spellIndex = saved["spells"][i]
|
||||
if saved["visible"][spellIndex] ~= false then
|
||||
info[infoIndex] = ZHunterMod_Track_Spells[spellIndex]
|
||||
infoIndex = infoIndex + 1
|
||||
end
|
||||
end
|
||||
zButtonTrack.found = ZSpellButton_SetButtons(zButtonTrack, info)
|
||||
zButtonTrack_ApplyRuntimeSettings()
|
||||
end
|
||||
|
||||
function zButtonTrack_SetupSizeAndPosition()
|
||||
zButtonTrack_EnsureConfig()
|
||||
local saved = zButtonTrack_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonTrack and zButtonTrack.Hide then
|
||||
zButtonTrack:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
local displayCount = zButtonTrack.found or ZHUNTER_TRACK_MAX
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
end
|
||||
ZSpellButton_SetSize(zButtonTrack, saved["parent"]["size"])
|
||||
ZSpellButton_SetSize(zButtonTrack, saved["children"]["size"], 1)
|
||||
ZSpellButton_SetExpandDirection(zButtonTrack, saved["firstbutton"])
|
||||
ZSpellButton_ArrangeChildren(zButtonTrack, saved["rows"],
|
||||
displayCount, saved["horizontal"],
|
||||
saved["vertical"])
|
||||
end
|
||||
|
||||
function zButtonTrack_Reset()
|
||||
local currentRoot = zButtonTrack_GetRoot()
|
||||
currentRoot["zButtonTrack"] = {}
|
||||
local saved = zButtonTrack_GetSaved()
|
||||
saved["spells"] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
|
||||
saved["rows"] = 1
|
||||
saved["horizontal"] = nil
|
||||
saved["vertical"] = nil
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
saved["enabled"] = 1
|
||||
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
|
||||
saved["visible"] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
|
||||
zButtonTrack_EnsureConfig()
|
||||
end
|
||||
|
||||
function zButtonTrackAdjustment_OnEvent()
|
||||
if not zButtonTrack or not zButtonTrack.count then
|
||||
return
|
||||
end
|
||||
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then
|
||||
zButtonTrack_CreateButtons()
|
||||
zButtonTrack_SetupSizeAndPosition()
|
||||
end
|
||||
if event == "PLAYER_AURAS_CHANGED" or event == "PLAYER_ENTERING_WORLD"
|
||||
or event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then
|
||||
local i = 1
|
||||
local texture = zButtonTrack1IconTexture:GetTexture()
|
||||
local buff = GetTrackingTexture()
|
||||
if texture == buff and zButtonTrack2.id then
|
||||
zButtonTrack.id = zButtonTrack2.id
|
||||
else
|
||||
zButtonTrack.id = zButtonTrack1.id
|
||||
end
|
||||
ZSpellButton_UpdateButton(zButtonTrack)
|
||||
ZSpellButton_UpdateCooldown(zButtonTrack)
|
||||
if GameTooltip:IsOwned(zButtonTrack) then
|
||||
ZSpellButtonParent_OnEnter(zButtonTrack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonTrack_KeyBinding(index)
|
||||
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local button
|
||||
if index then
|
||||
button = getglobal("zButtonTrack"..index)
|
||||
else
|
||||
button = zButtonTrack
|
||||
end
|
||||
if button.id then
|
||||
CastSpell(button.id, "spell")
|
||||
if zButtonTrack.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(zButtonTrack, false)
|
||||
elseif zButtonTrack.children then
|
||||
zButtonTrack.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_zButtonTrack1 = "/ZTrack"
|
||||
SlashCmdList["zButtonTrack"] = function(msg)
|
||||
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Track button is disabled while module 'zhunter' is disabled.") then
|
||||
return
|
||||
end
|
||||
if msg == "reset" then
|
||||
zButtonTrack_Reset()
|
||||
zButtonTrack:ClearAllPoints()
|
||||
zButtonTrack:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
|
||||
elseif msg == "options" then
|
||||
MTH_OpenOptions("Track")
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
|
||||
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="zButtonTrackFrame">
|
||||
</Frame>
|
||||
<CheckButton name="zButtonTrack" inherits="ZSpellButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</CheckButton>
|
||||
</Ui>
|
||||
@@ -0,0 +1,262 @@
|
||||
local function zButtonTrap_GetRoot()
|
||||
return MTH_ZH_GetSavedRoot()
|
||||
end
|
||||
|
||||
local root = zButtonTrap_GetRoot()
|
||||
if not root["zButtonTrap"] then
|
||||
root["zButtonTrap"] = {}
|
||||
root["zButtonTrap"]["spells"] = {1, 2, 3, 4}
|
||||
root["zButtonTrap"]["rows"] = 1
|
||||
root["zButtonTrap"]["horizontal"] = nil
|
||||
root["zButtonTrap"]["vertical"] = nil
|
||||
root["zButtonTrap"]["firstbutton"] = "RIGHT"
|
||||
root["zButtonTrap"]["enabled"] = 1
|
||||
root["zButtonTrap"]["tooltip"] = 1
|
||||
root["zButtonTrap"]["parent"] = {}
|
||||
root["zButtonTrap"]["parent"]["size"] = 36
|
||||
root["zButtonTrap"]["parent"]["hide"] = nil
|
||||
root["zButtonTrap"]["parent"]["circle"] = 1
|
||||
root["zButtonTrap"]["children"] = {}
|
||||
root["zButtonTrap"]["children"]["size"] = 36
|
||||
root["zButtonTrap"]["children"]["hideonclick"] = 1
|
||||
end
|
||||
|
||||
ZHunterMod_Trap_Spells = {
|
||||
ZHUNTER_TRAP_FREEZING,
|
||||
ZHUNTER_TRAP_FROST,
|
||||
ZHUNTER_TRAP_IMMOLATION,
|
||||
ZHUNTER_TRAP_EXPLOSIVE
|
||||
}
|
||||
|
||||
local ZHUNTER_TRAP_MAX = table.getn(ZHunterMod_Trap_Spells)
|
||||
|
||||
local function zButtonTrap_GetSaved()
|
||||
local currentRoot = zButtonTrap_GetRoot()
|
||||
if not currentRoot["zButtonTrap"] then
|
||||
currentRoot["zButtonTrap"] = {}
|
||||
end
|
||||
return currentRoot["zButtonTrap"]
|
||||
end
|
||||
|
||||
local function zButtonTrap_EnsureConfig()
|
||||
local saved = zButtonTrap_GetSaved()
|
||||
saved["count"] = nil
|
||||
if saved["rows"] == nil then
|
||||
saved["rows"] = 1
|
||||
end
|
||||
if saved["firstbutton"] == nil then
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
end
|
||||
if saved["enabled"] == nil then
|
||||
saved["enabled"] = 1
|
||||
end
|
||||
if saved["tooltip"] == nil then
|
||||
saved["tooltip"] = 1
|
||||
end
|
||||
if not saved["parent"] then
|
||||
saved["parent"] = {}
|
||||
end
|
||||
if saved["parent"]["size"] == nil then
|
||||
saved["parent"]["size"] = 36
|
||||
end
|
||||
if saved["parent"]["circle"] == nil then
|
||||
saved["parent"]["circle"] = 1
|
||||
end
|
||||
if not saved["children"] then
|
||||
saved["children"] = {}
|
||||
end
|
||||
if saved["children"]["size"] == nil then
|
||||
saved["children"]["size"] = 36
|
||||
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
|
||||
for i = 1, ZHUNTER_TRAP_MAX do
|
||||
if not tonumber(saved["spells"][i]) then
|
||||
saved["spells"][i] = i
|
||||
end
|
||||
if saved["visible"][i] == nil then
|
||||
saved["visible"][i] = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function zButtonTrap_ApplyRuntimeSettings()
|
||||
if not zButtonTrap then
|
||||
return
|
||||
end
|
||||
local saved = zButtonTrap_GetSaved()
|
||||
zButtonTrap.tooltip = saved["tooltip"] and true or false
|
||||
zButtonTrap.hideonclick = saved["children"] and saved["children"]["hideonclick"] and true or false
|
||||
end
|
||||
|
||||
function zButtonTrap_OnLoad()
|
||||
this:RegisterEvent("VARIABLES_LOADED")
|
||||
end
|
||||
|
||||
function zButtonTrap_OnEvent()
|
||||
if event == "VARIABLES_LOADED" then
|
||||
if not zButtonTrap then
|
||||
return
|
||||
end
|
||||
if UnitClass("player") ~= ZHUNTER_HUNTER then
|
||||
zButtonTrap:UnregisterAllEvents()
|
||||
zButtonTrap:Hide()
|
||||
return
|
||||
end
|
||||
zButtonTrap_CreateButtons()
|
||||
zButtonTrapAdjustment = CreateFrame("Frame", "zButtonTrapAdjustment")
|
||||
zButtonTrapAdjustment:RegisterEvent("PLAYER_REGEN_ENABLED")
|
||||
zButtonTrapAdjustment:RegisterEvent("PLAYER_REGEN_DISABLED")
|
||||
zButtonTrapAdjustment:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
zButtonTrapAdjustment:RegisterEvent("SPELLS_CHANGED")
|
||||
zButtonTrapAdjustment:RegisterEvent("CHARACTER_POINTS_CHANGED")
|
||||
zButtonTrapAdjustment:SetScript("OnEvent", zButtonTrapAdjustment_OnEvent)
|
||||
zButtonTrap_SetupSizeAndPosition()
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonTrap_CreateButtons()
|
||||
zButtonTrap_EnsureConfig()
|
||||
local saved = zButtonTrap_GetSaved()
|
||||
|
||||
ZSpellButton_CreateChildren(zButtonTrap, "zButtonTrap", ZHUNTER_TRAP_MAX)
|
||||
local info = {}
|
||||
local infoIndex = 1
|
||||
for i=1, table.getn(ZHunterMod_Trap_Spells) do
|
||||
if not tonumber(saved["spells"][i]) then
|
||||
info = ZHunterMod_Trap_Spells
|
||||
saved["spells"] = {1, 2, 3, 4}
|
||||
break
|
||||
end
|
||||
local spellIndex = saved["spells"][i]
|
||||
if saved["visible"][spellIndex] ~= false then
|
||||
info[infoIndex] = ZHunterMod_Trap_Spells[spellIndex]
|
||||
infoIndex = infoIndex + 1
|
||||
end
|
||||
end
|
||||
zButtonTrap.found = ZSpellButton_SetButtons(zButtonTrap, info)
|
||||
zButtonTrap_ApplyRuntimeSettings()
|
||||
end
|
||||
|
||||
function zButtonTrap_SetupSizeAndPosition()
|
||||
zButtonTrap_EnsureConfig()
|
||||
local saved = zButtonTrap_GetSaved()
|
||||
if saved["enabled"] == false or saved["enabled"] == 0 then
|
||||
if zButtonTrap and zButtonTrap.Hide then
|
||||
zButtonTrap:Hide()
|
||||
end
|
||||
return
|
||||
end
|
||||
local displayCount = zButtonTrap.found or ZHUNTER_TRAP_MAX
|
||||
if displayCount < 0 then
|
||||
displayCount = 0
|
||||
end
|
||||
ZSpellButton_SetSize(zButtonTrap, saved["parent"]["size"])
|
||||
ZSpellButton_SetSize(zButtonTrap, saved["children"]["size"], 1)
|
||||
ZSpellButton_SetExpandDirection(zButtonTrap, saved["firstbutton"])
|
||||
ZSpellButton_ArrangeChildren(zButtonTrap, saved["rows"],
|
||||
displayCount, saved["horizontal"],
|
||||
saved["vertical"])
|
||||
end
|
||||
|
||||
function zButtonTrap_Reset()
|
||||
local currentRoot = zButtonTrap_GetRoot()
|
||||
currentRoot["zButtonTrap"] = {}
|
||||
local saved = zButtonTrap_GetSaved()
|
||||
saved["spells"] = {1, 2, 3, 4}
|
||||
saved["rows"] = 1
|
||||
saved["horizontal"] = nil
|
||||
saved["vertical"] = nil
|
||||
saved["firstbutton"] = "RIGHT"
|
||||
saved["enabled"] = 1
|
||||
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
|
||||
saved["visible"] = {1, 1, 1, 1}
|
||||
zButtonTrap_EnsureConfig()
|
||||
end
|
||||
|
||||
function zButtonTrapAdjustment_OnEvent()
|
||||
if not zButtonTrap or not zButtonTrap.count then
|
||||
return
|
||||
end
|
||||
if event == "SPELLS_CHANGED" or event == "CHARACTER_POINTS_CHANGED" then
|
||||
zButtonTrap_CreateButtons()
|
||||
zButtonTrap_SetupSizeAndPosition()
|
||||
end
|
||||
local nextbutton
|
||||
local button
|
||||
local combat = event == "PLAYER_REGEN_DISABLED"
|
||||
for i=1, zButtonTrap.count do
|
||||
button = getglobal(zButtonTrap.name..i)
|
||||
button.customcolor = nil
|
||||
if button.id then
|
||||
if not nextbutton then
|
||||
nextbutton = button
|
||||
end
|
||||
if combat then
|
||||
button.icontexture:SetVertexColor(0.4, 0.4, 0.4)
|
||||
button.customcolor = 1
|
||||
else
|
||||
button.icontexture:SetVertexColor(1.0, 1.0, 1.0)
|
||||
end
|
||||
end
|
||||
end
|
||||
zButtonTrap.id = nextbutton and nextbutton.id or zButtonTrap1.id
|
||||
ZSpellButton_UpdateButton(zButtonTrap)
|
||||
ZSpellButton_UpdateCooldown(zButtonTrap)
|
||||
if GameTooltip:IsOwned(zButtonTrap) then
|
||||
ZSpellButtonParent_OnEnter(zButtonTrap)
|
||||
end
|
||||
end
|
||||
|
||||
function zButtonTrap_KeyBinding(index)
|
||||
if MTH_ZH_IsModuleEnabled and not MTH_ZH_IsModuleEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local button
|
||||
if index then
|
||||
button = getglobal("zButtonTrap"..index)
|
||||
else
|
||||
button = zButtonTrap
|
||||
end
|
||||
if button.id then
|
||||
CastSpell(button.id, "spell")
|
||||
if zButtonTrap.hideonclick then
|
||||
if type(ZSpellButton_SetChildrenExpanded) == "function" then
|
||||
ZSpellButton_SetChildrenExpanded(zButtonTrap, false)
|
||||
elseif zButtonTrap.children then
|
||||
zButtonTrap.children:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_zButtonTrap1 = "/ZTrap"
|
||||
SlashCmdList["zButtonTrap"] = function(msg)
|
||||
if MTH_ZH_HandleDisabledSlash and MTH_ZH_HandleDisabledSlash("Trap button is disabled while module 'zhunter' is disabled.") then
|
||||
return
|
||||
end
|
||||
if msg == "reset" then
|
||||
zButtonTrap_Reset()
|
||||
zButtonTrap:ClearAllPoints()
|
||||
zButtonTrap:SetPoint("CENTER", UIParent, "CENTER", 60, 0)
|
||||
elseif msg == "options" then
|
||||
MTH_OpenOptions("Trap")
|
||||
else
|
||||
MTH_ZH_Print("Possible Commands: \"options\", \"reset\"")
|
||||
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="zButtonTrapFrame">
|
||||
</Frame>
|
||||
<CheckButton name="zButtonTrap" inherits="ZSpellButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="UIParent" relativePoint="CENTER">
|
||||
<Offset>
|
||||
<AbsDimension x="60" y="0"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
</CheckButton>
|
||||
</Ui>
|
||||
Reference in New Issue
Block a user