Initial import of shootyepgp 2.0
80% rewrite of shootyepgp 1.x compatible with shootyepgp 1.x
This commit is contained in:
@@ -0,0 +1,982 @@
|
||||
--[[
|
||||
Name: AceAddon-2.0
|
||||
Revision: $Rev: 14832 $
|
||||
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/AceAddon-2.0
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceAddon-2.0
|
||||
Description: Base for all Ace addons to inherit from.
|
||||
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0, (optional) AceConsole-2.0
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceAddon-2.0"
|
||||
local MINOR_VERSION = "$Revision: 14832 $"
|
||||
|
||||
-- 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 not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0.") end
|
||||
|
||||
-- Localization
|
||||
local STANDBY, TITLE, NOTES, VERSION, AUTHOR, DATE, CATEGORY, EMAIL, WEBSITE, CATEGORIES, ABOUT, PRINT_ADDON_INFO
|
||||
if GetLocale() == "deDE" then
|
||||
STANDBY = "|cffff5050(Standby)|r" -- capitalized
|
||||
|
||||
TITLE = "Titel"
|
||||
NOTES = "Anmerkung"
|
||||
VERSION = "Version"
|
||||
AUTHOR = "Autor"
|
||||
DATE = "Datum"
|
||||
CATEGORY = "Kategorie"
|
||||
EMAIL = "E-mail"
|
||||
WEBSITE = "Webseite"
|
||||
|
||||
ABOUT = "\195\188ber"
|
||||
PRINT_ADDON_INFO = "Gibt Addondaten aus"
|
||||
|
||||
CATEGORIES = {
|
||||
["Action Bars"] = "Aktionsleisten",
|
||||
["Auction"] = "Auktion",
|
||||
["Audio"] = "Audio",
|
||||
["Battlegrounds/PvP"] = "Schlachtfeld/PvP",
|
||||
["Buffs"] = "Buffs",
|
||||
["Chat/Communication"] = "Chat/Kommunikation",
|
||||
["Druid"] = "Druide",
|
||||
["Hunter"] = "Jäger",
|
||||
["Mage"] = "Magier",
|
||||
["Paladin"] = "Paladin",
|
||||
["Priest"] = "Priester",
|
||||
["Rogue"] = "Schurke",
|
||||
["Shaman"] = "Schamane",
|
||||
["Warlock"] = "Hexenmeister",
|
||||
["Warrior"] = "Krieger",
|
||||
["Healer"] = "Heiler",
|
||||
["Tank"] = "Tank", -- noone use "Brecher"...
|
||||
["Caster"] = "Caster",
|
||||
["Combat"] = "Kampf",
|
||||
["Compilations"] = "Compilations", -- whats that o_O
|
||||
["Data Export"] = "Datenexport",
|
||||
["Development Tools"] = "Entwicklungs Tools",
|
||||
["Guild"] = "Gilde",
|
||||
["Frame Modification"] = "Frame Modifikation",
|
||||
["Interface Enhancements"] = "Interface Verbesserungen",
|
||||
["Inventory"] = "Inventar",
|
||||
["Library"] = "Library",
|
||||
["Map"] = "Map",
|
||||
["Mail"] = "Mail",
|
||||
["Miscellaneous"] = "Diverses",
|
||||
["Quest"] = "Quest",
|
||||
["Raid"] = "Schlachtzug",
|
||||
["Tradeskill"] = "Handelsf\195\164higkeit",
|
||||
["UnitFrame"] = "UnitFrame",
|
||||
}
|
||||
elseif GetLocale() == "frFR" then
|
||||
STANDBY = "|cffff5050(attente)|r"
|
||||
|
||||
TITLE = "Titre"
|
||||
NOTES = "Notes"
|
||||
VERSION = "Version"
|
||||
AUTHOR = "Auteur"
|
||||
DATE = "Date"
|
||||
CATEGORY = "Cat\195\169gorie"
|
||||
EMAIL = "E-mail"
|
||||
WEBSITE = "Site web"
|
||||
|
||||
ABOUT = "A propos"
|
||||
PRINT_ADDON_INFO = "Afficher les informations sur l'addon"
|
||||
|
||||
CATEGORIES = {
|
||||
["Action Bars"] = "Barres d'action",
|
||||
["Auction"] = "H\195\180tel des ventes",
|
||||
["Audio"] = "Audio",
|
||||
["Battlegrounds/PvP"] = "Champs de bataille/JcJ",
|
||||
["Buffs"] = "Buffs",
|
||||
["Chat/Communication"] = "Chat/Communication",
|
||||
["Druid"] = "Druide",
|
||||
["Hunter"] = "Chasseur",
|
||||
["Mage"] = "Mage",
|
||||
["Paladin"] = "Paladin",
|
||||
["Priest"] = "Pr\195\170tre",
|
||||
["Rogue"] = "Voleur",
|
||||
["Shaman"] = "Chaman",
|
||||
["Warlock"] = "D\195\169moniste",
|
||||
["Warrior"] = "Guerrier",
|
||||
["Healer"] = "Soigneur",
|
||||
["Tank"] = "Tank",
|
||||
["Caster"] = "Casteur",
|
||||
["Combat"] = "Combat",
|
||||
["Compilations"] = "Compilations",
|
||||
["Data Export"] = "Exportation de donn\195\169es",
|
||||
["Development Tools"] = "Outils de d\195\169veloppement",
|
||||
["Guild"] = "Guilde",
|
||||
["Frame Modification"] = "Modification des fen\195\170tres",
|
||||
["Interface Enhancements"] = "Am\195\169liorations de l'interface",
|
||||
["Inventory"] = "Inventaire",
|
||||
["Library"] = "Biblioth\195\168ques",
|
||||
["Map"] = "Carte",
|
||||
["Mail"] = "Courrier",
|
||||
["Miscellaneous"] = "Divers",
|
||||
["Quest"] = "Qu\195\170tes",
|
||||
["Raid"] = "Raid",
|
||||
["Tradeskill"] = "M\195\169tiers",
|
||||
["UnitFrame"] = "Fen\195\170tres d'unit\195\169",
|
||||
}
|
||||
elseif GetLocale() == "koKR" then
|
||||
STANDBY = "|cffff5050(사용가능)|r"
|
||||
|
||||
TITLE = "ì œëª©"
|
||||
NOTES = "노트"
|
||||
VERSION = "ë²„ì „"
|
||||
AUTHOR = "ì €ìž‘ìž�"
|
||||
DATE = "ë‚ ì§œ"
|
||||
CATEGORY = "분류"
|
||||
EMAIL = "E-mail"
|
||||
WEBSITE = "웹사�트"
|
||||
|
||||
ABOUT = "ì •ë³´"
|
||||
PRINT_ADDON_INFO = "ì• ë“œì˜¨ ì •ë³´ ì¶œë ¥"
|
||||
|
||||
CATEGORIES = {
|
||||
["Action Bars"] = "액션바",
|
||||
["Auction"] = "경매",
|
||||
["Audio"] = "�향",
|
||||
["Battlegrounds/PvP"] = "ì „ìž¥/PvP",
|
||||
["Buffs"] = "버프",
|
||||
["Chat/Communication"] = "대화/�사소통",
|
||||
["Druid"] = "드루�드",
|
||||
["Hunter"] = "사냥꾼",
|
||||
["Mage"] = "마법사",
|
||||
["Paladin"] = "성기사",
|
||||
["Priest"] = "ì‚¬ì œ",
|
||||
["Rogue"] = "ë�„ì �",
|
||||
["Shaman"] = "ì£¼ìˆ ì‚¬",
|
||||
["Warlock"] = "�마법사",
|
||||
["Warrior"] = "ì „ì‚¬",
|
||||
["Healer"] = "�러",
|
||||
["Tank"] = "탱커",
|
||||
["Caster"] = "�스터",
|
||||
["Combat"] = "ì „íˆ¬",
|
||||
["Compilations"] = "복합",
|
||||
["Data Export"] = "ìž�료 ì¶œë ¥",
|
||||
["Development Tools"] = "개발 �구",
|
||||
["Guild"] = "길드",
|
||||
["Frame Modification"] = "구조 변경",
|
||||
["Interface Enhancements"] = "�터페�스 강화",
|
||||
["Inventory"] = "ì�¸ë²¤í† 리",
|
||||
["Library"] = "��브러리",
|
||||
["Map"] = "지�",
|
||||
["Mail"] = "우편",
|
||||
["Miscellaneous"] = "기타",
|
||||
["Quest"] = "퀘스트",
|
||||
["Raid"] = "공격대",
|
||||
["Tradeskill"] = "ì „ë¬¸ê¸°ìˆ ",
|
||||
["UnitFrame"] = "ìœ ë‹› í”„ë ˆìž„",
|
||||
}
|
||||
elseif GetLocale() == "zhTW" then
|
||||
STANDBY = "|cffff5050(待命)|r"
|
||||
|
||||
TITLE = "標題"
|
||||
NOTES = "註記"
|
||||
VERSION = "版本"
|
||||
AUTHOR = "作者"
|
||||
DATE = "日期"
|
||||
CATEGORY = "類別"
|
||||
EMAIL = "E-mail"
|
||||
WEBSITE = "網站"
|
||||
|
||||
ABOUT = "關於"
|
||||
PRINT_ADDON_INFO = "顯示�件資訊"
|
||||
|
||||
CATEGORIES = {
|
||||
["Action Bars"] = "動作列",
|
||||
["Auction"] = "�賣",
|
||||
["Audio"] = "音樂",
|
||||
["Battlegrounds/PvP"] = "æˆ°å ´/PvP",
|
||||
["Buffs"] = "增益",
|
||||
["Chat/Communication"] = "�天/通訊",
|
||||
["Druid"] = "å¾·é¯ä¼Š",
|
||||
["Hunter"] = "�人",
|
||||
["Mage"] = "法師",
|
||||
["Paladin"] = "�騎士",
|
||||
["Priest"] = "牧師",
|
||||
["Rogue"] = "盜賊",
|
||||
["Shaman"] = "薩滿",
|
||||
["Warlock"] = "術士",
|
||||
["Warrior"] = "戰士",
|
||||
["Healer"] = "治療者",
|
||||
["Tank"] = "�克",
|
||||
["Caster"] = "施法者",
|
||||
["Combat"] = "戰鬥",
|
||||
["Compilations"] = "編輯",
|
||||
["Data Export"] = "資料匯出",
|
||||
["Development Tools"] = "開發工具",
|
||||
["Guild"] = "公會",
|
||||
["Frame Modification"] = "框架修改",
|
||||
["Interface Enhancements"] = "介�增強",
|
||||
["Inventory"] = "背包",
|
||||
["Library"] = "資料庫",
|
||||
["Map"] = "地圖",
|
||||
["Mail"] = "郵件",
|
||||
["Miscellaneous"] = "綜�",
|
||||
["Quest"] = "任務",
|
||||
["Raid"] = "團隊",
|
||||
["Tradeskill"] = "å•†æ¥æŠ€èƒ½",
|
||||
["UnitFrame"] = "單�框架",
|
||||
}
|
||||
elseif GetLocale() == "zhCN" then
|
||||
STANDBY = "|cffff5050(\230\154\130\230\140\130)|r"
|
||||
|
||||
TITLE = "\230\160\135\233\162\152"
|
||||
NOTES = "\233\153\132\230\179\168"
|
||||
VERSION = "\231\137\136\230\156\172"
|
||||
AUTHOR = "\228\189\156\232\128\133"
|
||||
DATE = "\230\151\165\230\156\159"
|
||||
CATEGORY = "\229\136\134\231\177\187"
|
||||
EMAIL = "\231\148\181\229\173\144\233\130\174\228\187\182"
|
||||
WEBSITE = "\231\189\145\231\171\153"
|
||||
|
||||
ABOUT = "\229\133\179\228\186\142"
|
||||
PRINT_ADDON_INFO = "\229\141\176\229\136\151\229\135\186\230\143\146\228\187\182\228\191\161\230\129\175"
|
||||
|
||||
CATEGORIES = {
|
||||
["Action Bars"] = "\229\138\168\228\189\156\230\157\161",
|
||||
["Auction"] = "\230\139\141\229\141\150",
|
||||
["Audio"] = "\233\159\179\233\162\145",
|
||||
["Battlegrounds/PvP"] = "\230\136\152\229\156\186/PvP",
|
||||
["Buffs"] = "\229\162\158\231\155\138\233\173\148\230\179\149",
|
||||
["Chat/Communication"] = "\232\129\138\229\164\169/\228\186\164\230\181\129",
|
||||
["Druid"] = "\229\190\183\233\178\129\228\188\138",
|
||||
["Hunter"] = "\231\140\142\228\186\186",
|
||||
["Mage"] = "\230\179\149\229\184\136",
|
||||
["Paladin"] = "\229\156\163\233\170\145\229\163\171",
|
||||
["Priest"] = "\231\137\167\229\184\136",
|
||||
["Rogue"] = "\231\155\151\232\180\188",
|
||||
["Shaman"] = "\232\144\168\230\187\161\231\165\173\229\143\184",
|
||||
["Warlock"] = "\230\156\175\229\163\171",
|
||||
["Warrior"] = "\230\136\152\229\163\171",
|
||||
-- ["Healer"] = "\230\178\187\231\150\151\228\191\157\233\154\156",
|
||||
-- ["Tank"] = "\232\191\145\230\136\152\230\142\167\229\136\182",
|
||||
-- ["Caster"] = "\232\191\156\231\168\139\232\190\147\229\135\186",
|
||||
["Combat"] = "\230\136\152\230\150\151",
|
||||
["Compilations"] = "\231\188\150\232\175\145",
|
||||
["Data Export"] = "\230\149\176\230\141\174\229\175\188\229\135\186",
|
||||
["Development Tools"] = "\229\188\128\229\143\145\229\183\165\229\133\183",
|
||||
["Guild"] = "\229\133\172\228\188\154",
|
||||
["Frame Modification"] = "\230\161\134\230\158\182\228\191\174\230\148\185",
|
||||
["Interface Enhancements"] = "\231\149\140\233\157\162\229\162\158\229\188\186",
|
||||
["Inventory"] = "\232\131\140\229\140\133",
|
||||
["Library"] = "\229\186\147",
|
||||
["Map"] = "\229\156\176\229\155\190",
|
||||
["Mail"] = "\233\130\174\228\187\182",
|
||||
["Miscellaneous"] = "\230\157\130\233\161\185",
|
||||
["Quest"] = "\228\187\187\229\138\161",
|
||||
["Raid"] = "\229\155\162\233\152\159",
|
||||
["Tradeskill"] = "\229\149\134\228\184\154\230\138\128\232\131\189",
|
||||
["UnitFrame"] = "\229\164\180\229\131\143\230\161\134\230\158\182",
|
||||
}
|
||||
else -- enUS
|
||||
STANDBY = "|cffff5050(standby)|r"
|
||||
|
||||
TITLE = "Title"
|
||||
NOTES = "Notes"
|
||||
VERSION = "Version"
|
||||
AUTHOR = "Author"
|
||||
DATE = "Date"
|
||||
CATEGORY = "Category"
|
||||
EMAIL = "E-mail"
|
||||
WEBSITE = "Website"
|
||||
|
||||
ABOUT = "About"
|
||||
PRINT_ADDON_INFO = "Print out addon info"
|
||||
|
||||
CATEGORIES = {
|
||||
["Action Bars"] = "Action Bars",
|
||||
["Auction"] = "Auction",
|
||||
["Audio"] = "Audio",
|
||||
["Battlegrounds/PvP"] = "Battlegrounds/PvP",
|
||||
["Buffs"] = "Buffs",
|
||||
["Chat/Communication"] = "Chat/Communication",
|
||||
["Druid"] = "Druid",
|
||||
["Hunter"] = "Hunter",
|
||||
["Mage"] = "Mage",
|
||||
["Paladin"] = "Paladin",
|
||||
["Priest"] = "Priest",
|
||||
["Rogue"] = "Rogue",
|
||||
["Shaman"] = "Shaman",
|
||||
["Warlock"] = "Warlock",
|
||||
["Warrior"] = "Warrior",
|
||||
["Healer"] = "Healer",
|
||||
["Tank"] = "Tank",
|
||||
["Caster"] = "Caster",
|
||||
["Combat"] = "Combat",
|
||||
["Compilations"] = "Compilations",
|
||||
["Data Export"] = "Data Export",
|
||||
["Development Tools"] = "Development Tools",
|
||||
["Guild"] = "Guild",
|
||||
["Frame Modification"] = "Frame Modification",
|
||||
["Interface Enhancements"] = "Interface Enhancements",
|
||||
["Inventory"] = "Inventory",
|
||||
["Library"] = "Library",
|
||||
["Map"] = "Map",
|
||||
["Mail"] = "Mail",
|
||||
["Miscellaneous"] = "Miscellaneous",
|
||||
["Quest"] = "Quest",
|
||||
["Raid"] = "Raid",
|
||||
["Tradeskill"] = "Tradeskill",
|
||||
["UnitFrame"] = "UnitFrame",
|
||||
}
|
||||
end
|
||||
|
||||
setmetatable(CATEGORIES, { __index = function(self, key) -- case-insensitive
|
||||
local lowerKey = string.lower(key)
|
||||
for k,v in CATEGORIES do
|
||||
if string.lower(k) == lowerKey then
|
||||
return v
|
||||
end
|
||||
end
|
||||
end })
|
||||
|
||||
-- Create the library object
|
||||
|
||||
local AceOO = AceLibrary("AceOO-2.0")
|
||||
local AceAddon = AceOO.Class()
|
||||
local AceEvent
|
||||
local AceConsole
|
||||
local AceModuleCore
|
||||
|
||||
function AceAddon:ToString()
|
||||
return "AceAddon"
|
||||
end
|
||||
|
||||
local function print(text)
|
||||
DEFAULT_CHAT_FRAME:AddMessage(text)
|
||||
end
|
||||
|
||||
function AceAddon:ADDON_LOADED(name)
|
||||
while table.getn(self.nextAddon) > 0 do
|
||||
local addon = table.remove(self.nextAddon, 1)
|
||||
table.insert(self.addons, addon)
|
||||
if not self.addons[name] then
|
||||
self.addons[name] = addon
|
||||
end
|
||||
self:InitializeAddon(addon, name)
|
||||
end
|
||||
end
|
||||
|
||||
local function RegisterOnEnable(self)
|
||||
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage then -- HACK
|
||||
AceAddon.playerLoginFired = true
|
||||
end
|
||||
if AceAddon.playerLoginFired then
|
||||
AceAddon.addonsStarted[self] = true
|
||||
if (type(self.IsActive) ~= "function" or self:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(self) or AceModuleCore:IsModuleActive(self)) then
|
||||
local current = self.class
|
||||
while true do
|
||||
if current == AceOO.Class then
|
||||
break
|
||||
end
|
||||
if current.mixins then
|
||||
for mixin in pairs(current.mixins) do
|
||||
if type(mixin.OnEmbedEnable) == "function" then
|
||||
mixin:OnEmbedEnable(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
current = current.super
|
||||
end
|
||||
if type(self.OnEnable) == "function" then
|
||||
self:OnEnable()
|
||||
end
|
||||
end
|
||||
else
|
||||
if not AceAddon.addonsToOnEnable then
|
||||
AceAddon.addonsToOnEnable = {}
|
||||
end
|
||||
table.insert(AceAddon.addonsToOnEnable, self)
|
||||
end
|
||||
end
|
||||
|
||||
local function stripSpaces(text)
|
||||
if type(text) == "string" then
|
||||
return (string.gsub(string.gsub(text, "^%s*(.-)%s*$", "%1"), "%s%s+", " "))
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
function AceAddon:InitializeAddon(addon, name)
|
||||
if addon.name == nil then
|
||||
addon.name = name
|
||||
end
|
||||
if GetAddOnMetadata then
|
||||
-- TOC checks
|
||||
if addon.title == nil then
|
||||
addon.title = GetAddOnMetadata(name, "Title")
|
||||
if addon.title then
|
||||
local num = string.find(addon.title, " |cff7fff7f %-Ace2%-|r$")
|
||||
if num then
|
||||
addon.title = string.sub(addon.title, 1, num - 1)
|
||||
end
|
||||
addon.title = stripSpaces(addon.title)
|
||||
end
|
||||
end
|
||||
if addon.notes == nil then
|
||||
addon.notes = GetAddOnMetadata(name, "Notes")
|
||||
addon.notes = stripSpaces(addon.notes)
|
||||
end
|
||||
if addon.version == nil then
|
||||
addon.version = GetAddOnMetadata(name, "Version")
|
||||
if addon.version then
|
||||
if string.find(addon.version, "%$Revision: (%d+) %$") then
|
||||
addon.version = string.gsub(addon.version, "%$Revision: (%d+) %$", "%1")
|
||||
elseif string.find(addon.version, "%$Rev: (%d+) %$") then
|
||||
addon.version = string.gsub(addon.version, "%$Rev: (%d+) %$", "%1")
|
||||
elseif string.find(addon.version, "%$LastChangedRevision: (%d+) %$") then
|
||||
addon.version = string.gsub(addon.version, "%$LastChangedRevision: (%d+) %$", "%1")
|
||||
end
|
||||
end
|
||||
addon.version = stripSpaces(addon.version)
|
||||
end
|
||||
if addon.author == nil then
|
||||
addon.author = GetAddOnMetadata(name, "Author")
|
||||
addon.author = stripSpaces(addon.author)
|
||||
end
|
||||
if addon.date == nil then
|
||||
addon.date = GetAddOnMetadata(name, "X-Date") or GetAddOnMetadata(name, "X-ReleaseDate")
|
||||
if addon.date then
|
||||
if string.find(addon.date, "%$Date: (.-) %$") then
|
||||
addon.date = string.gsub(addon.date, "%$Date: (.-) %$", "%1")
|
||||
elseif string.find(addon.date, "%$LastChangedDate: (.-) %$") then
|
||||
addon.date = string.gsub(addon.date, "%$LastChangedDate: (.-) %$", "%1")
|
||||
end
|
||||
end
|
||||
addon.date = stripSpaces(addon.date)
|
||||
end
|
||||
if addon.category == nil then
|
||||
addon.category = GetAddOnMetadata(name, "X-Category")
|
||||
addon.category = stripSpaces(addon.category)
|
||||
end
|
||||
if addon.email == nil then
|
||||
addon.email = GetAddOnMetadata(name, "X-eMail") or GetAddOnMetadata(name, "X-Email")
|
||||
addon.email = stripSpaces(addon.email)
|
||||
end
|
||||
if addon.website == nil then
|
||||
addon.website = GetAddOnMetadata(name, "X-Website")
|
||||
addon.website = stripSpaces(addon.website)
|
||||
end
|
||||
end
|
||||
local current = addon.class
|
||||
while true do
|
||||
if current == AceOO.Class then
|
||||
break
|
||||
end
|
||||
if current.mixins then
|
||||
for mixin in pairs(current.mixins) do
|
||||
if type(mixin.OnEmbedInitialize) == "function" then
|
||||
mixin:OnEmbedInitialize(addon, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
current = current.super
|
||||
end
|
||||
if type(addon.OnInitialize) == "function" then
|
||||
addon:OnInitialize(name)
|
||||
end
|
||||
RegisterOnEnable(addon)
|
||||
end
|
||||
|
||||
function AceAddon.prototype:PrintAddonInfo()
|
||||
local x
|
||||
if self.title then
|
||||
x = "|cffffff7f" .. tostring(self.title) .. "|r"
|
||||
elseif self.name then
|
||||
x = "|cffffff7f" .. tostring(self.name) .. "|r"
|
||||
else
|
||||
x = "|cffffff7f<" .. tostring(self.class) .. " instance>|r"
|
||||
end
|
||||
if type(self.IsActive) == "function" then
|
||||
if not self:IsActive() then
|
||||
x = x .. " " .. STANDBY
|
||||
end
|
||||
end
|
||||
if self.version then
|
||||
x = x .. " - |cffffff7f" .. tostring(self.version) .. "|r"
|
||||
end
|
||||
if self.notes then
|
||||
x = x .. " - " .. tostring(self.notes)
|
||||
end
|
||||
print(x)
|
||||
if self.author then
|
||||
print(" - |cffffff7f" .. AUTHOR .. ":|r " .. tostring(self.author))
|
||||
end
|
||||
if self.date then
|
||||
print(" - |cffffff7f" .. DATE .. ":|r " .. tostring(self.date))
|
||||
end
|
||||
if self.category then
|
||||
local category = CATEGORIES[self.category]
|
||||
if category then
|
||||
print(" - |cffffff7f" .. CATEGORY .. ":|r " .. category)
|
||||
end
|
||||
end
|
||||
if self.email then
|
||||
print(" - |cffffff7f" .. EMAIL .. ":|r " .. tostring(self.email))
|
||||
end
|
||||
if self.website then
|
||||
print(" - |cffffff7f" .. WEBSITE .. ":|r " .. tostring(self.website))
|
||||
end
|
||||
end
|
||||
|
||||
local options
|
||||
function AceAddon:GetAceOptionsDataTable(target)
|
||||
if not options then
|
||||
options = {
|
||||
about = {
|
||||
name = ABOUT,
|
||||
desc = PRINT_ADDON_INFO,
|
||||
type = "execute",
|
||||
func = "PrintAddonInfo",
|
||||
order = -1,
|
||||
}
|
||||
}
|
||||
end
|
||||
return options
|
||||
end
|
||||
|
||||
function AceAddon:PLAYER_LOGIN()
|
||||
self.playerLoginFired = true
|
||||
if self.addonsToOnEnable then
|
||||
while table.getn(self.addonsToOnEnable) > 0 do
|
||||
local addon = table.remove(self.addonsToOnEnable, 1)
|
||||
self.addonsStarted[addon] = true
|
||||
if (type(addon.IsActive) ~= "function" or addon:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(addon) or AceModuleCore:IsModuleActive(addon)) then
|
||||
local current = addon.class
|
||||
while true do
|
||||
if current == AceOO.Class then
|
||||
break
|
||||
end
|
||||
if current.mixins then
|
||||
for mixin in pairs(current.mixins) do
|
||||
if type(mixin.OnEmbedEnable) == "function" then
|
||||
mixin:OnEmbedEnable(addon)
|
||||
end
|
||||
end
|
||||
end
|
||||
current = current.super
|
||||
end
|
||||
if type(addon.OnEnable) == "function" then
|
||||
addon:OnEnable()
|
||||
end
|
||||
end
|
||||
end
|
||||
self.addonsToOnEnable = nil
|
||||
end
|
||||
end
|
||||
|
||||
function AceAddon.prototype:Inject(t)
|
||||
AceAddon:argCheck(t, 2, "table")
|
||||
for k,v in pairs(t) do
|
||||
self[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
function AceAddon.prototype:init()
|
||||
if not AceEvent then
|
||||
error(MAJOR_VERSION .. " requires AceEvent-2.0", 4)
|
||||
end
|
||||
AceAddon.super.prototype.init(self)
|
||||
|
||||
self.super = self.class.prototype
|
||||
|
||||
AceAddon:RegisterEvent("ADDON_LOADED", "ADDON_LOADED", true)
|
||||
table.insert(AceAddon.nextAddon, self)
|
||||
end
|
||||
|
||||
function AceAddon.prototype:ToString()
|
||||
local x
|
||||
if type(self.title) == "string" then
|
||||
x = self.title
|
||||
elseif type(self.name) == "string" then
|
||||
x = self.name
|
||||
else
|
||||
x = "<" .. tostring(self.class) .. " instance>"
|
||||
end
|
||||
if (type(self.IsActive) == "function" and not self:IsActive()) or (AceModuleCore and AceModuleCore:IsModule(addon) and AceModuleCore:IsModuleActive(addon)) then
|
||||
x = x .. " " .. STANDBY
|
||||
end
|
||||
return x
|
||||
end
|
||||
|
||||
AceAddon.new = function(self, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20)
|
||||
local class = AceAddon:pcall(AceOO.Classpool, self, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20)
|
||||
return class:new()
|
||||
end
|
||||
|
||||
local function external(self, major, instance)
|
||||
if major == "AceEvent-2.0" then
|
||||
AceEvent = instance
|
||||
|
||||
AceEvent:embed(self)
|
||||
|
||||
self:RegisterEvent("PLAYER_LOGIN", "PLAYER_LOGIN", true)
|
||||
elseif major == "AceConsole-2.0" then
|
||||
AceConsole = instance
|
||||
|
||||
local slashCommands = { "/ace2" }
|
||||
local _,_,_,enabled,loadable = GetAddOnInfo("Ace")
|
||||
if not enabled or not loadable then
|
||||
table.insert(slashCommands, "/ace")
|
||||
end
|
||||
local function listAddon(addon, depth)
|
||||
if not depth then
|
||||
depth = 0
|
||||
end
|
||||
|
||||
local s = string.rep(" ", depth) .. " - " .. tostring(addon)
|
||||
if rawget(addon, 'version') then
|
||||
s = s .. " - |cffffff7f" .. tostring(addon.version) .. "|r"
|
||||
end
|
||||
if rawget(addon, 'slashCommand') then
|
||||
s = s .. " |cffffff7f(" .. tostring(addon.slashCommand) .. ")|r"
|
||||
end
|
||||
print(s)
|
||||
if type(rawget(addon, 'modules')) == "table" then
|
||||
local i = 0
|
||||
for k,v in pairs(addon.modules) do
|
||||
i = i + 1
|
||||
if i == 6 then
|
||||
print(string.rep(" ", depth + 1) .. " - more...")
|
||||
break
|
||||
else
|
||||
listAddon(v, depth + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local function listNormalAddon(i)
|
||||
local name,_,_,enabled,loadable = GetAddOnInfo(i)
|
||||
if not loadable then
|
||||
enabled = false
|
||||
end
|
||||
if self.addons[name] then
|
||||
local addon = self.addons[name]
|
||||
if not AceCoreAddon or not AceCoreAddon:IsModule(addon) then
|
||||
listAddon(addon)
|
||||
end
|
||||
else
|
||||
local s = " - " .. tostring(GetAddOnMetadata(i, "Title") or name)
|
||||
local version = GetAddOnMetadata(i, "Version")
|
||||
if version then
|
||||
if string.find(version, "%$Revision: (%d+) %$") then
|
||||
version = string.gsub(version, "%$Revision: (%d+) %$", "%1")
|
||||
elseif string.find(version, "%$Rev: (%d+) %$") then
|
||||
version = string.gsub(version, "%$Rev: (%d+) %$", "%1")
|
||||
elseif string.find(version, "%$LastChangedRevision: (%d+) %$") then
|
||||
version = string.gsub(version, "%$LastChangedRevision: (%d+) %$", "%1")
|
||||
end
|
||||
s = s .. " - |cffffff7f" .. version .. "|r"
|
||||
end
|
||||
if not enabled then
|
||||
s = s .. " |cffff0000(disabled)|r"
|
||||
end
|
||||
if IsAddOnLoadOnDemand(i) then
|
||||
s = s .. " |cff00ff00[LoD]|r"
|
||||
end
|
||||
print(s)
|
||||
end
|
||||
end
|
||||
local function mySort(alpha, bravo)
|
||||
return tostring(alpha) < tostring(bravo)
|
||||
end
|
||||
AceConsole.RegisterChatCommand(self, slashCommands, {
|
||||
desc = "AddOn development framework",
|
||||
name = "Ace2",
|
||||
type = "group",
|
||||
args = {
|
||||
about = {
|
||||
desc = "Get information about Ace2",
|
||||
name = "About",
|
||||
type = "execute",
|
||||
func = function()
|
||||
print("|cffffff7fAce2|r - |cffffff7f2.0." .. string.gsub(MINOR_VERSION, "%$Revision: (%d+) %$", "%1") .. "|r - AddOn development framework")
|
||||
print(" - |cffffff7f" .. AUTHOR .. ":|r Ace Development Team")
|
||||
print(" - |cffffff7f" .. WEBSITE .. ":|r http://www.wowace.com/")
|
||||
end
|
||||
},
|
||||
list = {
|
||||
desc = "List addons",
|
||||
name = "List",
|
||||
type = "group",
|
||||
args = {
|
||||
ace2 = {
|
||||
desc = "List addons using Ace2",
|
||||
name = "Ace2",
|
||||
type = "execute",
|
||||
func = function()
|
||||
print("|cffffff7fAddon list:|r")
|
||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
||||
table.sort(self.addons, mySort)
|
||||
for _,v in ipairs(self.addons) do
|
||||
if not AceCoreAddon or not AceCoreAddon:IsModule(v) then
|
||||
listAddon(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
},
|
||||
all = {
|
||||
desc = "List all addons",
|
||||
name = "All",
|
||||
type = "execute",
|
||||
func = function()
|
||||
print("|cffffff7fAddon list:|r")
|
||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
||||
local count = GetNumAddOns()
|
||||
for i = 1, count do
|
||||
listNormalAddon(i)
|
||||
end
|
||||
end
|
||||
},
|
||||
enabled = {
|
||||
desc = "List all enabled addons",
|
||||
name = "Enabled",
|
||||
type = "execute",
|
||||
func = function()
|
||||
print("|cffffff7fAddon list:|r")
|
||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
||||
local count = GetNumAddOns()
|
||||
for i = 1, count do
|
||||
local _,_,_,enabled,loadable = GetAddOnInfo(i)
|
||||
if enabled and loadable then
|
||||
listNormalAddon(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
},
|
||||
disabled = {
|
||||
desc = "List all disabled addons",
|
||||
name = "Disabled",
|
||||
type = "execute",
|
||||
func = function()
|
||||
print("|cffffff7fAddon list:|r")
|
||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
||||
local count = GetNumAddOns()
|
||||
for i = 1, count do
|
||||
local _,_,_,enabled,loadable = GetAddOnInfo(i)
|
||||
if not enabled or not loadable then
|
||||
listNormalAddon(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
},
|
||||
lod = {
|
||||
desc = "List all LoadOnDemand addons",
|
||||
name = "LoadOnDemand",
|
||||
type = "execute",
|
||||
func = function()
|
||||
print("|cffffff7fAddon list:|r")
|
||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
||||
local count = GetNumAddOns()
|
||||
for i = 1, count do
|
||||
if IsAddOnLoadOnDemand(i) then
|
||||
listNormalAddon(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
},
|
||||
ace1 = {
|
||||
desc = "List all addons using Ace1",
|
||||
name = "Ace 1.x",
|
||||
type = "execute",
|
||||
func = function()
|
||||
print("|cffffff7fAddon list:|r")
|
||||
local count = GetNumAddOns()
|
||||
for i = 1, count do
|
||||
local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i)
|
||||
if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then
|
||||
listNormalAddon(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
},
|
||||
libs = {
|
||||
desc = "List all libraries using AceLibrary",
|
||||
name = "Libraries",
|
||||
type = "execute",
|
||||
func = function()
|
||||
if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then
|
||||
print("|cffffff7fLibrary list:|r")
|
||||
for name, data in pairs(AceLibrary.libs) do
|
||||
local s
|
||||
if data.minor then
|
||||
s = " - " .. tostring(name) .. "." .. tostring(data.minor)
|
||||
else
|
||||
s = " - " .. tostring(name)
|
||||
end
|
||||
if AceLibrary(name).slashCommand then
|
||||
s = s .. " |cffffff7f(" .. tostring(AceLibrary(name).slashCommand) .. "|cffffff7f)"
|
||||
end
|
||||
print(s)
|
||||
end
|
||||
end
|
||||
end
|
||||
},
|
||||
search = {
|
||||
desc = "Search by name",
|
||||
name = "Search",
|
||||
type = "text",
|
||||
usage = "<keyword>",
|
||||
input = true,
|
||||
get = false,
|
||||
set = function(...)
|
||||
for i,v in ipairs(arg) do
|
||||
arg[i] = string.lower(string.gsub(string.gsub(v, '%*', '.*'), '%%', '%%%%'))
|
||||
end
|
||||
local count = GetNumAddOns()
|
||||
for i = 1, count do
|
||||
local name = GetAddOnInfo(i)
|
||||
local good = true
|
||||
for _,v in ipairs(arg) do
|
||||
if not string.find(string.lower(name), v) then
|
||||
good = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if good then
|
||||
listNormalAddon(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
},
|
||||
},
|
||||
enable = {
|
||||
desc = "Enable addon",
|
||||
name = "Enable",
|
||||
type = "text",
|
||||
usage = "<addon>",
|
||||
get = false,
|
||||
set = function(text)
|
||||
local name,title,_,_,_,reason = GetAddOnInfo(text)
|
||||
if reason == "MISSING" then
|
||||
print(string.format("|cffffff7fAce2:|r AddOn %q does not exist", text))
|
||||
else
|
||||
EnableAddOn(text)
|
||||
print(string.format("|cffffff7fAce2:|r %s is now enabled", title or name))
|
||||
end
|
||||
end,
|
||||
},
|
||||
disable = {
|
||||
desc = "Disable addon",
|
||||
name = "Disable",
|
||||
type = "text",
|
||||
usage = "<addon>",
|
||||
get = false,
|
||||
set = function(text)
|
||||
local name,title,_,_,_,reason = GetAddOnInfo(text)
|
||||
if reason == "MISSING" then
|
||||
print(string.format("|cffffff7fAce2:|r AddOn %q does not exist", text))
|
||||
else
|
||||
DisableAddOn(text)
|
||||
print(string.format("|cffffff7fAce2:|r %s is now disabled", title or name))
|
||||
end
|
||||
end,
|
||||
},
|
||||
load = {
|
||||
desc = "Load addon",
|
||||
name = "Load",
|
||||
type = "text",
|
||||
usage = "<addon>",
|
||||
get = false,
|
||||
set = function(text)
|
||||
local name,title,_,_,loadable,reason = GetAddOnInfo(text)
|
||||
if reason == "MISSING" then
|
||||
print(string.format("|cffffff7fAce2:|r AddOn %q does not exist.", text))
|
||||
elseif not loadable then
|
||||
print(string.format("|cffffff7fAce2:|r AddOn %q is not loadable. Reason: %s", text, reason))
|
||||
else
|
||||
LoadAddOn(text)
|
||||
print(string.format("|cffffff7fAce2:|r %s is now loaded", title or name))
|
||||
end
|
||||
end
|
||||
},
|
||||
info = {
|
||||
desc = "Display information",
|
||||
name = "Information",
|
||||
type = "execute",
|
||||
func = function()
|
||||
local mem, threshold = gcinfo()
|
||||
print(string.format(" - |cffffff7fMemory usage [|r%.3f MiB|cffffff7f]|r", mem / 1024))
|
||||
print(string.format(" - |cffffff7fThreshold [|r%.3f MiB|cffffff7f]|r", threshold / 1024))
|
||||
print(string.format(" - |cffffff7fFramerate [|r%.0f fps|cffffff7f]|r", GetFramerate()))
|
||||
local bandwidthIn, bandwidthOut, latency = GetNetStats()
|
||||
bandwidthIn, bandwidthOut = floor(bandwidthIn * 1024), floor(bandwidthOut * 1024)
|
||||
print(string.format(" - |cffffff7fLatency [|r%.0f ms|cffffff7f]|r", latency))
|
||||
print(string.format(" - |cffffff7fBandwidth in [|r%.0f B/s|cffffff7f]|r", bandwidthIn))
|
||||
print(string.format(" - |cffffff7fBandwidth out [|r%.0f B/s|cffffff7f]|r", bandwidthOut))
|
||||
print(string.format(" - |cffffff7fTotal addons [|r%d|cffffff7f]|r", GetNumAddOns()))
|
||||
print(string.format(" - |cffffff7fAce2 addons [|r%d|cffffff7f]|r", table.getn(self.addons)))
|
||||
local ace = 0
|
||||
local enabled = 0
|
||||
local disabled = 0
|
||||
local lod = 0
|
||||
for i = 1, GetNumAddOns() do
|
||||
local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i)
|
||||
if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then
|
||||
ace = ace + 1
|
||||
end
|
||||
if IsAddOnLoadOnDemand(i) then
|
||||
lod = lod + 1
|
||||
end
|
||||
local _,_,_,IsActive,loadable = GetAddOnInfo(i)
|
||||
if not IsActive or not loadable then
|
||||
disabled = disabled + 1
|
||||
else
|
||||
enabled = enabled + 1
|
||||
end
|
||||
end
|
||||
print(string.format(" - |cffffff7fAce 1.x addons [|r%d|cffffff7f]|r", ace))
|
||||
print(string.format(" - |cffffff7fLoadOnDemand addons [|r%d|cffffff7f]|r", lod))
|
||||
print(string.format(" - |cffffff7fenabled addons [|r%d|cffffff7f]|r", enabled))
|
||||
print(string.format(" - |cffffff7fdisabled addons [|r%d|cffffff7f]|r", disabled))
|
||||
local libs = 0
|
||||
if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then
|
||||
for _ in pairs(AceLibrary.libs) do
|
||||
libs = libs + 1
|
||||
end
|
||||
end
|
||||
print(string.format(" - |cffffff7fAceLibrary instances [|r%d|cffffff7f]|r", libs))
|
||||
end
|
||||
}
|
||||
}
|
||||
})
|
||||
elseif major == "AceModuleCore-2.0" then
|
||||
AceModuleCore = instance
|
||||
end
|
||||
end
|
||||
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
AceAddon = self
|
||||
|
||||
if oldLib then
|
||||
self.playerLoginFired = oldLib.playerLoginFired or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage
|
||||
self.addonsToOnEnable = oldLib.addonsToOnEnable
|
||||
self.addons = oldLib.addons
|
||||
self.nextAddon = oldLib.nextAddon
|
||||
self.addonsStarted = oldLib.addonsStarted
|
||||
end
|
||||
if not self.addons then
|
||||
self.addons = {}
|
||||
end
|
||||
if not self.nextAddon then
|
||||
self.nextAddon = {}
|
||||
end
|
||||
if not self.addonsStarted then
|
||||
self.addonsStarted = {}
|
||||
end
|
||||
if oldDeactivate then
|
||||
oldDeactivate(oldLib)
|
||||
end
|
||||
end
|
||||
|
||||
AceLibrary:Register(AceAddon, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
|
||||
AceAddon = AceLibrary(MAJOR_VERSION)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,238 @@
|
||||
--[[
|
||||
Name: AceDebug-2.0
|
||||
Revision: $Rev: 15024 $
|
||||
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/AceDebug-2.0
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceDebug-2.0
|
||||
Description: Mixin to allow for simple debugging capabilities.
|
||||
Dependencies: AceLibrary, AceOO-2.0
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceDebug-2.0"
|
||||
local MINOR_VERSION = "$Revision: 15024 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
||||
|
||||
local DEBUGGING, TOGGLE_DEBUGGING
|
||||
|
||||
if GetLocale() == "frFR" then
|
||||
DEBUGGING = "D\195\169boguage"
|
||||
TOGGLE_DEBUGGING = "Activer/d\195\169sactiver le d\195\169boguage"
|
||||
elseif GetLocale() == "deDE" then
|
||||
DEBUGGING = "Debuggen"
|
||||
TOGGLE_DEBUGGING = "Aktiviert/Deaktiviert Debugging"
|
||||
elseif GetLocale() == "koKR" then
|
||||
DEBUGGING = "디버깅"
|
||||
TOGGLE_DEBUGGING = "디버깅 기능 사용함/사용안함"
|
||||
elseif GetLocale() == "zhTW" then
|
||||
DEBUGGING = "除錯"
|
||||
TOGGLE_DEBUGGING = "啟用/停用除錯功能"
|
||||
elseif GetLocale() == "zhCN" then
|
||||
DEBUGGING = "\232\176\131\232\175\149"
|
||||
TOGGLE_DEBUGGING = "\229\144\175\231\148\168/\231\166\129\231\148\168 \232\176\131\232\175\149"
|
||||
else -- enUS
|
||||
DEBUGGING = "Debugging"
|
||||
TOGGLE_DEBUGGING = "Enable/disable debugging"
|
||||
end
|
||||
|
||||
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 math_mod = math.mod or math.fmod
|
||||
|
||||
local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
||||
local AceDebug = AceOO.Mixin {"Debug", "CustomDebug", "IsDebugging", "SetDebugging", "SetDebugLevel", "LevelDebug", "CustomLevelDebug", "GetDebugLevel"}
|
||||
|
||||
local function print(text, r, g, b, frame, delay)
|
||||
(frame or DEFAULT_CHAT_FRAME):AddMessage(text, r, g, b, 1, delay or 5)
|
||||
end
|
||||
|
||||
local tmp
|
||||
|
||||
function AceDebug:CustomDebug(r, g, b, frame, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not self.debugging then return end
|
||||
|
||||
local output = string.format("|cff7fff7f(DEBUG) %s:[%s%3d]|r", tostring(self), date("%H:%M:%S"), math_mod(GetTime(), 1) * 1000)
|
||||
|
||||
if string.find(tostring(a1), "%%") then
|
||||
output = output .. " " .. string.format(tostring(a1), tostring(a2), tostring(a3), tostring(a4), tostring(a5), tostring(a6), tostring(a7), tostring(a8), tostring(a9), tostring(a10), tostring(a11), tostring(a12), tostring(a13), tostring(a14), tostring(a15), tostring(a16), tostring(a17), tostring(a18), tostring(a19), tostring(a20))
|
||||
else
|
||||
if not tmp then
|
||||
tmp = {}
|
||||
end
|
||||
|
||||
-- This block dynamically rebuilds the tmp array stopping on the first nil.
|
||||
table.insert(tmp, output)
|
||||
|
||||
table.insert(tmp, tostring(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)
|
||||
while tmp[table.getn(tmp)] == nil do
|
||||
table.remove(tmp)
|
||||
end
|
||||
for k = 1, table.getn(tmp) do
|
||||
tmp[k] = tostring(tmp[k])
|
||||
end
|
||||
|
||||
output = table.concat(tmp, " ")
|
||||
|
||||
for k,v in pairs(tmp) do
|
||||
tmp[k] = nil
|
||||
end
|
||||
table_setn(tmp, 0)
|
||||
end
|
||||
|
||||
print(output, r, g, b, frame or self.debugFrame, delay)
|
||||
end
|
||||
|
||||
function AceDebug:Debug(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
AceDebug.CustomDebug(self, nil, nil, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
|
||||
function AceDebug:IsDebugging()
|
||||
return self.debugging
|
||||
end
|
||||
|
||||
function AceDebug:SetDebugging(debugging)
|
||||
self.debugging = debugging
|
||||
end
|
||||
|
||||
-- Takes a number 1-3
|
||||
-- Level 1: Critical messages that every user should receive
|
||||
-- Level 2: Should be used for local debugging (function calls, etc)
|
||||
-- Level 3: Very verbose debugging, will dump everything and anything
|
||||
-- If set to nil, you will receive no debug information
|
||||
function AceDebug:SetDebugLevel(level)
|
||||
AceDebug:argCheck(level, 1, "number", "nil")
|
||||
if not level then
|
||||
self.debuglevel = nil
|
||||
return
|
||||
end
|
||||
if level < 1 or level > 3 then
|
||||
AceDebug:error("Bad argument #1 to `SetDebugLevel`, must be a number 1-3")
|
||||
end
|
||||
self.debuglevel = level
|
||||
end
|
||||
|
||||
function AceDebug:GetDebugLevel()
|
||||
return self.debuglevel
|
||||
end
|
||||
|
||||
function AceDebug:CustomLevelDebug(level, r, g, b, frame, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not self.debugging or not self.debuglevel then return end
|
||||
AceDebug:argCheck(level, 1, "number")
|
||||
if level < 1 or level > 3 then
|
||||
AceDebug:error("Bad argument #1 to `LevelDebug`, must be a number 1-3")
|
||||
end
|
||||
if level > self.debuglevel then return end
|
||||
|
||||
local output = string.format("|cff7fff7f(DEBUG) %s:[%s.%3d]|r", tostring(self), date("%H:%M:%S"), math_mod(GetTime(), 1) * 1000)
|
||||
|
||||
if string.find(tostring(a1), "%%") then
|
||||
output = output .. " " .. string.format(tostring(a1), tostring(a2), tostring(a3), tostring(a4), tostring(a5), tostring(a6), tostring(a7), tostring(a8), tostring(a9), tostring(a10), tostring(a11), tostring(a12), tostring(a13), tostring(a14), tostring(a15), tostring(a16), tostring(a17), tostring(a18), tostring(a19), tostring(a20))
|
||||
else
|
||||
if not tmp then
|
||||
tmp = {}
|
||||
end
|
||||
|
||||
-- This block dynamically rebuilds the tmp array stopping on the first nil.
|
||||
table.insert(tmp, output)
|
||||
|
||||
table.insert(tmp, tostring(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)
|
||||
while tmp[table.getn(tmp)] == nil do
|
||||
table.remove(tmp)
|
||||
end
|
||||
for k = 1, table.getn(tmp) do
|
||||
tmp[k] = tostring(tmp[k])
|
||||
end
|
||||
|
||||
output = table.concat(tmp, " ")
|
||||
|
||||
for k,v in pairs(tmp) do
|
||||
tmp[k] = nil
|
||||
end
|
||||
table_setn(tmp, 0)
|
||||
end
|
||||
|
||||
print(output, r, g, b, frame or self.debugFrame, delay)
|
||||
end
|
||||
|
||||
function AceDebug:LevelDebug(level, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not self.debugging or not self.debuglevel then return end
|
||||
AceDebug:argCheck(level, 1, "number")
|
||||
if level < 1 or level > 3 then
|
||||
AceDebug:error("Bad argument #1 to `LevelDebug`, must be a number 1-3")
|
||||
end
|
||||
if level > self.debuglevel then return end
|
||||
|
||||
AceDebug.CustomLevelDebug(self, level, nil, nil, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
|
||||
|
||||
local options
|
||||
function AceDebug:GetAceOptionsDataTable(target)
|
||||
if not options then
|
||||
options = {
|
||||
debug = {
|
||||
name = DEBUGGING,
|
||||
desc = TOGGLE_DEBUGGING,
|
||||
type = "toggle",
|
||||
get = "IsDebugging",
|
||||
set = "SetDebugging",
|
||||
order = -2,
|
||||
}
|
||||
}
|
||||
end
|
||||
return options
|
||||
end
|
||||
AceLibrary:Register(AceDebug, MAJOR_VERSION, MINOR_VERSION, AceDebug.activate)
|
||||
AceDebug = AceLibrary(MAJOR_VERSION)
|
||||
@@ -0,0 +1,962 @@
|
||||
--[[
|
||||
Name: AceEvent-2.0
|
||||
Revision: $Rev: 14125 $
|
||||
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: 14125 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
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 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
|
||||
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 function OnUpdate()
|
||||
local t = GetTime()
|
||||
local k,v = next(delayRegistry)
|
||||
local last = nil
|
||||
while k do
|
||||
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
|
||||
if delayRegistry[k] then
|
||||
last = k
|
||||
end
|
||||
k,v = next(delayRegistry, last)
|
||||
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
|
||||
self:UnregisterEvent("MEETINGSTONE_CHANGED")
|
||||
self:RegisterEvent("MINIMAP_ZONE_CHANGED", f, true)
|
||||
end
|
||||
end)
|
||||
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,561 @@
|
||||
--[[
|
||||
Name: AceHook-2.0
|
||||
Revision: $Rev: 10447 $
|
||||
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.0
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceHook-2.0
|
||||
Description: Mixin to allow for safe hooking of functions, methods, and scripts.
|
||||
Dependencies: AceLibrary, AceOO-2.0
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceHook-2.0"
|
||||
local MINOR_VERSION = "$Revision: 10447 $"
|
||||
|
||||
-- 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 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",
|
||||
"Unhook",
|
||||
"UnhookAll",
|
||||
"HookReport",
|
||||
"IsHooked",
|
||||
"HookScript",
|
||||
}
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
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 _G = getfenv(0)
|
||||
|
||||
local handlers, funcs, scripts, actives
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Private definitions (Not exposed)
|
||||
----------------------------------------------------------------------------------]]
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
_debug - Internal Method
|
||||
-------------------------------------------------------------------------]]
|
||||
local function print(text)
|
||||
DEFAULT_CHAT_FRAME:AddMessage(text)
|
||||
end
|
||||
|
||||
local function _debug(self, msg)
|
||||
local name = self.hooks.name
|
||||
if name then
|
||||
print(string.format("[%s]: %s", name, msg))
|
||||
else
|
||||
print(msg)
|
||||
end
|
||||
end
|
||||
|
||||
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)
|
||||
table.setn(t, 0)
|
||||
for k in pairs(t) do
|
||||
t[k] = nil
|
||||
end
|
||||
list[t] = true
|
||||
end
|
||||
end
|
||||
|
||||
local origMetatable = {
|
||||
__call = function(self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
return self.orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
}
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:_getFunctionHook- internal method
|
||||
-------------------------------------------------------------------------]]
|
||||
|
||||
local function _getFunctionHook(self, func, handler, orig)
|
||||
if type(handler) == "string" then
|
||||
-- The handler is a method, need to self it
|
||||
return function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[orig] 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
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
return function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[orig] 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
|
||||
end
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:_getMethodHook - Internal Method
|
||||
-------------------------------------------------------------------------]]
|
||||
local function _getMethodHook(self, object, method, handler, orig, script)
|
||||
if type(handler) == "string" then
|
||||
-- The handler is a method, need to self it
|
||||
if script then
|
||||
return function()
|
||||
if actives[orig] then
|
||||
return self[handler](self, object)
|
||||
else
|
||||
return orig()
|
||||
end
|
||||
end
|
||||
else
|
||||
return function(obj,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[orig] then
|
||||
return self[handler](self, obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
if script then
|
||||
return function()
|
||||
if actives[orig] then
|
||||
return handler(object)
|
||||
else
|
||||
return orig()
|
||||
end
|
||||
end
|
||||
else
|
||||
return function(obj,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[orig] then
|
||||
return handler(obj,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:HookFunc - internal method.
|
||||
o You can only hook each function once from each source.
|
||||
o If there is an inactive hook for this func/handler pair, we reactivate it
|
||||
o If there is an inactive hook for another handler, we error out.
|
||||
o Looks for handler as a method of the calling class, error if not available
|
||||
o If handler is a function, it just uses it directly through the wrapper
|
||||
-------------------------------------------------------------------------]]
|
||||
local function _hookFunc(self, func, handler)
|
||||
local orig = _G[func]
|
||||
|
||||
if not orig or type(orig) ~= "function" then
|
||||
_debug(self, string.format("Attempt to hook a non-existant function %q", func),3)
|
||||
return
|
||||
end
|
||||
|
||||
if not handler then handler = func end
|
||||
|
||||
if self.hooks[func] then
|
||||
local orig = self.hooks[func].orig
|
||||
-- We have an active hook from this source. Don't multi-hook
|
||||
if actives[orig] then
|
||||
_debug(self, string.format("%q already has an active hook from this source.", func))
|
||||
return
|
||||
end
|
||||
-- The hook is inactive, so reactivate it
|
||||
if handlers[orig] == handler then
|
||||
actives[orig] = 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 t = setmetatable(new(), origMetatable)
|
||||
self.hooks[func] = t
|
||||
t.orig = orig
|
||||
|
||||
actives[orig] = true
|
||||
handlers[orig] = handler
|
||||
local newFunc = _getFunctionHook(self, func, handler, orig)
|
||||
funcs[orig] = newFunc
|
||||
|
||||
_G[func] = newFunc
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:UnhookFunc - internal method
|
||||
o If you attempt to unhook a function that has never been hooked, or to unhook in a
|
||||
system that has never had a hook before, the system will error with a stack trace
|
||||
o If we own the global function, then put the original back in its place and remove
|
||||
all references to the Hooks[func] structure.
|
||||
o If we don't own the global function (we've been hooked) we deactivate the hook,
|
||||
forcing the handler to passthrough.
|
||||
-------------------------------------------------------------------------]]
|
||||
local function _unhookFunc(self, func)
|
||||
if not self.hooks[func] or not funcs[self.hooks[func].orig] then
|
||||
_debug(self, string.format("Tried to unhook %q which is not currently hooked.", func))
|
||||
return
|
||||
end
|
||||
|
||||
local orig = self.hooks[func].orig
|
||||
|
||||
if actives[orig] then
|
||||
-- See if we own the global function
|
||||
if _G[func] == funcs[orig] then
|
||||
_G[func] = orig
|
||||
self.hooks[func] = del(self.hooks[func])
|
||||
handlers[orig] = nil
|
||||
funcs[orig] = nil
|
||||
scripts[orig] = nil
|
||||
actives[orig] = nil
|
||||
-- Magically all-done
|
||||
else
|
||||
actives[orig] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:HookMeth - Takes an optional fourth argument
|
||||
o script - Signifies whether this is a script hook or not
|
||||
-------------------------------------------------------------------------]]
|
||||
|
||||
local function _hookMeth(self, obj, method, handler, script)
|
||||
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
|
||||
|
||||
if self.hooks[obj] and self.hooks[obj][method] then
|
||||
local orig = self.hooks[obj][method].orig
|
||||
-- We have an active hook from this source. Don't multi-hook
|
||||
if actives[orig] then
|
||||
_debug(self, string.format("%q already has an active hook from this source.", method))
|
||||
return
|
||||
end
|
||||
-- The hook is inactive, so reactivate it.
|
||||
if handlers[orig] == handler then
|
||||
actives[orig] = true
|
||||
return
|
||||
else
|
||||
AceHook:error("There is a stale hook for %q can't hook or reactivate.", method)
|
||||
end
|
||||
end
|
||||
-- We're clear to try the hook, let's make some checks first
|
||||
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
|
||||
-- Handler has been found, so now try to find the method we're trying to hook
|
||||
local orig
|
||||
-- Script
|
||||
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
|
||||
-- Sometimes there is not a original function for a script.
|
||||
orig = obj:GetScript(method)
|
||||
if not orig then
|
||||
orig = function() end
|
||||
end
|
||||
-- Method
|
||||
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 self.hooks[obj] then
|
||||
self.hooks[obj] = new()
|
||||
end
|
||||
local t = setmetatable(new(), origMetatable)
|
||||
self.hooks[obj][method] = t
|
||||
t.orig = orig
|
||||
|
||||
actives[orig] = true
|
||||
handlers[orig] = handler
|
||||
scripts[orig] = script and true or nil
|
||||
local newFunc = _getMethodHook(self, obj, method, handler, orig, script)
|
||||
funcs[orig] = newFunc
|
||||
|
||||
if script then
|
||||
obj:SetScript(method, newFunc)
|
||||
else
|
||||
obj[method] = newFunc
|
||||
end
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:UnhookMeth - Internal method
|
||||
o If you attempt to unhook a method that has never been hooked, or to unhook in a
|
||||
system that has never had a hook before, the system will error with a stack trace
|
||||
o If we own the global method, then put the original back in its place and remove
|
||||
all references to the Hooks[obj][method] structure.
|
||||
o If we don't own the global method (we've been hooked) we deactivate the hook,
|
||||
forcing the handler to passthrough.
|
||||
-------------------------------------------------------------------------]]
|
||||
local function _unhookMeth(self, obj, method)
|
||||
if not self.hooks[obj] or not self.hooks[obj][method] or not funcs[self.hooks[obj][method].orig] then
|
||||
_debug(self, string.format("Attempt to unhook a method %q that is not currently hooked.", method))
|
||||
return
|
||||
end
|
||||
|
||||
local orig = self.hooks[obj][method].orig
|
||||
|
||||
if actives[orig] then
|
||||
-- If this is a script
|
||||
if scripts[orig] then
|
||||
if obj:GetScript(method) == funcs[orig] then
|
||||
-- We own the script. Kill it.
|
||||
obj:SetScript(method, orig)
|
||||
self.hooks[obj][method] = del(self.hooks[obj][method])
|
||||
handlers[orig] = nil
|
||||
funcs[orig] = nil
|
||||
scripts[orig] = nil
|
||||
actives[orig] = nil
|
||||
else
|
||||
actives[orig] = nil
|
||||
end
|
||||
else
|
||||
if obj[method] == funcs[orig] then
|
||||
-- We own the method. Kill it.
|
||||
obj[method] = orig
|
||||
self.hooks[obj][method] = del(self.hooks[obj][method])
|
||||
handlers[orig] = nil
|
||||
funcs[orig] = nil
|
||||
scripts[orig] = nil
|
||||
actives[orig] = nil
|
||||
else
|
||||
actives[orig] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if not next(self.hooks[obj]) then
|
||||
-- Spank the table
|
||||
self.hooks[obj] = del(self.hooks[obj])
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:OnInstanceInit(object)
|
||||
if not object.hooks then
|
||||
object.hooks = new()
|
||||
end
|
||||
|
||||
local name
|
||||
|
||||
if type(rawget(object, 'GetLibraryVersion')) == "function" then
|
||||
name = object:GetLibraryVersion()
|
||||
end
|
||||
if not name and type(object.GetName) == "function" then
|
||||
name = object:GetName()
|
||||
end
|
||||
if not name and type(object.name) == "string" then
|
||||
name = object.name
|
||||
end
|
||||
if not name then
|
||||
for k,v in pairs(_G) do
|
||||
if v == object then
|
||||
name = tostring(k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
object.hooks.name = name
|
||||
end
|
||||
|
||||
AceHook.OnManualEmbed = AceHook.OnInstanceInit
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:Hook
|
||||
self:Hook("functionName", ["handlerName" | handler])
|
||||
self:Hook(ObjectName, "Method", ["Handler" | handler])
|
||||
-------------------------------------------------------------------------]]
|
||||
function AceHook:Hook(arg1, arg2, arg3)
|
||||
if type(arg1)== "string" then
|
||||
if protFuncs[arg1] then
|
||||
if self.hooks.name then
|
||||
AceHook:error("%s tried to hook %q, which is a Blizzard protected function.", self.hooks.name, arg1)
|
||||
else
|
||||
_debug(self, string.format("An Addon tried to hook %q, which is a Blizzard protected function.", arg1))
|
||||
end
|
||||
else
|
||||
_hookFunc(self, arg1, arg2)
|
||||
end
|
||||
else
|
||||
_hookMeth(self, arg1, arg2, arg3)
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:HookScript(arg1, arg2, arg3)
|
||||
_hookMeth(self, arg1, arg2, arg3, true)
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:IsHooked()
|
||||
self:Hook("functionName")
|
||||
self:Hook(ObjectName, "Method")
|
||||
|
||||
Returns whether or not the given function is hooked in the current
|
||||
namespace. A hooked, but inactive function is considered NOT
|
||||
hooked in this context.
|
||||
-------------------------------------------------------------------------]]
|
||||
function AceHook:IsHooked(obj, method)
|
||||
if method and obj then
|
||||
if self.hooks and self.hooks[obj] and self.hooks[obj][method] and actives[self.hooks[obj][method].orig] then
|
||||
return true, handlers[self.hooks[obj][method].orig]
|
||||
end
|
||||
else
|
||||
if self.hooks and self.hooks[obj] and actives[self.hooks[obj].orig] then
|
||||
return true, handlers[self.hooks[obj].orig]
|
||||
end
|
||||
end
|
||||
|
||||
return false, nil
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:Unhook
|
||||
self:Unhook("functionName")
|
||||
self:Unhook(ObjectName, "Method")
|
||||
-------------------------------------------------------------------------]]
|
||||
function AceHook:Unhook(arg1, arg2)
|
||||
if type(arg1) == "string" then
|
||||
_unhookFunc(self, arg1)
|
||||
else
|
||||
_unhookMeth(self, arg1, arg2)
|
||||
end
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:UnhookAll - Unhooks all active hooks from the calling source
|
||||
-------------------------------------------------------------------------]]
|
||||
function AceHook:UnhookAll()
|
||||
for key, value in pairs(self.hooks) 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:OnEmbedDisable(target)
|
||||
self.UnhookAll(target)
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------
|
||||
AceHook:HookReport - Lists registered hooks from this source
|
||||
-------------------------------------------------------------------------]]
|
||||
|
||||
function AceHook:HookReport()
|
||||
_debug(self, "This is a list of all active hooks for this object:")
|
||||
if not self.hooks then _debug(self, "No registered hooks.") return end
|
||||
|
||||
for key, value in pairs(self.hooks) do
|
||||
if type(value) == "table" then
|
||||
for method in pairs(value) do
|
||||
_debug(self, string.format("key: %s method: %q |cff%s|r", tostring(key), method, self.hooks[key][method].active and "00ff00Active" or "ffff00Inactive"))
|
||||
end
|
||||
else
|
||||
_debug(self, string.format("key: %s value: %q |cff%s|r", tostring(key), tostring(value), self.hooks[key].active and "00ff00Active" or "ffff00Inactive"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Stub and Library registration
|
||||
----------------------------------------------------------------------------------]]
|
||||
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
AceHook = self
|
||||
|
||||
AceHook.super.activate(self, oldLib, oldDeactivate)
|
||||
|
||||
if oldLib then
|
||||
self.handlers = oldLib.handlers
|
||||
self.funcs = oldLib.funcs
|
||||
self.scripts = oldLib.scripts
|
||||
self.actives = oldLib.actives
|
||||
end
|
||||
|
||||
if not self.handlers then
|
||||
self.handlers = {}
|
||||
end
|
||||
if not self.funcs then
|
||||
self.funcs = {}
|
||||
end
|
||||
if not self.scripts then
|
||||
self.scripts = {}
|
||||
end
|
||||
if not self.actives then
|
||||
self.actives = {}
|
||||
end
|
||||
|
||||
handlers = self.handlers
|
||||
funcs = self.funcs
|
||||
scripts = self.scripts
|
||||
actives = self.actives
|
||||
|
||||
if oldDeactivate then
|
||||
oldDeactivate(oldLib)
|
||||
end
|
||||
end
|
||||
|
||||
AceLibrary:Register(AceHook, MAJOR_VERSION, MINOR_VERSION, activate)
|
||||
@@ -0,0 +1,751 @@
|
||||
--[[
|
||||
Name: AceLibrary
|
||||
Revision: $Rev: 14130 $
|
||||
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: 14130 $
|
||||
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: 14130 $"
|
||||
|
||||
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
|
||||
|
||||
-- @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
|
||||
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
|
||||
externalFunc(instance, k, data.instance)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k,data in pairs(self.libs) do
|
||||
if k ~= major and data.externalFunc then
|
||||
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
|
||||
activateFunc(instance, oldInstance, oldDeactivateFunc)
|
||||
else
|
||||
oldDeactivateFunc(oldInstance)
|
||||
end
|
||||
del(oldInstance)
|
||||
|
||||
if externalFunc then
|
||||
for k,data in pairs(self.libs) do
|
||||
if k ~= major then
|
||||
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)
|
||||
@@ -0,0 +1,537 @@
|
||||
--[[
|
||||
Name: AceLocale-2.2
|
||||
Revision: $Rev: 15291 $
|
||||
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/AceLocale-2.2
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceLocale-2.2
|
||||
Description: Localization library for addons to use to handle proper
|
||||
localization and internationalization.
|
||||
Dependencies: AceLibrary
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceLocale-2.2"
|
||||
local MINOR_VERSION = "$Revision: 15291 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
local AceLocale = {}
|
||||
|
||||
local DEFAULT_LOCALE = "enUS"
|
||||
local _G = getfenv(0)
|
||||
|
||||
local BASE_TRANSLATIONS, DEBUGGING, TRANSLATIONS, BASE_LOCALE, TRANSLATION_TABLES, REVERSE_TRANSLATIONS, STRICTNESS, DYNAMIC_LOCALES, CURRENT_LOCALE, NAME
|
||||
|
||||
local rawget = rawget
|
||||
local rawset = rawset
|
||||
local type = type
|
||||
|
||||
local newRegistries = {}
|
||||
local scheduleClear
|
||||
|
||||
local lastSelf
|
||||
local __index = function(self, key)
|
||||
lastSelf = self
|
||||
local value = (rawget(self, TRANSLATIONS) or AceLocale.prototype)[key]
|
||||
rawset(self, key, value)
|
||||
return value
|
||||
end
|
||||
|
||||
local __newindex = function(self, k, v)
|
||||
if type(v) ~= "function" and type(k) ~= "table" then
|
||||
AceLocale.error(self, "Cannot change the values of an AceLocale instance.")
|
||||
end
|
||||
rawset(self, k, v)
|
||||
end
|
||||
|
||||
local __tostring = function(self)
|
||||
if type(rawget(self, 'GetLibraryVersion')) == "function" then
|
||||
return self:GetLibraryVersion()
|
||||
else
|
||||
return "AceLocale(" .. self[NAME] .. ")"
|
||||
end
|
||||
end
|
||||
|
||||
local function clearCache(self)
|
||||
if not rawget(self, BASE_TRANSLATIONS) then
|
||||
return
|
||||
end
|
||||
|
||||
local cache = self[BASE_TRANSLATIONS]
|
||||
rawset(self, REVERSE_TRANSLATIONS, nil)
|
||||
|
||||
for k in pairs(self) do
|
||||
if rawget(cache, k) ~= nil then
|
||||
self[k] = nil
|
||||
end
|
||||
end
|
||||
rawset(self, 'tmp', true)
|
||||
self.tmp = nil
|
||||
end
|
||||
|
||||
local function refixInstance(instance)
|
||||
if getmetatable(instance) then
|
||||
setmetatable(instance, nil)
|
||||
end
|
||||
local translations = instance[TRANSLATIONS]
|
||||
if translations then
|
||||
if getmetatable(translations) then
|
||||
setmetatable(translations, nil)
|
||||
end
|
||||
local baseTranslations = instance[BASE_TRANSLATIONS]
|
||||
if getmetatable(baseTranslations) then
|
||||
setmetatable(baseTranslations, nil)
|
||||
end
|
||||
if translations == baseTranslations or instance[STRICTNESS] then
|
||||
setmetatable(instance, {
|
||||
__index = __index,
|
||||
__newindex = __newindex,
|
||||
__tostring = __tostring
|
||||
})
|
||||
|
||||
setmetatable(translations, {
|
||||
__index = AceLocale.prototype
|
||||
})
|
||||
else
|
||||
setmetatable(instance, {
|
||||
__index = __index,
|
||||
__newindex = __newindex,
|
||||
__tostring = __tostring
|
||||
})
|
||||
|
||||
setmetatable(translations, {
|
||||
__index = baseTranslations,
|
||||
})
|
||||
|
||||
setmetatable(baseTranslations, {
|
||||
__index = AceLocale.prototype,
|
||||
})
|
||||
end
|
||||
else
|
||||
setmetatable(instance, {
|
||||
__index = __index,
|
||||
__newindex = __newindex,
|
||||
__tostring = __tostring,
|
||||
})
|
||||
end
|
||||
clearCache(instance)
|
||||
newRegistries[instance] = true
|
||||
scheduleClear()
|
||||
return instance
|
||||
end
|
||||
|
||||
function AceLocale:new(name)
|
||||
self:argCheck(name, 2, "string")
|
||||
|
||||
if self.registry[name] and type(rawget(self.registry[name], 'GetLibraryVersion')) ~= "function" then
|
||||
return self.registry[name]
|
||||
end
|
||||
|
||||
AceLocale.registry[name] = refixInstance({
|
||||
[STRICTNESS] = false,
|
||||
[NAME] = name,
|
||||
})
|
||||
newRegistries[AceLocale.registry[name]] = true
|
||||
return AceLocale.registry[name]
|
||||
end
|
||||
|
||||
AceLocale.prototype = { class = AceLocale }
|
||||
|
||||
function AceLocale.prototype:EnableDebugging()
|
||||
if rawget(self, BASE_TRANSLATIONS) then
|
||||
AceLocale.error(self, "Cannot enable debugging after a translation has been registered.")
|
||||
end
|
||||
rawset(self, DEBUGGING, true)
|
||||
end
|
||||
|
||||
function AceLocale.prototype:EnableDynamicLocales(override)
|
||||
AceLocale.argCheck(self, override, 2, "boolean", "nil")
|
||||
if not override and rawget(self, BASE_TRANSLATIONS) then
|
||||
AceLocale.error(self, "Cannot enable dynamic locales after a translation has been registered.")
|
||||
end
|
||||
if not rawget(self, DYNAMIC_LOCALES) then
|
||||
rawset(self, DYNAMIC_LOCALES, true)
|
||||
if rawget(self, BASE_LOCALE) then
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
rawset(self, TRANSLATION_TABLES, {})
|
||||
end
|
||||
self[TRANSLATION_TABLES][self[BASE_LOCALE]] = self[BASE_TRANSLATIONS]
|
||||
self[TRANSLATION_TABLES][self[CURRENT_LOCALE]] = self[TRANSLATIONS]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceLocale.prototype:RegisterTranslations(locale, func)
|
||||
AceLocale.argCheck(self, locale, 2, "string")
|
||||
AceLocale.argCheck(self, func, 3, "function")
|
||||
|
||||
if locale == rawget(self, BASE_LOCALE) then
|
||||
AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale)
|
||||
end
|
||||
|
||||
if rawget(self, BASE_TRANSLATIONS) and GetLocale() ~= locale then
|
||||
if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
rawset(self, TRANSLATION_TABLES, {})
|
||||
end
|
||||
if self[TRANSLATION_TABLES][locale] then
|
||||
AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale)
|
||||
end
|
||||
local t = func()
|
||||
func = nil
|
||||
if type(t) ~= "table" then
|
||||
AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t))
|
||||
end
|
||||
self[TRANSLATION_TABLES][locale] = t
|
||||
t = nil
|
||||
end
|
||||
func = nil
|
||||
return
|
||||
end
|
||||
local t = func()
|
||||
func = nil
|
||||
if type(t) ~= "table" then
|
||||
AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t))
|
||||
end
|
||||
|
||||
rawset(self, TRANSLATIONS, t)
|
||||
if not rawget(self, BASE_TRANSLATIONS) then
|
||||
rawset(self, BASE_TRANSLATIONS, t)
|
||||
rawset(self, BASE_LOCALE, locale)
|
||||
for key,value in pairs(t) do
|
||||
if value == true then
|
||||
t[key] = key
|
||||
end
|
||||
end
|
||||
else
|
||||
for key, value in pairs(self[TRANSLATIONS]) do
|
||||
if not rawget(self[BASE_TRANSLATIONS], key) then
|
||||
AceLocale.error(self, "Improper translation exists. %q is likely misspelled for locale %s.", key, locale)
|
||||
end
|
||||
if value == true then
|
||||
AceLocale.error(self, "Can only accept true as a value on the base locale. %q is the base locale, %q is not.", rawget(self, BASE_LOCALE), locale)
|
||||
end
|
||||
end
|
||||
end
|
||||
rawset(self, CURRENT_LOCALE, locale)
|
||||
refixInstance(self)
|
||||
if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
rawset(self, TRANSLATION_TABLES, {})
|
||||
end
|
||||
self[TRANSLATION_TABLES][locale] = t
|
||||
end
|
||||
t = nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:SetLocale(locale)
|
||||
AceLocale.argCheck(self, locale, 2, "string", "boolean")
|
||||
if not rawget(self, DYNAMIC_LOCALES) then
|
||||
AceLocale.error(self, "Cannot call `SetLocale' without first calling `EnableDynamicLocales'.")
|
||||
end
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
AceLocale.error(self, "Cannot call `SetLocale' without first calling `RegisterTranslations'.")
|
||||
end
|
||||
if locale == true then
|
||||
locale = GetLocale()
|
||||
if not self[TRANSLATION_TABLES][locale] then
|
||||
locale = self[BASE_LOCALE]
|
||||
end
|
||||
end
|
||||
|
||||
if self[CURRENT_LOCALE] == locale then
|
||||
return
|
||||
end
|
||||
|
||||
if not self[TRANSLATION_TABLES][locale] then
|
||||
AceLocale.error(self, "Locale %q not registered.", locale)
|
||||
end
|
||||
|
||||
self[TRANSLATIONS] = self[TRANSLATION_TABLES][locale]
|
||||
self[CURRENT_LOCALE] = locale
|
||||
refixInstance(self)
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetLocale()
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
AceLocale.error(self, "Cannot call `GetLocale' without first calling `RegisterTranslations'.")
|
||||
end
|
||||
return self[CURRENT_LOCALE]
|
||||
end
|
||||
|
||||
local function iter(t, position)
|
||||
return (next(t, position))
|
||||
end
|
||||
|
||||
function AceLocale.prototype:IterateAvailableLocales()
|
||||
if not rawget(self, DYNAMIC_LOCALES) then
|
||||
AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `EnableDynamicLocales'.")
|
||||
end
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `RegisterTranslations'.")
|
||||
end
|
||||
return iter, self[TRANSLATION_TABLES], nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:HasLocale(locale)
|
||||
if not rawget(self, DYNAMIC_LOCALES) then
|
||||
AceLocale.error(self, "Cannot call `HasLocale' without first calling `EnableDynamicLocales'.")
|
||||
end
|
||||
AceLocale.argCheck(self, locale, 2, "string")
|
||||
return rawget(self, TRANSLATION_TABLES) and self[TRANSLATION_TABLES][locale] ~= nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:SetStrictness(strict)
|
||||
AceLocale.argCheck(self, strict, 2, "boolean")
|
||||
local mt = getmetatable(self)
|
||||
if not mt then
|
||||
AceLocale.error(self, "Cannot call `SetStrictness' without a metatable.")
|
||||
end
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered.")
|
||||
end
|
||||
rawset(self, STRICTNESS, strict)
|
||||
refixInstance(self)
|
||||
end
|
||||
|
||||
local function initReverse(self)
|
||||
rawset(self, REVERSE_TRANSLATIONS, {})
|
||||
local alpha = self[TRANSLATIONS]
|
||||
local bravo = self[REVERSE_TRANSLATIONS]
|
||||
for base, localized in pairs(alpha) do
|
||||
bravo[localized] = base
|
||||
end
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetTranslation(text)
|
||||
AceLocale.argCheck(self, text, 1, "string", "number")
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
return self[text]
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetStrictTranslation(text)
|
||||
AceLocale.argCheck(self, text, 1, "string", "number")
|
||||
local x = rawget(self, TRANSLATIONS)
|
||||
if not x then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
local value = rawget(x, text)
|
||||
if value == nil then
|
||||
AceLocale.error(self, "Translation %q does not exist for locale %s", text, self[CURRENT_LOCALE])
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetReverseTranslation(text)
|
||||
local x = rawget(self, REVERSE_TRANSLATIONS)
|
||||
if not x then
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
initReverse(self)
|
||||
x = self[REVERSE_TRANSLATIONS]
|
||||
end
|
||||
local translation = x[text]
|
||||
if not translation then
|
||||
AceLocale.error(self, "Reverse translation for %q does not exist", text)
|
||||
end
|
||||
return translation
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetIterator()
|
||||
local x = rawget(self, TRANSLATIONS)
|
||||
if not x then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
return next, x, nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetReverseIterator()
|
||||
local x = rawget(self, REVERSE_TRANSLATIONS)
|
||||
if not x then
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
initReverse(self)
|
||||
x = self[REVERSE_TRANSLATIONS]
|
||||
end
|
||||
return next, x, nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:HasTranslation(text)
|
||||
AceLocale.argCheck(self, text, 1, "string", "number")
|
||||
local x = rawget(self, TRANSLATIONS)
|
||||
if not x then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
return rawget(x, text) and true
|
||||
end
|
||||
|
||||
function AceLocale.prototype:HasReverseTranslation(text)
|
||||
local x = rawget(self, REVERSE_TRANSLATIONS)
|
||||
if not x then
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
initReverse(self)
|
||||
x = self[REVERSE_TRANSLATIONS]
|
||||
end
|
||||
return x[text] and true
|
||||
end
|
||||
|
||||
function AceLocale.prototype:Debug()
|
||||
if not rawget(self, DEBUGGING) then
|
||||
return
|
||||
end
|
||||
local words = {}
|
||||
local locales = {"enUS", "deDE", "frFR", "koKR", "zhCN", "zhTW", "esES"}
|
||||
local localizations = {}
|
||||
DEFAULT_CHAT_FRAME:AddMessage("--- AceLocale Debug ---")
|
||||
for _,locale in ipairs(locales) do
|
||||
if not self[TRANSLATION_TABLES][locale] then
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q not found", locale))
|
||||
else
|
||||
localizations[locale] = self[TRANSLATION_TABLES][locale]
|
||||
end
|
||||
end
|
||||
local localeDebug = {}
|
||||
for locale, localization in pairs(localizations) do
|
||||
localeDebug[locale] = {}
|
||||
for word in pairs(localization) do
|
||||
if type(localization[word]) == "table" then
|
||||
if type(words[word]) ~= "table" then
|
||||
words[word] = {}
|
||||
end
|
||||
for bit in pairs(localization[word]) do
|
||||
if type(localization[word][bit]) == "string" then
|
||||
words[word][bit] = true
|
||||
end
|
||||
end
|
||||
elseif type(localization[word]) == "string" then
|
||||
words[word] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
for word in pairs(words) do
|
||||
if type(words[word]) == "table" then
|
||||
for bit in pairs(words[word]) do
|
||||
for locale, localization in pairs(localizations) do
|
||||
if not rawget(localization, word) or not localization[word][bit] then
|
||||
localeDebug[locale][word .. "::" .. bit] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for locale, localization in pairs(localizations) do
|
||||
if not rawget(localization, word) then
|
||||
localeDebug[locale][word] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for locale, t in pairs(localeDebug) do
|
||||
if not next(t) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q complete", locale))
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q missing:", locale))
|
||||
for word in pairs(t) do
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format(" %q", word))
|
||||
end
|
||||
end
|
||||
end
|
||||
DEFAULT_CHAT_FRAME:AddMessage("--- End AceLocale Debug ---")
|
||||
end
|
||||
|
||||
setmetatable(AceLocale.prototype, {
|
||||
__index = function(self, k)
|
||||
if type(k) ~= "table" and k ~= 0 and k ~= "GetLibraryVersion" and k ~= "error" and k ~= "assert" and k ~= "argCheck" and k ~= "pcall" then -- HACK: remove "GetLibraryVersion" and such later.
|
||||
AceLocale.error(lastSelf or self, "Translation %q does not exist.", k)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
})
|
||||
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
AceLocale = self
|
||||
|
||||
self.frame = oldLib and oldLib.frame or CreateFrame("Frame")
|
||||
self.registry = oldLib and oldLib.registry or {}
|
||||
self.BASE_TRANSLATIONS = oldLib and oldLib.BASE_TRANSLATIONS or {}
|
||||
self.DEBUGGING = oldLib and oldLib.DEBUGGING or {}
|
||||
self.TRANSLATIONS = oldLib and oldLib.TRANSLATIONS or {}
|
||||
self.BASE_LOCALE = oldLib and oldLib.BASE_LOCALE or {}
|
||||
self.TRANSLATION_TABLES = oldLib and oldLib.TRANSLATION_TABLES or {}
|
||||
self.REVERSE_TRANSLATIONS = oldLib and oldLib.REVERSE_TRANSLATIONS or {}
|
||||
self.STRICTNESS = oldLib and oldLib.STRICTNESS or {}
|
||||
self.NAME = oldLib and oldLib.NAME or {}
|
||||
self.DYNAMIC_LOCALES = oldLib and oldLib.DYNAMIC_LOCALES or {}
|
||||
self.CURRENT_LOCALE = oldLib and oldLib.CURRENT_LOCALE or {}
|
||||
|
||||
BASE_TRANSLATIONS = self.BASE_TRANSLATIONS
|
||||
DEBUGGING = self.DEBUGGING
|
||||
TRANSLATIONS = self.TRANSLATIONS
|
||||
BASE_LOCALE = self.BASE_LOCALE
|
||||
TRANSLATION_TABLES = self.TRANSLATION_TABLES
|
||||
REVERSE_TRANSLATIONS = self.REVERSE_TRANSLATIONS
|
||||
STRICTNESS = self.STRICTNESS
|
||||
NAME = self.NAME
|
||||
DYNAMIC_LOCALES = self.DYNAMIC_LOCALES
|
||||
CURRENT_LOCALE = self.CURRENT_LOCALE
|
||||
|
||||
|
||||
local GetTime = GetTime
|
||||
local timeUntilClear = GetTime() + 5
|
||||
scheduleClear = function()
|
||||
if next(newRegistries) then
|
||||
self.frame:Show()
|
||||
timeUntilClear = GetTime() + 5
|
||||
end
|
||||
end
|
||||
|
||||
if not self.registry then
|
||||
self.registry = {}
|
||||
else
|
||||
for name, instance in pairs(self.registry) do
|
||||
local name = name
|
||||
local mt = getmetatable(instance)
|
||||
setmetatable(instance, nil)
|
||||
instance[NAME] = name
|
||||
local strict
|
||||
if instance[STRICTNESS] ~= nil then
|
||||
strict = instance[STRICTNESS]
|
||||
elseif instance[TRANSLATIONS] ~= instance[BASE_TRANSLATIONS] then
|
||||
if getmetatable(instance[TRANSLATIONS]).__index == oldLib.prototype then
|
||||
strict = true
|
||||
end
|
||||
end
|
||||
instance[STRICTNESS] = strict and true or false
|
||||
refixInstance(instance)
|
||||
end
|
||||
end
|
||||
|
||||
self.frame:SetScript("OnEvent", scheduleClear)
|
||||
self.frame:SetScript("OnUpdate", function() -- (this, elapsed)
|
||||
if timeUntilClear - GetTime() <= 0 then
|
||||
self.frame:Hide()
|
||||
for k in pairs(newRegistries) do
|
||||
clearCache(k)
|
||||
newRegistries[k] = nil
|
||||
k = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
self.frame:UnregisterAllEvents()
|
||||
self.frame:RegisterEvent("ADDON_LOADED")
|
||||
self.frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
self.frame:Show()
|
||||
|
||||
if oldDeactivate then
|
||||
oldDeactivate(oldLib)
|
||||
end
|
||||
end
|
||||
|
||||
AceLibrary:Register(AceLocale, MAJOR_VERSION, MINOR_VERSION, activate)
|
||||
@@ -0,0 +1,404 @@
|
||||
--[[
|
||||
Name: AceModuleCore-2.0
|
||||
Revision: $Rev: 12441 $
|
||||
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/AceModuleCore-2.0
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceModuleCore-2.0
|
||||
Description: Mixin to provide a module system so that modules or plugins can
|
||||
use an addon as its core.
|
||||
Dependencies: AceLibrary, AceOO-2.0, AceAddon-2.0, Compost-2.0 (optional)
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceModuleCore-2.0"
|
||||
local MINOR_VERSION = "$Revision: 12441 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
||||
|
||||
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 new, del
|
||||
do
|
||||
local list = setmetatable({}, {__mode = 'k'})
|
||||
function new()
|
||||
local t = next(list)
|
||||
if t then
|
||||
list[t] = nil
|
||||
return t
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
function del(t)
|
||||
for k in pairs(t) do
|
||||
t[k] = nil
|
||||
end
|
||||
table_setn(t, 0)
|
||||
list[t] = true
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
||||
local AceModuleCore = AceOO.Mixin {
|
||||
"NewModule",
|
||||
"HasModule",
|
||||
"GetModule",
|
||||
"IsModule",
|
||||
"IterateModules",
|
||||
"SetModuleMixins",
|
||||
"SetModuleClass",
|
||||
"IsModuleActive",
|
||||
"ToggleModuleActive"
|
||||
}
|
||||
|
||||
local Compost = AceLibrary:HasInstance("Compost-2.0") and AceLibrary("Compost-2.0")
|
||||
|
||||
local function getlibrary(lib)
|
||||
if type(lib) == "string" then
|
||||
return AceLibrary(lib)
|
||||
else
|
||||
return lib
|
||||
end
|
||||
end
|
||||
|
||||
local tmp
|
||||
function AceModuleCore:NewModule(name, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not self.modules then
|
||||
AceModuleCore:error("CreatePrototype() must be called before attempting to create a new module.", 2)
|
||||
end
|
||||
AceModuleCore:argCheck(name, 2, "string")
|
||||
if string.len(name) == 0 then
|
||||
AceModuleCore:error("Bad argument #2 to `NewModule`, string must not be empty")
|
||||
end
|
||||
if self.modules[name] then
|
||||
AceModuleCore:error("The module %q has already been registered", name)
|
||||
end
|
||||
|
||||
if not tmp then
|
||||
tmp = {}
|
||||
end
|
||||
if a1 then table.insert(tmp, a1)
|
||||
if a2 then table.insert(tmp, a2)
|
||||
if a3 then table.insert(tmp, a3)
|
||||
if a4 then table.insert(tmp, a4)
|
||||
if a5 then table.insert(tmp, a5)
|
||||
if a6 then table.insert(tmp, a6)
|
||||
if a7 then table.insert(tmp, a7)
|
||||
if a8 then table.insert(tmp, a8)
|
||||
if a9 then table.insert(tmp, a9)
|
||||
if a10 then table.insert(tmp, a10)
|
||||
if a11 then table.insert(tmp, a11)
|
||||
if a12 then table.insert(tmp, a12)
|
||||
if a13 then table.insert(tmp, a13)
|
||||
if a14 then table.insert(tmp, a14)
|
||||
if a15 then table.insert(tmp, a15)
|
||||
if a16 then table.insert(tmp, a16)
|
||||
if a17 then table.insert(tmp, a17)
|
||||
if a18 then table.insert(tmp, a18)
|
||||
if a19 then table.insert(tmp, a19)
|
||||
if a20 then table.insert(tmp, a20)
|
||||
end end end end end end end end end end end end end end end end end end end end
|
||||
for k,v in ipairs(tmp) do
|
||||
tmp[k] = getlibrary(v)
|
||||
end
|
||||
|
||||
if self.moduleMixins then
|
||||
for _,mixin in ipairs(self.moduleMixins) do
|
||||
local exists = false
|
||||
for _,v in ipairs(tmp) do
|
||||
if mixin == v then
|
||||
exists = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not exists then
|
||||
table.insert(tmp, mixin)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local module = AceOO.Classpool(self.moduleClass, unpack(tmp)):new(name)
|
||||
self.modules[name] = module
|
||||
module.name = name
|
||||
module.title = name
|
||||
|
||||
AceModuleCore.totalModules[module] = self
|
||||
|
||||
for k in pairs(tmp) do
|
||||
tmp[k] = nil
|
||||
end
|
||||
table_setn(tmp, 0)
|
||||
return module
|
||||
end
|
||||
|
||||
function AceModuleCore:HasModule(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if a1 then if not self.modules[a1] then return false end
|
||||
if a2 then if not self.modules[a2] then return false end
|
||||
if a3 then if not self.modules[a3] then return false end
|
||||
if a4 then if not self.modules[a4] then return false end
|
||||
if a5 then if not self.modules[a5] then return false end
|
||||
if a6 then if not self.modules[a6] then return false end
|
||||
if a7 then if not self.modules[a7] then return false end
|
||||
if a8 then if not self.modules[a8] then return false end
|
||||
if a9 then if not self.modules[a9] then return false end
|
||||
if a10 then if not self.modules[a10] then return false end
|
||||
if a11 then if not self.modules[a11] then return false end
|
||||
if a12 then if not self.modules[a12] then return false end
|
||||
if a13 then if not self.modules[a13] then return false end
|
||||
if a14 then if not self.modules[a14] then return false end
|
||||
if a15 then if not self.modules[a15] then return false end
|
||||
if a16 then if not self.modules[a16] then return false end
|
||||
if a17 then if not self.modules[a17] then return false end
|
||||
if a18 then if not self.modules[a18] then return false end
|
||||
if a19 then if not self.modules[a19] then return false end
|
||||
if a20 then if not self.modules[a20] then return false end
|
||||
end end end end end end end end end end end end end end end end end end end end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function AceModuleCore:GetModule(name)
|
||||
if not self.modules then
|
||||
AceModuleCore:error("Error initializing class. Please report error.")
|
||||
end
|
||||
if not self.modules[name] then
|
||||
AceModuleCore:error("Cannot find module %q.", name)
|
||||
end
|
||||
return self.modules[name]
|
||||
end
|
||||
|
||||
function AceModuleCore:IsModule(module)
|
||||
if self == AceModuleCore then
|
||||
return AceModuleCore.totalModules[module]
|
||||
else
|
||||
for k,v in pairs(self.modules) do
|
||||
if v == module then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function AceModuleCore:IterateModules()
|
||||
local t = new()
|
||||
for k in pairs(self.modules) do
|
||||
table.insert(t, k)
|
||||
end
|
||||
table.sort(t)
|
||||
local i = 0
|
||||
return function()
|
||||
i = i + 1
|
||||
local x = t[i]
|
||||
if x then
|
||||
return x, self.modules[x]
|
||||
else
|
||||
t = del(t)
|
||||
return nil
|
||||
end
|
||||
end, nil, nil
|
||||
end
|
||||
|
||||
function AceModuleCore:SetModuleMixins(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if self.moduleMixins then
|
||||
AceModuleCore:error('Cannot call "SetModuleMixins" twice')
|
||||
elseif not self.modules then
|
||||
AceModuleCore:error("Error initializing class. Please report error.")
|
||||
elseif next(self.modules) then
|
||||
AceModuleCore:error('Cannot call "SetModuleMixins" after "NewModule" has been called.')
|
||||
end
|
||||
|
||||
self.moduleMixins = Compost and Compost:Acquire(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) or {a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20}
|
||||
for k,v in ipairs(self.moduleMixins) do
|
||||
self.moduleMixins[k] = getlibrary(v)
|
||||
end
|
||||
end
|
||||
|
||||
function AceModuleCore:SetModuleClass(class)
|
||||
class = getlibrary(class)
|
||||
AceModuleCore:assert(AceOO.inherits(class, AceOO.Class), "Bad argument #2 to `SetModuleClass' (Class expected)")
|
||||
if not self.modules then
|
||||
AceModuleCore:error("Error initializing class. Please report error.")
|
||||
end
|
||||
if self.customModuleClass then
|
||||
AceModuleCore:error("Cannot call `SetModuleClass' twice.")
|
||||
end
|
||||
self.customModuleClass = true
|
||||
self.moduleClass = class
|
||||
self.modulePrototype = class.prototype
|
||||
end
|
||||
|
||||
function AceModuleCore:ToggleModuleActive(module, state)
|
||||
AceModuleCore:argCheck(module, 2, "table", "string")
|
||||
AceModuleCore:argCheck(state, 3, "nil", "boolean")
|
||||
|
||||
if type(module) == "string" then
|
||||
if not self:HasModule(module) then
|
||||
AceModuleCore:error("Cannot find module %q", module)
|
||||
end
|
||||
module = self:GetModule(module)
|
||||
else
|
||||
if not self:IsModule(module) then
|
||||
AceModuleCore:error("%q is not a module", module)
|
||||
end
|
||||
end
|
||||
|
||||
local disable
|
||||
if state == nil then
|
||||
disable = self:IsModuleActive(module)
|
||||
else
|
||||
disable = not state
|
||||
if disable ~= self:IsModuleActive(module) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if type(module.ToggleActive) == "function" then
|
||||
return module:ToggleActive(not disable)
|
||||
elseif AceOO.inherits(self, "AceDB-2.0") then
|
||||
if not self.db or not self.db.raw then
|
||||
AceModuleCore:error("Cannot toggle a module until `RegisterDB' has been called and `ADDON_LOADED' has been fireed.")
|
||||
end
|
||||
if type(self.db.raw.disabledModules) ~= "table" then
|
||||
self.db.raw.disabledModules = Compost and Compost:Acquire() or {}
|
||||
end
|
||||
local _,profile = self:GetProfile()
|
||||
if type(self.db.raw.disabledModules[profile]) ~= "table" then
|
||||
self.db.raw.disabledModules[profile] = Compost and Compost:Acquire() or {}
|
||||
end
|
||||
if type(self.db.raw.disabledModules[profile][module.name]) ~= "table" then
|
||||
self.db.raw.disabledModules[profile][module.name] = disable or nil
|
||||
end
|
||||
if not disable then
|
||||
if not next(self.db.raw.disabledModules[profile]) then
|
||||
if Compost then
|
||||
Compost:Reclaim(self.db.raw.disabledModules[profile])
|
||||
end
|
||||
self.db.raw.disabledModules[profile] = nil
|
||||
end
|
||||
if not next(self.db.raw.disabledModules) then
|
||||
if Compost then
|
||||
Compost:Reclaim(self.db.raw.disabledModules)
|
||||
end
|
||||
self.db.raw.disabledModules = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
if type(self.disabledModules) ~= "table" then
|
||||
self.disabledModules = Compost and Compost:Acquire() or {}
|
||||
end
|
||||
self.disabledModules[module.name] = disable or nil
|
||||
end
|
||||
if AceOO.inherits(module, "AceAddon-2.0") then
|
||||
local AceAddon = AceLibrary("AceAddon-2.0")
|
||||
if not AceAddon.addonsStarted[module] then
|
||||
return
|
||||
end
|
||||
end
|
||||
if not disable then
|
||||
if type(module.OnEnable) == "function" then
|
||||
module:OnEnable()
|
||||
end
|
||||
else
|
||||
local current = module.class
|
||||
while true do
|
||||
if current == AceOO.Class then
|
||||
break
|
||||
end
|
||||
if current.mixins then
|
||||
for mixin in pairs(current.mixins) do
|
||||
if type(mixin.OnEmbedDisable) == "function" then
|
||||
mixin:OnEmbedDisable(module)
|
||||
end
|
||||
end
|
||||
end
|
||||
current = current.super
|
||||
end
|
||||
if type(module.OnDisable) == "function" then
|
||||
module:OnDisable()
|
||||
end
|
||||
end
|
||||
return not disable
|
||||
end
|
||||
|
||||
function AceModuleCore:IsModuleActive(module)
|
||||
AceModuleCore:argCheck(module, 2, "table", "string")
|
||||
|
||||
if AceModuleCore == self then
|
||||
self:argCheck(module, 2, "table")
|
||||
|
||||
local core = AceModuleCore.totalModules[module]
|
||||
if not core then
|
||||
self:error("Bad argument #2 to `IsModuleActive'. Not a module")
|
||||
end
|
||||
return core:IsModuleActive(module)
|
||||
end
|
||||
|
||||
if type(module) == "string" then
|
||||
if not self:HasModule(module) then
|
||||
AceModuleCore:error("Cannot find module %q", module)
|
||||
end
|
||||
module = self:GetModule(module)
|
||||
else
|
||||
if not self:IsModule(module) then
|
||||
AceModuleCore:error("%q is not a module", module)
|
||||
end
|
||||
end
|
||||
|
||||
if type(module.IsActive) == "function" then
|
||||
return module:IsActive()
|
||||
elseif AceOO.inherits(self, "AceDB-2.0") then
|
||||
local _,profile = self:GetProfile()
|
||||
return not self.db or not self.db.raw or not self.db.raw.disabledModules or not self.db.raw.disabledModules[profile] or not self.db.raw.disabledModules[profile][module.name]
|
||||
else
|
||||
return not self.disabledModules or not self.disabledModules[module.name]
|
||||
end
|
||||
end
|
||||
|
||||
function AceModuleCore:OnInstanceInit(target)
|
||||
if target.modules then
|
||||
AceModuleCore:error("OnInstanceInit cannot be called twice")
|
||||
end
|
||||
target.modules = Compost and Compost:Acquire() or {}
|
||||
|
||||
target.moduleClass = AceOO.Class("AceAddon-2.0")
|
||||
target.modulePrototype = target.moduleClass.prototype
|
||||
end
|
||||
|
||||
AceModuleCore.OnManualEmbed = AceModuleCore.OnInstanceInit
|
||||
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
AceModuleCore = self
|
||||
|
||||
self.super.activate(self, oldLib, oldDeactivate)
|
||||
|
||||
if oldLib then
|
||||
self.totalModules = oldLib.totalModules
|
||||
end
|
||||
if not self.totalModules then
|
||||
self.totalModules = {}
|
||||
end
|
||||
end
|
||||
|
||||
local function external(self, major, instance)
|
||||
if major == "Compost-2.0" then
|
||||
Compost = instance
|
||||
end
|
||||
end
|
||||
|
||||
AceLibrary:Register(AceModuleCore, MAJOR_VERSION, MINOR_VERSION, activate)
|
||||
AceModuleCore = AceLibrary(MAJOR_VERSION)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,136 @@
|
||||
--[[
|
||||
Name: Babble-Class-2.2
|
||||
Revision: $Rev: 14410 $
|
||||
Author(s): ckknight (ckknight@gmail.com)
|
||||
Website: http://ckknight.wowinterface.com/
|
||||
Documentation: http://wiki.wowace.com/index.php/Babble-Class-2.2
|
||||
SVN: http://svn.wowace.com/root/trunk/Babble-2.2/Babble-Class-2.2
|
||||
Description: A library to provide localizations for classes.
|
||||
Dependencies: AceLibrary, AceLocale-2.2
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "Babble-Class-2.2"
|
||||
local MINOR_VERSION = tonumber(string.sub("$Revision: 14410 $", 12, -3))
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
|
||||
if not AceLibrary:HasInstance("AceLocale-2.2") then error(MAJOR_VERSION .. " requires AceLocale-2.2") end
|
||||
|
||||
local _, x = AceLibrary("AceLocale-2.2"):GetLibraryVersion()
|
||||
MINOR_VERSION = MINOR_VERSION * 100000 + x
|
||||
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
local BabbleClass = AceLibrary("AceLocale-2.2"):new(MAJOR_VERSION)
|
||||
|
||||
-- uncomment below for debug information
|
||||
-- BabbleClass:EnableDebugging()
|
||||
|
||||
BabbleClass:RegisterTranslations("enUS", function()
|
||||
return {
|
||||
["Warlock"] = true,
|
||||
["Warrior"] = true,
|
||||
["Hunter"] = true,
|
||||
["Mage"] = true,
|
||||
["Priest"] = true,
|
||||
["Druid"] = true,
|
||||
["Paladin"] = true,
|
||||
["Shaman"] = true,
|
||||
["Rogue"] = true,
|
||||
}
|
||||
end)
|
||||
|
||||
BabbleClass:RegisterTranslations("deDE", function()
|
||||
return {
|
||||
["Warlock"] = "Hexenmeister",
|
||||
["Warrior"] = "Krieger",
|
||||
["Hunter"] = "Jäger",
|
||||
["Mage"] = "Magier",
|
||||
["Priest"] = "Priester",
|
||||
["Druid"] = "Druide",
|
||||
["Paladin"] = "Paladin",
|
||||
["Shaman"] = "Schamane",
|
||||
["Rogue"] = "Schurke",
|
||||
}
|
||||
end)
|
||||
|
||||
BabbleClass:RegisterTranslations("frFR", function()
|
||||
return {
|
||||
["Warlock"] = "D\195\169moniste",
|
||||
["Warrior"] = "Guerrier",
|
||||
["Hunter"] = "Chasseur",
|
||||
["Mage"] = "Mage",
|
||||
["Priest"] = "Pr\195\170tre",
|
||||
["Druid"] = "Druide",
|
||||
["Paladin"] = "Paladin",
|
||||
["Shaman"] = "Chaman",
|
||||
["Rogue"] = "Voleur",
|
||||
}
|
||||
end)
|
||||
|
||||
BabbleClass:RegisterTranslations("zhCN", function()
|
||||
return {
|
||||
["Warlock"] = "术士",
|
||||
["Warrior"] = "战士",
|
||||
["Hunter"] = "猎人",
|
||||
["Mage"] = "法师",
|
||||
["Priest"] = "牧师",
|
||||
["Druid"] = "德鲁伊",
|
||||
["Paladin"] = "圣骑士",
|
||||
["Shaman"] = "萨满祭司",
|
||||
["Rogue"] = "盗贼",
|
||||
}
|
||||
end)
|
||||
|
||||
BabbleClass:RegisterTranslations("zhTW", function()
|
||||
return {
|
||||
["Warlock"] = "術士",
|
||||
["Warrior"] = "戰士",
|
||||
["Hunter"] = "獵人",
|
||||
["Mage"] = "法師",
|
||||
["Priest"] = "牧師",
|
||||
["Druid"] = "德魯伊",
|
||||
["Paladin"] = "聖騎士",
|
||||
["Shaman"] = "薩滿",
|
||||
["Rogue"] = "盜賊",
|
||||
}
|
||||
end)
|
||||
|
||||
BabbleClass:RegisterTranslations("koKR", function()
|
||||
return {
|
||||
["Warlock"] = "흑마법사",
|
||||
["Warrior"] = "전사",
|
||||
["Hunter"] = "사냥꾼",
|
||||
["Mage"] = "마법사",
|
||||
["Priest"] = "사제",
|
||||
["Druid"] = "드루이드",
|
||||
["Paladin"] = "성기사",
|
||||
["Shaman"] = "주술사",
|
||||
["Rogue"] = "도적",
|
||||
}
|
||||
end)
|
||||
|
||||
BabbleClass:Debug()
|
||||
BabbleClass:SetStrictness(true)
|
||||
|
||||
function BabbleClass:GetColor(class)
|
||||
self:argCheck(class, 2, "string")
|
||||
if self:HasReverseTranslation(class) then
|
||||
class = string.upper(self:GetReverseTranslation(class))
|
||||
else
|
||||
class = string.upper(class)
|
||||
end
|
||||
if RAID_CLASS_COLORS and RAID_CLASS_COLORS[class] then
|
||||
return RAID_CLASS_COLORS[class].r, RAID_CLASS_COLORS[class].g, RAID_CLASS_COLORS[class].b
|
||||
end
|
||||
return 0.63, 0.63, 0.63
|
||||
end
|
||||
|
||||
function BabbleClass:GetHexColor(class)
|
||||
self:argCheck(class, 2, "string")
|
||||
local r, g, b = self:GetColor(class)
|
||||
return string.format("%02x%02x%02x", r * 255, g * 255, b * 255)
|
||||
end
|
||||
|
||||
AceLibrary:Register(BabbleClass, MAJOR_VERSION, MINOR_VERSION)
|
||||
BabbleClass = nil
|
||||
@@ -0,0 +1,277 @@
|
||||
|
||||
--[[
|
||||
Name: Compost-2.0
|
||||
Revision: $Rev: 11579 $
|
||||
Author: Tekkub Stoutwrithe (tekkub@gmail.com)
|
||||
Website: http://wiki.wowace.com/index.php/CompostLib
|
||||
Documentation: http://wiki.wowace.com/index.php/Compost-2.0_API_Documentation
|
||||
SVN: svn://svn.wowace.com/root/trunk/CompostLib/Compost-2.0
|
||||
Description: Recycle tables to reduce garbage generation
|
||||
Dependencies: AceLibrary
|
||||
]]
|
||||
|
||||
local vmajor, vminor = "Compost-2.0", "$Revision: 11579 $"
|
||||
|
||||
if not AceLibrary then error(vmajor .. " requires AceLibrary.") end
|
||||
if not AceLibrary:IsNewVersion(vmajor, vminor) then return end
|
||||
|
||||
local lib = {}
|
||||
|
||||
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
|
||||
|
||||
-- Activate a new instance of this library
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
if oldLib then -- if upgrading
|
||||
self.var, self.k = oldLib.var, oldLib.k
|
||||
else
|
||||
self.k = { -- Constants go here
|
||||
maxcache = 10, -- I think this is a good number, I'll change it later if necessary
|
||||
}
|
||||
self.var = { -- "Local" variables go here
|
||||
cache = {},
|
||||
secondarycache = {},
|
||||
}
|
||||
|
||||
-- This makes the secondary cache table a weak table, any values in it will be reclaimed
|
||||
-- during a GC if there are no other references to them
|
||||
setmetatable(self.var.secondarycache, {__mode = "v"})
|
||||
end
|
||||
if not self.var.tablechecks then
|
||||
self.var.tablechecks = {}
|
||||
setmetatable(self.var.tablechecks, {__mode = "kv"})
|
||||
for i,v in ipairs(self.var.cache) do self.var.tablechecks[v] = true end
|
||||
for i,v in ipairs(self.var.secondarycache) do self.var.tablechecks[v] = true end
|
||||
end
|
||||
if oldDeactivate then oldDeactivate(oldLib) end
|
||||
end
|
||||
|
||||
|
||||
-- Removes an empty table from the cache and returns it
|
||||
-- or generates a new table if none available
|
||||
function lib:GetTable()
|
||||
if self.var.disabled then return {} end
|
||||
|
||||
if table.getn(self.var.cache) > 0 then
|
||||
for i in pairs(self.var.cache) do
|
||||
local t = table.remove(self.var.cache, i)
|
||||
self.var.tablechecks[t] = nil
|
||||
if next(t) then -- Table has been modified, someone holds a ref still, discard it
|
||||
error("Someone is modifying tables reclaimed by Compost!")
|
||||
self:IncDec("numdiscarded", 1)
|
||||
else -- It's clean, we think... return it.
|
||||
self:IncDec("totn", -1)
|
||||
self:IncDec("numrecycled", 1)
|
||||
return t
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if next(self.var.secondarycache) then
|
||||
for i in pairs(self.var.secondarycache) do
|
||||
local t = table.remove(self.var.secondarycache, i)
|
||||
self.var.tablechecks[t] = nil
|
||||
if next(t) then -- Table has been modified, someone holds a ref still, discard it
|
||||
error("Someone is modifying tables reclaimed by Compost!")
|
||||
self:IncDec("numdiscarded", 1)
|
||||
else -- It's clean, we think... return it.
|
||||
self:IncDec("totn", -1)
|
||||
self:IncDec("numrecycled", 1)
|
||||
return t
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:IncDec("numnew", 1)
|
||||
return {}
|
||||
end
|
||||
|
||||
|
||||
-- Returns a table, populated with any variables passed
|
||||
-- basically: return {a1, a2, ... a20}
|
||||
function lib:Acquire(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
local t = self:GetTable()
|
||||
return self:Populate(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
|
||||
|
||||
-- Acquires a table and fills it with values, hash style
|
||||
-- basically: return {k1 = v1, k2 = v2, ... k10 = v10}
|
||||
function lib:AcquireHash(k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
local t = self:GetTable()
|
||||
return self:PopulateHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
end
|
||||
|
||||
|
||||
-- Erases the table passed, fills it with the args passed, and returns it
|
||||
-- Essentially the same as doing Reclaim then Acquire, except the same table is reused
|
||||
function lib:Recycle(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
t = self:Erase(t)
|
||||
return self:Populate(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
|
||||
|
||||
-- Erases the table passed, fills it with the args passed, and returns it
|
||||
-- Essentially the same as doing Reclaim then AcquireHash, except the same table is reused
|
||||
function lib:RecycleHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
t = self:Erase(t)
|
||||
return self:PopulateHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
end
|
||||
|
||||
|
||||
-- Returns a table to the cache
|
||||
-- All tables referenced inside the passed table will be reclaimed also
|
||||
-- If a depth is passed, Reclaim will call itsself recursivly
|
||||
-- to reclaim all tables contained in t to the depth specified
|
||||
function lib:Reclaim(t, depth)
|
||||
if type(t) ~= "table" or self.var.disabled then return end
|
||||
self:assert(not self.var.tablechecks[t], "Cannot reclaim a table twice")
|
||||
|
||||
if not self:ItemsInSecondaryCache() then self.var.totn = table.getn(self.var.cache) end
|
||||
|
||||
if depth and depth > 0 then
|
||||
for i in pairs(t) do
|
||||
if type(t[i]) == "table" then self:Reclaim(t[i], depth - 1) end
|
||||
end
|
||||
end
|
||||
self:Erase(t)
|
||||
if self.k.maxcache and table.getn(self.var.cache) >= self.k.maxcache then
|
||||
table.insert(self.var.secondarycache, t)
|
||||
else
|
||||
table.insert(self.var.cache, t)
|
||||
end
|
||||
self:IncDec("numreclaim", 1)
|
||||
self:IncDec("totn", 1)
|
||||
self.var.maxn = math.max(self.var.maxn or 0, self.var.totn)
|
||||
self.var.tablechecks[t] = true
|
||||
end
|
||||
|
||||
|
||||
-- Reclaims multiple tables, can take 10 recursive sets or 20 non-recursives,
|
||||
-- or any combination of the two. Pass args in the following manner:
|
||||
-- table1, depth1, tabl2, depth2, table3, table4, table5, depth5, ...
|
||||
function lib:ReclaimMulti(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if not a1 then return end
|
||||
if type(a2) == "number" then
|
||||
self:Reclaim(a1, a2)
|
||||
self:ReclaimMulti(a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
self:Reclaim(a1)
|
||||
self:ReclaimMulti(a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Erases the table passed, nothing more nothing less :)
|
||||
-- Tables referenced inside the passed table are NOT erased
|
||||
function lib:Erase(t)
|
||||
if type(t) ~= "table" then return end
|
||||
if self.var.disabled then return {} end
|
||||
local mem = gcinfo()
|
||||
setmetatable(t, nil)
|
||||
for i in pairs(t) do
|
||||
t[i] = nil
|
||||
end
|
||||
t.reset = 1
|
||||
t.reset = nil
|
||||
table_setn(t, 0)
|
||||
self:IncDec("memfreed", math.abs(gcinfo() - mem))
|
||||
self:IncDec("numerased", 1)
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
-- Fills the table passed with the args passed
|
||||
function lib:Populate(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if not t then return end
|
||||
if a1 ~= nil then table.insert(t, a1) end
|
||||
if a2 ~= nil then table.insert(t, a2) end
|
||||
if a3 ~= nil then table.insert(t, a3) end
|
||||
if a4 ~= nil then table.insert(t, a4) end
|
||||
if a5 ~= nil then table.insert(t, a5) end
|
||||
if a6 ~= nil then table.insert(t, a6) end
|
||||
if a7 ~= nil then table.insert(t, a7) end
|
||||
if a8 ~= nil then table.insert(t, a8) end
|
||||
if a9 ~= nil then table.insert(t, a9) end
|
||||
if a10 ~= nil then table.insert(t, a10) end
|
||||
if a11 ~= nil then table.insert(t, a11) end
|
||||
if a12 ~= nil then table.insert(t, a12) end
|
||||
if a13 ~= nil then table.insert(t, a13) end
|
||||
if a14 ~= nil then table.insert(t, a14) end
|
||||
if a15 ~= nil then table.insert(t, a15) end
|
||||
if a16 ~= nil then table.insert(t, a16) end
|
||||
if a17 ~= nil then table.insert(t, a17) end
|
||||
if a18 ~= nil then table.insert(t, a18) end
|
||||
if a19 ~= nil then table.insert(t, a19) end
|
||||
if a20 ~= nil then table.insert(t, a20) end
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
-- Same as Populate, but takes 10 key-value pairs instead
|
||||
function lib:PopulateHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
if not t then return end
|
||||
if k1 ~= nil then t[k1] = v1 end
|
||||
if k2 ~= nil then t[k2] = v2 end
|
||||
if k3 ~= nil then t[k3] = v3 end
|
||||
if k4 ~= nil then t[k4] = v4 end
|
||||
if k5 ~= nil then t[k5] = v5 end
|
||||
if k6 ~= nil then t[k6] = v6 end
|
||||
if k7 ~= nil then t[k7] = v7 end
|
||||
if k8 ~= nil then t[k8] = v8 end
|
||||
if k9 ~= nil then t[k9] = v9 end
|
||||
if k10 ~= nil then t[k10] = v10 end
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
function lib:IncDec(variable, diff)
|
||||
self.var[variable] = (self.var[variable] or 0) + diff
|
||||
end
|
||||
|
||||
|
||||
function lib:ItemsInSecondaryCache()
|
||||
for i in pairs(self.var.secondarycache) do return true end
|
||||
end
|
||||
|
||||
|
||||
function lib:GetSecondaryCacheSize()
|
||||
local n = 0
|
||||
for i in pairs(self.var.secondarycache) do n = n + 1 end
|
||||
return n
|
||||
end
|
||||
|
||||
|
||||
-- Prints out statistics on table recycling
|
||||
-- /script CompostLib:GetInstance("compost-1"):Stats()
|
||||
function lib:Stats()
|
||||
if self.var.disabled then ChatFrame1:AddMessage("CompostLib is disabled!")
|
||||
else ChatFrame1:AddMessage(
|
||||
string.format(
|
||||
"|cff00ff00New: %d|r | |cffffff00Recycled: %d|r | |cff00ffffMain: %d|r | |cffff0000Secondary: %d|r | |cffff8800Max %d|r | |cff888888Erases: %d|r | |cffff00ffMem Saved: %d KiB|r | |cffff0088Lost to GC: %d",
|
||||
self.var.numnew or 0,
|
||||
self.var.numrecycled or 0,
|
||||
table.getn(self.var.cache),
|
||||
self:GetSecondaryCacheSize(),
|
||||
self.var.maxn or 0,
|
||||
(self.var.numerased or 0) - (self.var.numreclaim or 0),
|
||||
(self.var.memfreed or 0) + 32/1024*(self.var.numrecycled or 0),
|
||||
(self.var.numreclaim or 0) - (self.var.numrecycled or 0) - table.getn(self.var.cache)))
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(lib, { __call = lib.Acquire })
|
||||
|
||||
--------------------------------
|
||||
-- Load this bitch! --
|
||||
--------------------------------
|
||||
AceLibrary:Register(lib, vmajor, vminor, activate)
|
||||
lib = nil
|
||||
@@ -0,0 +1,156 @@
|
||||
--[[
|
||||
Name: Crayon-2.0
|
||||
Revision: $Rev: 7622 $
|
||||
Author(s): ckknight (ckknight@gmail.com)
|
||||
Website: http://ckknight.wowinterface.com/
|
||||
Documentation: http://wiki.wowace.com/index.php/Crayon-2.0
|
||||
SVN: http://svn.wowace.com/root/trunk/CrayonLib/Crayon-2.0
|
||||
Description: A library to provide coloring tools.
|
||||
Dependencies: AceLibrary
|
||||
]]
|
||||
|
||||
--Theondry (theondry@gmail.com) added the purple. yell at me if it's wrong, please
|
||||
|
||||
local MAJOR_VERSION = "Crayon-2.0"
|
||||
local MINOR_VERSION = "$Revision: 7622 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
local Crayon = {}
|
||||
|
||||
Crayon.COLOR_HEX_RED = "ff0000"
|
||||
Crayon.COLOR_HEX_ORANGE = "ff7f00"
|
||||
Crayon.COLOR_HEX_YELLOW = "ffff00"
|
||||
Crayon.COLOR_HEX_GREEN = "00ff00"
|
||||
Crayon.COLOR_HEX_WHITE = "ffffff"
|
||||
Crayon.COLOR_HEX_COPPER = "eda55f"
|
||||
Crayon.COLOR_HEX_SILVER = "c7c7cf"
|
||||
Crayon.COLOR_HEX_GOLD = "ffd700"
|
||||
Crayon.COLOR_HEX_PURPLE = "9980CC"
|
||||
|
||||
function Crayon:Colorize(hexColor, text)
|
||||
return "|cff" .. tostring(hexColor or 'ffffff') .. tostring(text) .. "|r"
|
||||
end
|
||||
function Crayon:Red(text) return self:Colorize(self.COLOR_HEX_RED, text) end
|
||||
function Crayon:Orange(text) return self:Colorize(self.COLOR_HEX_ORANGE, text) end
|
||||
function Crayon:Yellow(text) return self:Colorize(self.COLOR_HEX_YELLOW, text) end
|
||||
function Crayon:Green(text) return self:Colorize(self.COLOR_HEX_GREEN, text) end
|
||||
function Crayon:White(text) return self:Colorize(self.COLOR_HEX_WHITE, text) end
|
||||
function Crayon:Copper(text) return self:Colorize(self.COLOR_HEX_COPPER, text) end
|
||||
function Crayon:Silver(text) return self:Colorize(self.COLOR_HEX_SILVER, text) end
|
||||
function Crayon:Gold(text) return self:Colorize(self.COLOR_HEX_GOLD, text) end
|
||||
function Crayon:Purple(text) return self:Colorize(self.COLOR_HEX_PURPLE, text) end
|
||||
|
||||
local inf = 1/0
|
||||
|
||||
function Crayon:GetThresholdColor(quality, worst, worse, normal, better, best)
|
||||
self:argCheck(quality, 2, "number")
|
||||
if quality ~= quality or quality == inf or quality == -inf then
|
||||
return 1, 1, 1
|
||||
end
|
||||
if not best then
|
||||
worst = 0
|
||||
worse = 0.25
|
||||
normal = 0.5
|
||||
better = 0.75
|
||||
best = 1
|
||||
end
|
||||
|
||||
if worst < best then
|
||||
if (worse == better and quality == worse) or (worst == best and quality == worst) then
|
||||
return 1, 1, 0
|
||||
elseif quality <= worst then
|
||||
return 1, 0, 0
|
||||
elseif quality <= worse then
|
||||
return 1, 0.5 * (quality - worst) / (worse - worst), 0
|
||||
elseif quality <= normal then
|
||||
return 1, 0.5 + 0.5 * (quality - worse) / (normal - worse), 0
|
||||
elseif quality <= better then
|
||||
return 1 - 0.5 * (quality - normal) / (better - normal), 1, 0
|
||||
elseif quality <= best then
|
||||
return 0.5 - 0.5 * (quality - better) / (best - better), 1, 0
|
||||
else
|
||||
return 0, 1, 0
|
||||
end
|
||||
else
|
||||
if (worse == better and quality == worse) or (worst == best and quality == worst) then
|
||||
return 1, 1, 0
|
||||
elseif quality >= worst then
|
||||
return 1, 0, 0
|
||||
elseif quality >= worse then
|
||||
return 1, 0.5 - 0.5 * (quality - worse) / (worst - worse), 0
|
||||
elseif quality >= normal then
|
||||
return 1, 1 - 0.5 * (quality - normal) / (worse - normal), 0
|
||||
elseif quality >= better then
|
||||
return 0.5 + 0.5 * (quality - better) / (normal - better), 1, 0
|
||||
elseif quality >= best then
|
||||
return 0.5 * (quality - best) / (better - best), 1, 0
|
||||
else
|
||||
return 0, 1, 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Crayon:GetThresholdHexColor(quality, worst, worse, normal, better, best)
|
||||
local r, g, b = self:GetThresholdColor(quality, worst, worse, normal, better, best)
|
||||
return string.format("%02x%02x%02x", r*255, g*255, b*255)
|
||||
end
|
||||
|
||||
function Crayon:GetThresholdColorTrivial(quality, worst, worse, normal, better, best)
|
||||
self:argCheck(quality, 2, "number")
|
||||
if quality ~= quality or quality == inf or quality == -inf then
|
||||
return 1, 1, 1
|
||||
end
|
||||
if not best then
|
||||
worst = 0
|
||||
worse = 0.25
|
||||
normal = 0.5
|
||||
better = 0.75
|
||||
best = 1
|
||||
end
|
||||
|
||||
if worst < best then
|
||||
if worse == better and normal == worse then
|
||||
return 1, 1, 0
|
||||
elseif quality <= worst then
|
||||
return 1, 0, 0
|
||||
elseif quality <= worse then
|
||||
return 1, 0.5 * (quality - worst) / (worse - worst), 0
|
||||
elseif quality <= normal then
|
||||
return 1, 0.5 + 0.5 * (quality - worse) / (normal - worse), 0
|
||||
elseif quality <= better then
|
||||
return 1 - (quality - normal) / (better - normal), 1, 0
|
||||
elseif quality <= best then
|
||||
local x = 0.5 * (quality - better) / (best - better)
|
||||
return x, 1 - x, x
|
||||
else
|
||||
return 0.5, 0.5, 0.5
|
||||
end
|
||||
else
|
||||
if worse == better and normal == worse then
|
||||
return 1, 1, 0
|
||||
elseif quality >= worst then
|
||||
return 1, 0, 0
|
||||
elseif quality >= worse then
|
||||
return 1, 0.5 - 0.5 * (quality - worse) / (worst - worse), 0
|
||||
elseif quality >= normal then
|
||||
return 1, 1 - 0.5 * (quality - normal) / (worse - normal), 0
|
||||
elseif quality >= better then
|
||||
return (quality - better) / (normal - better), 1, 0
|
||||
elseif quality >= best then
|
||||
local x = 0.5 * (quality - best) / (better - best)
|
||||
return 0.5 - x, 0.5 + x, 0.5 - x
|
||||
else
|
||||
return 0.5, 0.5, 0.5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Crayon:GetThresholdHexColorTrivial(quality, worst, worse, normal, better, best)
|
||||
local r, g, b = self:GetThresholdColorTrivial(quality, worst, worse, normal, better, best)
|
||||
return string.format("%02x%02x%02x", r*255, g*255, b*255)
|
||||
end
|
||||
|
||||
AceLibrary:Register(Crayon, MAJOR_VERSION, MINOR_VERSION)
|
||||
Crayon = nil
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,179 @@
|
||||
local T = AceLibrary("Tablet-2.0")
|
||||
local D = AceLibrary("Dewdrop-2.0")
|
||||
local C = AceLibrary("Crayon-2.0")
|
||||
|
||||
local BC = AceLibrary("Babble-Class-2.2")
|
||||
|
||||
sepgp_bids = sepgp:NewModule("sepgp_bids", "AceDB-2.0")
|
||||
sepgp_bids.tipOwner = CreateFrame("Frame","shootyepgp_bids_tipowner",UIParent)
|
||||
sepgp_bids.tipOwner:Show()
|
||||
|
||||
function sepgp_bids:OnEnable()
|
||||
if not T:IsRegistered("sepgp_bids") then
|
||||
T:Register("sepgp_bids",
|
||||
"children", function()
|
||||
T:SetTitle("shootyepgp bids")
|
||||
self:OnTooltipUpdate()
|
||||
end,
|
||||
"showTitleWhenDetached", true,
|
||||
"showHintWhenDetached", true,
|
||||
"cantAttach", true,
|
||||
"menu", function()
|
||||
D:AddLine(
|
||||
"text", "Refresh",
|
||||
"tooltipText", "Refresh window",
|
||||
"func", function() sepgp_bids:Refresh() end
|
||||
)
|
||||
end
|
||||
)
|
||||
end
|
||||
if not T:IsAttached("sepgp_bids") then
|
||||
T:Open("sepgp_bids")
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp_bids:OnDisable()
|
||||
T:Close("sepgp_bids")
|
||||
end
|
||||
|
||||
function sepgp_bids:Refresh()
|
||||
T:Refresh("sepgp_bids")
|
||||
end
|
||||
|
||||
function sepgp_bids:Toggle(forceShow)
|
||||
if T:IsAttached("sepgp_bids") then
|
||||
T:Detach("sepgp_bids")
|
||||
if (T:IsLocked("sepgp_bids")) then
|
||||
T:ToggleLocked("sepgp_bids")
|
||||
end
|
||||
--[[if not (sepgp:IsEventScheduled("shootyepgpBidRefresh")) then
|
||||
sepgp:ScheduleRepeatingEvent("shootyepgpBidRefresh", self.Refresh, 5, self)
|
||||
end]]
|
||||
elseif (forceShow) then
|
||||
else
|
||||
T:Attach("sepgp_bids")
|
||||
if GameTooltip:IsOwned(self.tipOwner) and GameTooltip:IsShown() then
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
--[[if (sepgp:IsEventScheduled("shootyepgpBidRefresh")) then
|
||||
sepgp:CancelScheduledEvent("shootyepgpBidRefresh")
|
||||
end]]
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp_bids:lineTooltip(item,line)
|
||||
if line and line.highlight then
|
||||
if not sepgp:IsHooked(line.highlight,"Show") then
|
||||
sepgp:SecureHook(line.highlight,"Show",function()
|
||||
if not (GameTooltip:IsOwned(sepgp_bids.tipOwner) and GameTooltip:IsShown()) then
|
||||
GameTooltip:SetOwner(sepgp_bids.tipOwner,"ANCHOR_CURSOR")
|
||||
GameTooltip:SetHyperlink(item)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end)
|
||||
end
|
||||
if not sepgp:IsHooked(line.highlight,"Hide") then
|
||||
sepgp:SecureHook(line.highlight,"Hide",function()
|
||||
if GameTooltip:IsOwned(sepgp_bids.tipOwner) and GameTooltip:IsShown() then
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp_bids:announceWinnerMS(name, pr)
|
||||
if GetNumRaidMembers()>0 then
|
||||
SendChatMessage(string.format("Highest MainSpec Bid is %s with %dPR",name,pr),"RAID")
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp_bids:announceWinnerOS(name, pr)
|
||||
if GetNumRaidMembers()>0 then
|
||||
SendChatMessage(string.format("Highest OffSpec Bid is %s with %dPR",name,pr),"RAID")
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp_bids:BuildBidsTable()
|
||||
-- {name,class,ep,gp,ep/gp}
|
||||
table.sort(sepgp.bids_main, function(a,b)
|
||||
return a[5] > b[5]
|
||||
end)
|
||||
table.sort(sepgp.bids_off, function(a,b)
|
||||
return a[5] > b[5]
|
||||
end)
|
||||
return sepgp.bids_main, sepgp.bids_off
|
||||
end
|
||||
|
||||
function sepgp_bids:OnTooltipUpdate()
|
||||
if not (sepgp.bid_item and sepgp.bid_item.link) then return end
|
||||
local link = sepgp.bid_item.link
|
||||
local itemName = sepgp.bid_item.name
|
||||
local price = sepgp_prices:GetPrice(link,sepgp_progress)
|
||||
local offspec
|
||||
if not price then
|
||||
price = "<n/a>"
|
||||
offspec = "<n/a>"
|
||||
else
|
||||
offspec = math.floor(price*sepgp_discount)
|
||||
end
|
||||
local bidcat = T:AddCategory(
|
||||
"columns", 3,
|
||||
"text", C:Orange("Bid Item"), "child_textR", 1, "child_textG", 1, "child_textB", 1, "child_justify", "LEFT",
|
||||
"text2", C:Orange("GP Cost"), "child_text2R", 50/255, "child_text2G", 205/255, "child_text2B", 50/255, "child_justify2", "RIGHT",
|
||||
"text3", C:Orange("OffSpec"), "child_text3R", 32/255, "child_text3G", 178/255, "child_text3B", 170/255, "child_justify3", "RIGHT",
|
||||
"hideBlankLine", true
|
||||
)
|
||||
bidcat:AddLine(
|
||||
"text", itemName,
|
||||
"text2", price,
|
||||
"text3", offspec,
|
||||
"func", "lineTooltip", "arg1", self, "arg2", link, "arg3", this
|
||||
)
|
||||
local maincatHeader = T:AddCategory(
|
||||
"columns", 1,
|
||||
"text", C:Gold("MainSpec Bids")
|
||||
):AddLine("text","")
|
||||
local maincat = T:AddCategory(
|
||||
"columns", 4,
|
||||
"text", C:Orange("Name"), "child_textR", 1, "child_textG", 1, "child_textB", 1, "child_justify", "LEFT",
|
||||
"text2", C:Orange("ep"), "child_text2R", 1, "child_text2G", 1, "child_text2B", 1, "child_justify2", "RIGHT",
|
||||
"text3", C:Orange("gp"), "child_text3R", 1, "child_text3G", 1, "child_text3B", 1, "child_justify3", "RIGHT",
|
||||
"text4", C:Orange("pr"), "child_text4R", 1, "child_text4G", 1, "child_text4B", 0, "child_justify4", "RIGHT",
|
||||
"hideBlankLine", true
|
||||
)
|
||||
local tm = self:BuildBidsTable()
|
||||
for i = 1, table.getn(tm) do
|
||||
local name, class, ep, gp, pr = unpack(tm[i])
|
||||
maincat:AddLine(
|
||||
"text", C:Colorize(BC:GetHexColor(class), name),
|
||||
"text2", string.format("%.4g", ep),
|
||||
"text3", string.format("%.4g", gp),
|
||||
"text4", string.format("%.4g", pr),
|
||||
"func", "announceWinnerMS", "arg1", self, "arg2", name, "arg3", pr
|
||||
)
|
||||
end
|
||||
local offcatHeader = T:AddCategory(
|
||||
"columns", 1,
|
||||
"text", C:Silver("OffSpec Bids")
|
||||
):AddLine("text","")
|
||||
local offcat = T:AddCategory(
|
||||
"columns", 4,
|
||||
"text", C:Orange("Name"), "child_textR", 1, "child_textG", 1, "child_textB", 1, "child_justify", "LEFT",
|
||||
"text2", C:Orange("ep"), "child_text2R", 1, "child_text2G", 1, "child_text2B", 1, "child_justify2", "RIGHT",
|
||||
"text3", C:Orange("gp"), "child_text3R", 1, "child_text3G", 1, "child_text3B", 1, "child_justify3", "RIGHT",
|
||||
"text4", C:Orange("pr"), "child_text4R", 1, "child_text4G", 1, "child_text4B", 0, "child_justify4", "RIGHT",
|
||||
"hideBlankLine", true
|
||||
)
|
||||
local _,to = self:BuildBidsTable()
|
||||
for i = 1, table.getn(to) do
|
||||
local name, class, ep, gp, pr = unpack(to[i])
|
||||
offcat:AddLine(
|
||||
"text", C:Colorize(BC:GetHexColor(class), name),
|
||||
"text2", string.format("%.4g", ep),
|
||||
"text3", string.format("%.4g", gp),
|
||||
"text4", string.format("%.4g", pr),
|
||||
"func", "announceWinnerOS", "arg1", self, "arg2", name, "arg3", pr
|
||||
)
|
||||
end
|
||||
end
|
||||
+875
@@ -0,0 +1,875 @@
|
||||
local prices = {
|
||||
-----------------
|
||||
--- Naxxramas ---
|
||||
-----------------
|
||||
[23226] = {104,"T3"}; --Ghoul Skin Tunic
|
||||
[23663] = {48,"T3"}; --Girdle of Elemental Fury
|
||||
[23044] = {116,"T3"}; --Harbinger of Doom
|
||||
[23665] = {48,"T3"}; --Leggings of Elemental Fury
|
||||
[23221] = {100,"T3"}; --Misplaced Servo Arm
|
||||
[23069] = {18,"T3"}; --Necro-knight Garb
|
||||
[23664] = {48,"T3"}; --Pauldrons of Elemental Fury
|
||||
[23237] = {60,"T3"}; --Ring of Eternal Flame
|
||||
[23238] = {40,"T3"}; --Stygian Buckler
|
||||
|
||||
[22939] = {72,"T3"}; --Band of Unanswered Prayers
|
||||
[22938] = {96,"T3"}; --Cryptfiend Silk Cloak
|
||||
[22937] = {48,"T3"}; --Gem of Nerubis
|
||||
[22935] = {4,"T3"}; --Touch of Frost
|
||||
[22936] = {72,"T3"}; --Wristguards of Vengeance
|
||||
[22369] = {84,"T3"}; --T3 Wrist Token
|
||||
[22362] = {84,"T3"}; --T3 Wrist Token
|
||||
[22355] = {84,"T3"}; --T3 Wrist Token
|
||||
|
||||
[22940] = {4,"T3"}; --Icebane Pauldrons
|
||||
[22943] = {60,"T3"}; --Malice Stone Pendant
|
||||
[22941] = {4,"T3"}; --Polar Shoulderpads
|
||||
[22942] = {116,"T3"}; --The Widow's Embrace
|
||||
[22806] = {116,"T3"}; --Widow's Remorse
|
||||
|
||||
[23220] = {132,"T3"}; --Crystal Webbed Robe
|
||||
[22954] = {116,"T3"}; --Kiss of the Spider
|
||||
[22804] = {116,"T3"}; --Maexxna's Fang
|
||||
[22947] = {24,"T3"}; --Pendant of Forgotten Names
|
||||
[22807] = {152,"T3"}; --Wraith Blade
|
||||
[22371] = {96,"T3"}; --T3 Gloves Token
|
||||
[22364] = {96,"T3"}; --T3 Gloves Token
|
||||
[22357] = {96,"T3"}; --T3 Gloves Token
|
||||
|
||||
[22961] = {80,"T3"}; --Band of Reanimation
|
||||
[22960] = {96,"T3"}; --Cloak of Suturing
|
||||
[22815] = {88,"T3"}; --Severance
|
||||
[22818] = {92,"T3"}; --The Plague Bearer
|
||||
[22820] = {72,"T3"}; --Wand of Fates
|
||||
[22368] = {100,"T3"}; --T3 Shoulder Token
|
||||
[22361] = {100,"T3"}; --T3 Shoulder Token
|
||||
[22354] = {100,"T3"}; --T3 Shoulder Token
|
||||
|
||||
[22968] = {4,"T3"}; --Glacial Mantle
|
||||
[22967] = {4,"T3"}; --Icy Scale Spaulders
|
||||
[22803] = {80,"T3"}; --Midnight Haze
|
||||
[22988] = {152,"T3"}; --The End of Dreams
|
||||
[22810] = {44,"T3"}; --Toxin Injector
|
||||
|
||||
[22813] = {72,"T3"}; --Claymore of Unholy Might
|
||||
[23075] = {80,"T3"}; --Death's Bargain
|
||||
[22994] = {24,"T3"}; --Digested Hand of Power
|
||||
[22981] = {52,"T3"}; --Gluth's Missing Collar
|
||||
[22983] = {112,"T3"}; --Rime Covered Mantle
|
||||
|
||||
[23001] = {96,"T3"}; --Eye of Diminution
|
||||
[23070] = {136,"T3"}; --Leggings of Polarity
|
||||
[23000] = {136,"T3"}; --Plated Abomination Ribcage
|
||||
[22801] = {140,"T3"}; --Spire of Twilight
|
||||
[22808] = {116,"T3"}; --The Castigator
|
||||
[22367] = {120,"T3"}; --T3 Helm Token
|
||||
[22360] = {120,"T3"}; --T3 Helm Token
|
||||
[22353] = {120,"T3"}; --T3 Helm Token
|
||||
|
||||
[23031] = {76,"T3"}; --Band of the Inevitable
|
||||
[23030] = {68,"T3"}; --Cloak of the Scourge
|
||||
[23028] = {16,"T3"}; --Hailstone Band
|
||||
[22816] = {136,"T3"}; --Hatchet of Sundered Bone
|
||||
[23029] = {60,"T3"}; --Noth's Frigid Heart
|
||||
[23005] = {68,"T3"}; --Totem of Flowing Water
|
||||
[22370] = {92,"T3"}; --T3 Belt Token
|
||||
[22363] = {92,"T3"}; --T3 Belt Token
|
||||
[22356] = {92,"T3"}; --T3 Belt Token
|
||||
|
||||
[23019] = {4,"T3"}; --Icebane Helmet
|
||||
[23033] = {4,"T3"}; --Icy Scale Coif
|
||||
[23068] = {124,"T3"}; --Legplates of Carnage
|
||||
[23036] = {72,"T3"}; --Necklace of Necropsy
|
||||
[23035] = {112,"T3"}; --Preceptor's Hat
|
||||
|
||||
[23038] = {88,"T3"}; --Band of Unnatural Forces
|
||||
[22800] = {160,"T3"}; --Brimstone Staff
|
||||
[23042] = {12,"T3"}; --Loatheb's Reflection
|
||||
[23037] = {24,"T3"}; --Ring of Spiritual Fervor
|
||||
[23039] = {132,"T3"}; --The Eye of Nerub
|
||||
[22366] = {136,"T3"}; --T3 Pants Token
|
||||
[22359] = {136,"T3"}; --T3 Pants Token
|
||||
[22352] = {136,"T3"}; --T3 Pants Token
|
||||
|
||||
[23017] = {48,"T3"}; --Veil of Eclipse
|
||||
[23219] = {124,"T3"}; --Girdle of the Mentor
|
||||
[23014] = {120,"T3"}; --Iblis, Blade of the Fallen Seraph
|
||||
[23009] = {72,"T3"}; --Wand of the Whispering Dead
|
||||
[23018] = {84,"T3"}; --Signets of the Fallen Defender
|
||||
[23004] = {48,"T3"}; --Idol of Longevity
|
||||
[22372] = {92,"T3"}; --T3 Boots Token
|
||||
[22365] = {92,"T3"}; --T3 Boots Token
|
||||
[22358] = {92,"T3"}; --T3 Boots Token
|
||||
|
||||
[23073] = {32,"T3"}; --Boots of Displacement
|
||||
[23032] = {4,"T3"}; --Glacial Headdress
|
||||
[23020] = {4,"T3"}; --Polar Helmet
|
||||
[23021] = {96,"T3"}; --The Soul Harvester's Bindings
|
||||
[23023] = {48,"T3"}; --Sadist's Collar
|
||||
|
||||
[22691] = {200,"T3"}; --Corrupted Ashbringer
|
||||
[22811] = {172,"T3"}; --Soulstring
|
||||
[22809] = {60,"T3"}; --Maul of the Redeemed Crusader
|
||||
[23071] = {144,"T3"}; --Leggings of Apocalypse
|
||||
[23025] = {92,"T3"}; --Seal of the Damned
|
||||
[23027] = {96,"T3"}; --Warmth of Forgiveness
|
||||
[22351] = {148,"T3"}; --T3 Chest Token
|
||||
[22350] = {148,"T3"}; --T3 Chest Token
|
||||
[22349] = {148,"T3"}; --T3 Chest Token
|
||||
|
||||
[23050] = {160,"T3"}; --Cloak of the Necropolis
|
||||
[23045] = {160,"T3"}; --Shroud of Dominion
|
||||
[23043] = {150,"T3"}; --The Face of Death
|
||||
[23242] = {180,"T3"}; --Claw of the Frost Wyrm
|
||||
[23049] = {160,"T3"}; --Sapphiron's Left Eye
|
||||
[23048] = {160,"T3"}; --Sapphiron's Right Eye
|
||||
[23040] = {160,"T3"}; --Glyph of Deflection
|
||||
[23047] = {160,"T3"}; --Eye of the Dead
|
||||
[23046] = {160,"T3"}; --The Restrained Essence of Sapphiron
|
||||
[23041] = {160,"T3"}; --Slayer's Crest
|
||||
[23548] = {80,"T3"}; --Might of the Scourge
|
||||
[23545] = {80,"T3"}; --Power of the Scourge
|
||||
[23547] = {80,"T3"}; --Resilience of the Scourge
|
||||
[23549] = {120,"T3"}; --Fortitude of the Scourge
|
||||
|
||||
[22802] = {200,"T3"}; --Kingsfall
|
||||
[23054] = {200,"T3"}; --Gressil, Dawn of Ruin
|
||||
[23577] = {200,"T3"}; --The Hungering Cold
|
||||
[23056] = {240,"T3"}; --Hammer of the Twisting Nether
|
||||
[22798] = {300,"T3"}; --Might of Menethil
|
||||
[22799] = {300,"T3"}; --Soulseeker
|
||||
[22821] = {116,"T3"}; --Doomfinger
|
||||
[22812] = {300,"T3"}; --Nerubian Slavemaker
|
||||
[22819] = {180,"T3"}; --Shield of Condemnation
|
||||
[23057] = {140,"T3"}; --Gem of Trapped Innocents
|
||||
[23053] = {140,"T3"}; --Stormrage's Talisman of Seething
|
||||
[22520] = {0,"T3"}; --The Phylactery of Kel'Thuzad
|
||||
[22733] = {400,"T3"}; --Staff Head of Atiesh
|
||||
|
||||
[22490] = {120,"T3"}; --Dreamwalker Raiment
|
||||
[22491] = {100,"T3"}; --Dreamwalker Raiment
|
||||
[22488] = {148,"T3"}; --Dreamwalker Raiment
|
||||
[22495] = {84,"T3"}; --Dreamwalker Raiment
|
||||
[22493] = {96,"T3"}; --Dreamwalker Raiment
|
||||
[22494] = {92,"T3"}; --Dreamwalker Raiment
|
||||
[22489] = {136,"T3"}; --Dreamwalker Raiment
|
||||
[22492] = {92,"T3"}; --Dreamwalker Raiment
|
||||
[23064] = {500,"T3"}; --Dreamwalker Raiment
|
||||
|
||||
[22438] = {120,"T3"}; --Cryptstalker Armor
|
||||
[22439] = {100,"T3"}; --Cryptstalker Armor
|
||||
[22436] = {148,"T3"}; --Cryptstalker Armor
|
||||
[22443] = {84,"T3"}; --Cryptstalker Armor
|
||||
[22441] = {96,"T3"}; --Cryptstalker Armor
|
||||
[22442] = {92,"T3"}; --Cryptstalker Armor
|
||||
[22437] = {136,"T3"}; --Cryptstalker Armor
|
||||
[22440] = {92,"T3"}; --Cryptstalker Armor
|
||||
[23067] = {500,"T3"}; --Cryptstalker Armor
|
||||
|
||||
[22498] = {120,"T3"}; --Frostfire Regalia
|
||||
[22499] = {100,"T3"}; --Frostfire Regalia
|
||||
[22496] = {148,"T3"}; --Frostfire Regalia
|
||||
[22503] = {84,"T3"}; --Frostfire Regalia
|
||||
[22501] = {96,"T3"}; --Frostfire Regalia
|
||||
[22502] = {92,"T3"}; --Frostfire Regalia
|
||||
[22497] = {136,"T3"}; --Frostfire Regalia
|
||||
[22500] = {92,"T3"}; --Frostfire Regalia
|
||||
[23062] = {500,"T3"}; --Frostfire Regalia
|
||||
|
||||
[22514] = {120,"T3"}; --Vestments of Faith
|
||||
[22515] = {100,"T3"}; --Vestments of Faith
|
||||
[22512] = {148,"T3"}; --Vestments of Faith
|
||||
[22519] = {84,"T3"}; --Vestments of Faith
|
||||
[22517] = {96,"T3"}; --Vestments of Faith
|
||||
[22518] = {92,"T3"}; --Vestments of Faith
|
||||
[22513] = {136,"T3"}; --Vestments of Faith
|
||||
[22516] = {92,"T3"}; --Vestments of Faith
|
||||
[23061] = {500,"T3"}; --Vestments of Faith
|
||||
|
||||
[22478] = {120,"T3"}; --Bonescythe Armor
|
||||
[22479] = {100,"T3"}; --Bonescythe Armor
|
||||
[22476] = {148,"T3"}; --Bonescythe Armor
|
||||
[22483] = {84,"T3"}; --Bonescythe Armor
|
||||
[22481] = {96,"T3"}; --Bonescythe Armor
|
||||
[22482] = {92,"T3"}; --Bonescythe Armor
|
||||
[22477] = {136,"T3"}; --Bonescythe Armor
|
||||
[22480] = {92,"T3"}; --Bonescythe Armor
|
||||
[23060] = {500,"T3"}; --Bonescythe Armor
|
||||
|
||||
[22466] = {120,"T3"}; --The Earthshatterer
|
||||
[22467] = {100,"T3"}; --The Earthshatterer
|
||||
[22464] = {148,"T3"}; --The Earthshatterer
|
||||
[22471] = {84,"T3"}; --The Earthshatterer
|
||||
[22469] = {96,"T3"}; --The Earthshatterer
|
||||
[22470] = {92,"T3"}; --The Earthshatterer
|
||||
[22465] = {136,"T3"}; --The Earthshatterer
|
||||
[22468] = {92,"T3"}; --The Earthshatterer
|
||||
[23065] = {500,"T3"}; --The Earthshatterer
|
||||
|
||||
[22506] = {120,"T3"}; --Plaguehart Raiment
|
||||
[22507] = {100,"T3"}; --Plaguehart Raiment
|
||||
[22504] = {148,"T3"}; --Plaguehart Raiment
|
||||
[22511] = {84,"T3"}; --Plaguehart Raiment
|
||||
[22509] = {96,"T3"}; --Plaguehart Raiment
|
||||
[22510] = {92,"T3"}; --Plaguehart Raiment
|
||||
[22505] = {136,"T3"}; --Plaguehart Raiment
|
||||
[22508] = {92,"T3"}; --Plaguehart Raiment
|
||||
[23063] = {500,"T3"}; --Plaguehart Raiment
|
||||
|
||||
[22418] = {120,"T3"}; --Dreadnaught's Battlegear
|
||||
[22419] = {100,"T3"}; --Dreadnaught's Battlegear
|
||||
[22416] = {148,"T3"}; --Dreadnaught's Battlegear
|
||||
[22423] = {84,"T3"}; --Dreadnaught's Battlegear
|
||||
[22421] = {96,"T3"}; --Dreadnaught's Battlegear
|
||||
[22422] = {92,"T3"}; --Dreadnaught's Battlegear
|
||||
[22417] = {136,"T3"}; --Dreadnaught's Battlegear
|
||||
[22420] = {92,"T3"}; --Dreadnaught's Battlegear
|
||||
[23059] = {500,"T3"}; --Dreadnaught's Battlegear
|
||||
|
||||
---------------------------
|
||||
--- Temple of Ahn'Qiraj ---
|
||||
---------------------------
|
||||
|
||||
[21837] = {40,"T2.5"}; --Anubisath Warhammer
|
||||
[21838] = {4,"T2.5"}; --Garb of Royal Ascension
|
||||
[21888] = {8,"T2.5"}; --Gloves of the Immortal
|
||||
[21889] = {0,"T2.5"}; --Gloves of the Redeemed Prophet
|
||||
[21856] = {16,"T2.5"}; --Neretzek, The Blood Drinker
|
||||
[21836] = {44,"T2.5"}; --Ritssyn's Ring of Chaos
|
||||
[21891] = {64,"T2.5"}; --Shard of the Fallen Star
|
||||
|
||||
[21702] = {4,"T2.5"}; --Amulet of Foul Warding
|
||||
[21699] = {36,"T2.5"}; --Barrage Shoulders
|
||||
[21708] = {4,"T2.5"}; --Beetle Scaled Wristguards
|
||||
[21705] = {12,"T2.5"}; --Boots of the Fallen Prophet
|
||||
[21706] = {28,"T2.5"}; --Boots of the Unwavering Will
|
||||
[21814] = {92,"T2.5"}; --Breastplate of Annihilation
|
||||
[21701] = {88,"T2.5"}; --Cloak of the Concentrated Hatred
|
||||
[21703] = {24,"T2.5"}; --Hammer of Ji'zhi
|
||||
[21698] = {40,"T2.5"}; --Leggings of Immersion
|
||||
[21700] = {24,"T2.5"}; --Pendant of the Qiraji Guardian
|
||||
[21707] = {48,"T2.5"}; --Ring of Swarming Thought
|
||||
[21128] = {52,"T2.5"}; --Staff of the Qiraji Prophets
|
||||
[21232] = {116,"T2.5"}; --Imperial Qiraji Armaments
|
||||
[21242] = {116,"T2.5"}; --Imperial Qiraji Armaments
|
||||
[21272] = {116,"T2.5"}; --Imperial Qiraji Armaments
|
||||
[21244] = {116,"T2.5"}; --Imperial Qiraji Armaments
|
||||
[21269] = {116,"T2.5"}; --Imperial Qiraji Armaments
|
||||
[21237] = {84,"T2.5"}; --Imperial Qiraji Regalia
|
||||
[21273] = {84,"T2.5"}; --Imperial Qiraji Regalia
|
||||
[21275] = {84,"T2.5"}; --Imperial Qiraji Regalia
|
||||
[21268] = {84,"T2.5"}; --Imperial Qiraji Regalia
|
||||
|
||||
[21695] = {80,"T2.5"}; --Angelista's Touch
|
||||
[21697] = {4,"T2.5"}; --Cape of the Trinity
|
||||
[21693] = {60,"T2.5"}; --Guise of the Devourer
|
||||
[21696] = {4,"T2.5"}; --Robes of the Triumvirate
|
||||
[21694] = {60,"T2.5"}; --Ternary Mantle
|
||||
[21692] = {32,"T2.5"}; --Triad Girdle
|
||||
|
||||
[21690] = {48,"T2.5"}; --Angelista's Charm
|
||||
[21688] = {68,"T2.5"}; --Boots of the Fallen Hero
|
||||
[21689] = {60,"T2.5"}; --Gloves of Ebru
|
||||
[21691] = {4,"T2.5"}; --Ooze-ridden Gauntlets
|
||||
|
||||
[21685] = {4,"T2.5"}; --Petrified Scarab
|
||||
[21681] = {64,"T2.5"}; --Ring of the Devoured
|
||||
[21680] = {56,"T2.5"}; --Vest of Swift Execution
|
||||
[21603] = {56,"T2.5"}; --Wand of the Qiraji Nobility
|
||||
|
||||
[21682] = {4,"T2.5"}; --Bile-Covered Gauntlets
|
||||
[21686] = {40,"T2.5"}; --Mantle of Phrenic Power
|
||||
[21683] = {0,"T2.5"}; --Mantle of the Desert Crusade
|
||||
[21684] = {4,"T2.5"}; --Mantle of the Desert's Fury
|
||||
[21687] = {4,"T2.5"}; --Ukko's Ring of Darkness
|
||||
|
||||
[21670] = {44,"T2.5"}; --Badge of the Swarmguard
|
||||
[21669] = {48,"T2.5"}; --Creeping Vine Helm
|
||||
[21674] = {64,"T2.5"}; --Gauntlets of Steadfast Determ..
|
||||
[21672] = {64,"T2.5"}; --Gloves of Enforcement
|
||||
[21667] = {0,"T2.5"}; --Legplates of Blazing Light
|
||||
[21676] = {32,"T2.5"}; --Leggings of the Festering Swa..
|
||||
[21678] = {4,"T2.5"}; --Necklace of Purity
|
||||
[21648] = {4,"T2.5"}; --Recomposed Boots
|
||||
[21671] = {48,"T2.5"}; --Robes of the Battleguard
|
||||
[21666] = {88,"T2.5"}; --Sartura's Might
|
||||
[21668] = {20,"T2.5"}; --Scaled Leggings of Qiraji Fury
|
||||
[21673] = {32,"T2.5"}; --Silithid Claw
|
||||
[21675] = {60,"T2.5"}; --Thick Qirajihide Belt
|
||||
|
||||
[21650] = {112,"T2.5"}; --Ancient Qiraji Ripper
|
||||
[21664] = {80,"T2.5"}; --Barbed Choker
|
||||
[21635] = {104,"T2.5"}; --Barb of the Sand Reaver
|
||||
[21627] = {4,"T2.5"}; --Cloak of Untold Secrets
|
||||
[21647] = {28,"T2.5"}; --Fetish of the Sand Reaver
|
||||
[21645] = {60,"T2.5"}; --Hive Tunneler's Boots
|
||||
[22402] = {0,"T2.5"}; --Libram of Grace
|
||||
[21665] = {72,"T2.5"}; --Mantle of Wicked Revenge
|
||||
[21639] = {76,"T2.5"}; --Pauldrons of the Unrelenting
|
||||
[21663] = {136,"T2.5"}; --Robes of the Guardian Saint
|
||||
[21651] = {52,"T2.5"}; --Scaled Sand Reaver Leggings
|
||||
[21652] = {4,"T2.5"}; --Silithid Carapace Chestguard
|
||||
[22396] = {4,"T2.5"}; --Totem of Life
|
||||
|
||||
[21623] = {0,"T2.5"}; --Gauntlets of the Right. Champ
|
||||
[21624] = {48,"T2.5"}; --Gauntlets of Kalimdor
|
||||
[22399] = {68,"T2.5"}; --Idol of Health
|
||||
[21677] = {56,"T2.5"}; --Ring of the Qiraji Fury
|
||||
[21625] = {48,"T2.5"}; --Scarab Brooch
|
||||
[21622] = {100,"T2.5"}; --Sharpened Silithid Femur
|
||||
[21626] = {4,"T2.5"}; --Slime-coated Leggings
|
||||
|
||||
[20928] = {68,"T2.5"}; --Qiraji Bindings of Command
|
||||
[20932] = {68,"T2.5"}; --Qiraji Bindings of Dominance
|
||||
|
||||
[21621] = {40,"T2.5"}; --Cloak of the Golden Hive
|
||||
[21619] = {44,"T2.5"}; --Gloves of the Messiah
|
||||
[21618] = {24,"T2.5"}; --Hive Defiler Wristguards
|
||||
[21616] = {52,"T2.5"}; --Huhuran's Stinger
|
||||
[21620] = {80,"T2.5"}; --Ring of the Martyr
|
||||
[21617] = {64,"T2.5"}; --Wasphide Gauntlets
|
||||
|
||||
[21608] = {80,"T2.5"}; --Amulet of Vek'nilash
|
||||
[21606] = {0,"T2.5"}; --Belt of the Fallen Emperor
|
||||
[21600] = {88,"T2.5"}; --Boots of Epiphany
|
||||
[21604] = {80,"T2.5"}; --Bracelets of Royal Redemption
|
||||
[21605] = {60,"T2.5"}; --Gloves of the Hidden Temple
|
||||
[21607] = {20,"T2.5"}; --Grasp of the Fallen Emperor
|
||||
[21679] = {48,"T2.5"}; --Kalimdor's Revenge
|
||||
[21609] = {52,"T2.5"}; --Regenerating Belt of Vek'nilash
|
||||
[21601] = {80,"T2.5"}; --Ring of Emperor Vek'lor
|
||||
[21597] = {88,"T2.5"}; --Royal Scepter of Vek'lor
|
||||
[21598] = {84,"T2.5"}; --Royal Qiraji Belt
|
||||
[21599] = {68,"T2.5"}; --Vek'lor's Gloves of Devastation
|
||||
[21602] = {88,"T2.5"}; --Qiraji Execution Bracers
|
||||
|
||||
[20926] = {72,"T2.5"}; --Vek'nilash's Circlet
|
||||
[20930] = {72,"T2.5"}; --Vek'lor's Diadem
|
||||
|
||||
[21611] = {48,"T2.5"}; --Burrower Bracers
|
||||
[21615] = {88,"T2.5"}; --Don Rigoberto's Lost Hat
|
||||
[23570] = {80,"T2.5"}; --Jom Gabbar
|
||||
[23557] = {128,"T2.5"}; --Larvae of the Great Worm
|
||||
[23558] = {24,"T2.5"}; --The Burrower's Shell
|
||||
[21610] = {88,"T2.5"}; --Wormscale Blocker
|
||||
|
||||
[20927] = {76,"T2.5"}; --Ouro's Intact Hide
|
||||
[20931] = {76,"T2.5"}; --Skin of the Great Sandworm
|
||||
|
||||
[21586] = {124,"T2.5"}; --Belt of Never-ending Agony
|
||||
[21583] = {116,"T2.5"}; --Cloak of Clarity
|
||||
[22731] = {116,"T2.5"}; --Cloak of the Devoured
|
||||
[21134] = {172,"T2.5"}; --Dark Edge of Insanity
|
||||
[21585] = {132,"T2.5"}; --Dark Storm Gauntlets
|
||||
[21126] = {152,"T2.5"}; --Death's Sting
|
||||
[22730] = {124,"T2.5"}; --Eyestalk Waist Cord
|
||||
[21581] = {116,"T2.5"}; --Gauntlets of Annihilation
|
||||
[21582] = {124,"T2.5"}; --Grasp of the Old God
|
||||
[22732] = {116,"T2.5"}; --Mark of C'thun
|
||||
[21596] = {104,"T2.5"}; --Ring of the Godslayer
|
||||
[21839] = {180,"T2.5"}; --Scepter of the False Prophet
|
||||
[21579] = {44,"T2.5"}; --Vanquished Tentacle of C'thun
|
||||
|
||||
[21221] = {96,"T2.5"}; --Eye of C'thun
|
||||
[21712] = {96,"T2.5"}; --Eye of C'thun
|
||||
[21710] = {96,"T2.5"}; --Eye of C'thun
|
||||
[21709] = {96,"T2.5"}; --Eye of C'thun
|
||||
[20929] = {128,"T2.5"}; --Carapace of the Old God
|
||||
[20933] = {128,"T2.5"}; --Husk of the Old God
|
||||
|
||||
[21357] = {128,"T2.5"}; --Genesis Raiment
|
||||
[21353] = {72,"T2.5"}; --Genesis Raiment
|
||||
[21356] = {76,"T2.5"}; --Genesis Raiment
|
||||
[21354] = {68,"T2.5"}; --Genesis Raiment
|
||||
[21355] = {68,"T2.5"}; --Genesis Raiment
|
||||
|
||||
[21370] = {128,"T2.5"}; --Striker's Garb
|
||||
[21366] = {72,"T2.5"}; --Striker's Garb
|
||||
[21368] = {76,"T2.5"}; --Striker's Garb
|
||||
[21367] = {68,"T2.5"}; --Striker's Garb
|
||||
[21365] = {68,"T2.5"}; --Striker's Garb
|
||||
|
||||
[21343] = {128,"T2.5"}; --Enigma Vestments
|
||||
[21347] = {72,"T2.5"}; --Enigma Vestments
|
||||
[21346] = {76,"T2.5"}; --Enigma Vestments
|
||||
[21345] = {68,"T2.5"}; --Enigma Vestments
|
||||
[21344] = {68,"T2.5"}; --Enigma Vestments
|
||||
|
||||
[21351] = {128,"T2.5"}; --Garments of the Oracle
|
||||
[21348] = {72,"T2.5"}; --Garments of the Oracle
|
||||
[21352] = {76,"T2.5"}; --Garments of the Oracle
|
||||
[21350] = {68,"T2.5"}; --Garments of the Oracle
|
||||
[21349] = {68,"T2.5"}; --Garments of the Oracle
|
||||
|
||||
[21364] = {128,"T2.5"}; --Deathdealer's Embrace
|
||||
[21360] = {72,"T2.5"}; --Deathdealer's Embrace
|
||||
[21362] = {76,"T2.5"}; --Deathdealer's Embrace
|
||||
[21361] = {68,"T2.5"}; --Deathdealer's Embrace
|
||||
[21359] = {68,"T2.5"}; --Deathdealer's Embrace
|
||||
|
||||
[21374] = {128,"T2.5"}; --Stormcaller's Garb
|
||||
[21372] = {72,"T2.5"}; --Stormcaller's Garb
|
||||
[21375] = {76,"T2.5"}; --Stormcaller's Garb
|
||||
[21376] = {68,"T2.5"}; --Stormcaller's Garb
|
||||
[21373] = {68,"T2.5"}; --Stormcaller's Garb
|
||||
|
||||
[21334] = {128,"T2.5"}; --Doomcaller's Attire
|
||||
[21337] = {72,"T2.5"}; --Doomcaller's Attire
|
||||
[21336] = {76,"T2.5"}; --Doomcaller's Attire
|
||||
[21335] = {68,"T2.5"}; --Doomcaller's Attire
|
||||
[21338] = {68,"T2.5"}; --Doomcaller's Attire
|
||||
|
||||
[21331] = {128,"T2.5"}; --Conqueror's Battlegear
|
||||
[21329] = {72,"T2.5"}; --Conqueror's Battlegear
|
||||
[21332] = {76,"T2.5"}; --Conqueror's Battlegear
|
||||
[21330] = {68,"T2.5"}; --Conqueror's Battlegear
|
||||
[21333] = {68,"T2.5"}; --Conqueror's Battlegear
|
||||
|
||||
----------------------
|
||||
--- Blackwing Lair ---
|
||||
----------------------
|
||||
|
||||
[19434] = {40,"T2"}; --Band of Dark Dominion
|
||||
[19437] = {48,"T2"}; --Boots of Pure Thought
|
||||
[19436] = {16,"T2"}; --Cloak of Draconic Might
|
||||
[19362] = {32,"T2"}; --Doom's Edge
|
||||
[19354] = {16,"T2"}; --Draconic Avenger
|
||||
[19358] = {12,"T2"}; --Draconic Maul
|
||||
[19435] = {8,"T2"}; --Essence Gatherer
|
||||
[19439] = {4,"T2"}; --Interlaced Shadow Jerkin
|
||||
[19438] = {48,"T2"}; --Ringo's Blizzard Boots
|
||||
|
||||
[19336] = {16,"T2"}; --Arcane Infused Gem
|
||||
[19369] = {16,"T2"}; --Gloves of Rapid Evolution
|
||||
[19370] = {72,"T2"}; --Mantle of the Blackwing Cabal
|
||||
[19335] = {20,"T2"}; --Spineshatter
|
||||
[19337] = {16,"T2"}; --The Black Book
|
||||
[19334] = {32,"T2"}; --The Untamed Blade
|
||||
|
||||
[19346] = {48,"T2"}; --Dragonfang Blade
|
||||
[19372] = {44,"T2"}; --Helm of Endless Rage
|
||||
[19339] = {40,"T2"}; --Mind Quickening Gem
|
||||
[19371] = {28,"T2"}; --Pendant of the Fallen Dragon
|
||||
[19348] = {28,"T2"}; --Red Dragonscale Protector
|
||||
[19340] = {16,"T2"}; --Rune of Metamorphosis
|
||||
|
||||
[19373] = {40,"T2"}; --Black Brood Pauldrons
|
||||
[19374] = {72,"T2"}; --Bracers of Arcane Accuracy
|
||||
[19350] = {40,"T2"}; --Heartstriker
|
||||
[19341] = {68,"T2"}; --Lifegiving Gem
|
||||
[19351] = {92,"T2"}; --Maladath, Runed Blade of the..
|
||||
[19342] = {16,"T2"}; --Venomous Totem
|
||||
[20383] = {40,"T2"}; --Head of Broodlord Lashlayer
|
||||
|
||||
[19399] = {12,"T2"}; --Black Ash Robe
|
||||
[19365] = {52,"T2"}; --Claw of the Black Drake
|
||||
[19398] = {32,"T2"}; --Cloak of Firemaw
|
||||
[19353] = {32,"T2"}; --Drake Talon Cleaver
|
||||
[19394] = {52,"T2"}; --Drake Talon Pauldrons
|
||||
[19400] = {44,"T2"}; --Firemaw's Clutch
|
||||
[19402] = {0,"T2"}; --Legguards of the Fallen Crusader
|
||||
[19344] = {20,"T2"}; --Natural Alignment Crystal
|
||||
[19401] = {20,"T2"}; --Primalist's Linked Legguards
|
||||
[19395] = {116,"T2"}; --Rejuvenating Gem
|
||||
[19397] = {52,"T2"}; --Ring of Blackrock
|
||||
[19355] = {48,"T2"}; --Shadow Wing Focus Staff
|
||||
[19396] = {36,"T2"}; --Taut Dragonhide Belt
|
||||
|
||||
[19345] = {20,"T2"}; --Aegis of Preservation
|
||||
[19403] = {52,"T2"}; --Band of Forced Concentration
|
||||
[19368] = {52,"T2"}; --Dragonbreath Hand Cannon
|
||||
[19406] = {116,"T2"}; --Drake Fang Talisman
|
||||
[19407] = {40,"T2"}; --Ebony Flame Gloves
|
||||
[19405] = {60,"T2"}; --Malfurion's Blessed Bulwark
|
||||
|
||||
[19432] = {32,"T2"}; --Circle of Applied Force
|
||||
[19367] = {32,"T2"}; --Dragon's Touch
|
||||
[19433] = {12,"T2"}; --Emberweave Leggings
|
||||
[19357] = {32,"T2"}; --Herald of Woe
|
||||
[19430] = {64,"T2"}; --Shroud of Pure Thought
|
||||
[19431] = {116,"T2"}; --Styleen's Impeding Scarab
|
||||
|
||||
[19388] = {36,"T2"}; --Angelista's Grasp
|
||||
[19361] = {124,"T2"}; --Ashjre'thul, Crossbow of Smiting
|
||||
[19352] = {76,"T2"}; --Chromatically Tempered Sword
|
||||
[19387] = {84,"T2"}; --Chromatic Boots
|
||||
[19347] = {72,"T2"}; --Claw of Chromaggus
|
||||
[19349] = {76,"T2"}; --Elementium Reinforced Bulwark
|
||||
[19386] = {32,"T2"}; --Elementium Threaded Cloak
|
||||
[19385] = {100,"T2"}; --Empowered Leggings
|
||||
[19392] = {0,"T2"}; --Girdle of the Fallen Crusader
|
||||
[19393] = {16,"T2"}; --Primalist's Linked Waistguard
|
||||
[19391] = {40,"T2"}; --Shimmering Geta
|
||||
[19390] = {24,"T2"}; --Taut Dragonhide Gloves
|
||||
[19389] = {44,"T2"}; --Taut Dragonhide Shoulderpads
|
||||
|
||||
[19376] = {20,"T2"}; --Archimtiros' Ring of Reckoning
|
||||
[19364] = {64,"T2"}; --Ashkandi, Greatsword of the Bro..
|
||||
[19381] = {84,"T2"}; --Boots of the Shadow Flame
|
||||
[19378] = {20,"T2"}; --Cloak of the Brood Lord
|
||||
[19363] = {100,"T2"}; --Crul'shoruk, Edge of Chaos
|
||||
[19360] = {60,"T2"}; --Lok'amir il Romathis
|
||||
[19375] = {96,"T2"}; --Mish'undare, Circlet of the Mind…
|
||||
[19379] = {116,"T2"}; --Neltharion's Tear
|
||||
[19377] = {76,"T2"}; --Prestor's Talisman of Connivery
|
||||
[19382] = {76,"T2"}; --Pure Elementium Band
|
||||
[19356] = {80,"T2"}; --Staff of the Shadow Flame
|
||||
[19380] = {36,"T2"}; --Therazane's Link
|
||||
|
||||
[19003] = {52,"T2"}; --Head of Nefarian
|
||||
[19383] = {52,"T2"}; --Head of Nefarian
|
||||
[19366] = {52,"T2"}; --Head of Nefarian
|
||||
[19384] = {52,"T2"}; --Head of Nefarian
|
||||
|
||||
[16900] = {40,"T2"}; --Stormrage Raiment
|
||||
[16902] = {40,"T2"}; --Stormrage Raiment
|
||||
[16897] = {48,"T2"}; --Stormrage Raiment
|
||||
[16904] = {28,"T2"}; --Stormrage Raiment
|
||||
[16899] = {32,"T2"}; --Stormrage Raiment
|
||||
[16903] = {32,"T2"}; --Stormrage Raiment
|
||||
[16901] = {32,"T2"}; --Stormrage Raiment
|
||||
[16898] = {32,"T2"}; --Stormrage Raiment
|
||||
|
||||
[16939] = {40,"T2"}; --Dragonstalker Armor
|
||||
[16937] = {40,"T2"}; --Dragonstalker Armor
|
||||
[16942] = {48,"T2"}; --Dragonstalker Armor
|
||||
[16935] = {28,"T2"}; --Dragonstalker Armor
|
||||
[16940] = {32,"T2"}; --Dragonstalker Armor
|
||||
[16936] = {32,"T2"}; --Dragonstalker Armor
|
||||
[16938] = {32,"T2"}; --Dragonstalker Armor
|
||||
[16941] = {32,"T2"}; --Dragonstalker Armor
|
||||
|
||||
[16914] = {40,"T2"}; --Netherwind Regalia
|
||||
[16917] = {40,"T2"}; --Netherwind Regalia
|
||||
[16916] = {48,"T2"}; --Netherwind Regalia
|
||||
[16918] = {28,"T2"}; --Netherwind Regalia
|
||||
[16913] = {32,"T2"}; --Netherwind Regalia
|
||||
[16818] = {32,"T2"}; --Netherwind Regalia
|
||||
[16915] = {32,"T2"}; --Netherwind Regalia
|
||||
[16912] = {32,"T2"}; --Netherwind Regalia
|
||||
|
||||
[16921] = {40,"T2"}; --Vestments of Transcendence
|
||||
[16924] = {40,"T2"}; --Vestments of Transcendence
|
||||
[16923] = {48,"T2"}; --Vestments of Transcendence
|
||||
[16926] = {28,"T2"}; --Vestments of Transcendence
|
||||
[16920] = {32,"T2"}; --Vestments of Transcendence
|
||||
[16925] = {32,"T2"}; --Vestments of Transcendence
|
||||
[16922] = {32,"T2"}; --Vestments of Transcendence
|
||||
[16919] = {32,"T2"}; --Vestments of Transcendence
|
||||
|
||||
[16908] = {40,"T2"}; --Bloodfang Armor
|
||||
[16832] = {40,"T2"}; --Bloodfang Armor
|
||||
[16905] = {48,"T2"}; --Bloodfang Armor
|
||||
[16911] = {28,"T2"}; --Bloodfang Armor
|
||||
[16907] = {32,"T2"}; --Bloodfang Armor
|
||||
[16910] = {32,"T2"}; --Bloodfang Armor
|
||||
[16909] = {32,"T2"}; --Bloodfang Armor
|
||||
[16906] = {32,"T2"}; --Bloodfang Armor
|
||||
|
||||
[16947] = {40,"T2"}; --The Ten Storms
|
||||
[16945] = {40,"T2"}; --The Ten Storms
|
||||
[16950] = {48,"T2"}; --The Ten Storms
|
||||
[16943] = {28,"T2"}; --The Ten Storms
|
||||
[16948] = {32,"T2"}; --The Ten Storms
|
||||
[16944] = {32,"T2"}; --The Ten Storms
|
||||
[16946] = {32,"T2"}; --The Ten Storms
|
||||
[16949] = {32,"T2"}; --The Ten Storms
|
||||
|
||||
[16929] = {40,"T2"}; --Nemesis Raiment
|
||||
[16932] = {40,"T2"}; --Nemesis Raiment
|
||||
[16931] = {48,"T2"}; --Nemesis Raiment
|
||||
[16934] = {28,"T2"}; --Nemesis Raiment
|
||||
[16928] = {32,"T2"}; --Nemesis Raiment
|
||||
[16933] = {32,"T2"}; --Nemesis Raiment
|
||||
[16930] = {32,"T2"}; --Nemesis Raiment
|
||||
[16927] = {32,"T2"}; --Nemesis Raiment
|
||||
|
||||
[16963] = {40,"T2"}; --Battlegear of Wrath
|
||||
[16961] = {40,"T2"}; --Battlegear of Wrath
|
||||
[16966] = {48,"T2"}; --Battlegear of Wrath
|
||||
[16959] = {28,"T2"}; --Battlegear of Wrath
|
||||
[16964] = {32,"T2"}; --Battlegear of Wrath
|
||||
[16960] = {32,"T2"}; --Battlegear of Wrath
|
||||
[16962] = {32,"T2"}; --Battlegear of Wrath
|
||||
[16965] = {32,"T2"}; --Battlegear of Wrath
|
||||
|
||||
-------------------
|
||||
--- Molten Core ---
|
||||
-------------------
|
||||
[13982] = {4,"T1"}; -- [DEBUG]Warblade of Caer Darrow
|
||||
[17109] = {8,"T1"}; --Choker of Enlightenment
|
||||
[17077] = {4,"T1"}; --Crimson Shocker
|
||||
[18861] = {4,"T1"}; --Flamewalker Legplates
|
||||
[18879] = {40,"T1"}; --Heavy Dark Iron Ring
|
||||
[18870] = {8,"T1"}; --Helm of the Lifegiver
|
||||
[18872] = {8,"T1"}; --Manastorm Leggings
|
||||
[19147] = {8,"T1"}; --Ring of Spell Power
|
||||
[19145] = {60,"T1"}; --Robe of Volatile Power
|
||||
[18875] = {60,"T1"}; --Salamander Scale Pants
|
||||
[18878] = {16,"T1"}; --Sorcerous Dagger
|
||||
[19146] = {8,"T1"}; --Wristguards of Stability
|
||||
[16665] = {0,"T1"}; --Tome of Tranquilizing Shot
|
||||
|
||||
[18823] = {12,"T1"}; --Aged Core Leather Gloves
|
||||
[18829] = {20,"T1"}; --Deep Earth Spaulders
|
||||
[17073] = {12,"T1"}; --Earthshaker
|
||||
[18203] = {16,"T1"}; --Eskhandar's Right Claw
|
||||
[19142] = {12,"T1"}; --Fire Runed Grimoire
|
||||
[19143] = {14,"T1"}; --Flameguard Gauntlets
|
||||
[18861] = {4,"T1"}; --Flamewalker Legplates
|
||||
[18824] = {0,"T1"}; --Magma Tempered Boots
|
||||
[19136] = {36,"T1"}; --Mana Igniting Cord
|
||||
[17065] = {48,"T1"}; --Medallion of Steadfast Might
|
||||
[18822] = {12,"T1"}; --Obsidian Edged Blade
|
||||
[18821] = {48,"T1"}; --Quick Strike Ring
|
||||
[19144] = {12,"T1"}; --Sabatons of the Flamewalker
|
||||
[17069] = {56,"T1"}; --Striker's Mark
|
||||
[18820] = {48,"T1"}; --Talisman of Ephemeral Power
|
||||
|
||||
[17105] = {24,"T1"}; --Aurastone Hammer
|
||||
[18832] = {28,"T1"}; --Brutality Blade
|
||||
[17066] = {28,"T1"}; --Drillborer Disk
|
||||
[17071] = {12,"T1"}; --Gutgore Ripper
|
||||
[18564] = {150,"T1"}; --Bindings of the Windseeker
|
||||
|
||||
[17110] = {8,"T1"}; --Seal of the Archmagus
|
||||
|
||||
[18563] = {150,"T1"}; --Bindings of the Windseeker
|
||||
|
||||
[17074] = {4,"T1"}; --Shadowstrike
|
||||
|
||||
[17103] = {36,"T1"}; --Azuresong Mageblade
|
||||
[17072] = {24,"T1"}; --Blastershot Launcher
|
||||
[18842] = {28,"T1"}; --Staff of Dominance
|
||||
|
||||
[18703] = {48,"T1"}; --Ancient Petrified Leaf
|
||||
[19140] = {36,"T1"}; --Cauterizing Band
|
||||
[18806] = {4,"T1"}; --Core Forged Greaves
|
||||
[18805] = {44,"T1"}; --Core Hound Tooth
|
||||
[18803] = {12,"T1"}; --Finkle's Lava Dredger
|
||||
[19139] = {4,"T1"}; --Fireguard Shoulders
|
||||
[18811] = {4,"T1"}; --Fireproof Cloak
|
||||
[18808] = {16,"T1"}; --Gloves of the Hypnotic Flame
|
||||
[18809] = {16,"T1"}; --Sash of Whispered Secrets
|
||||
[18646] = {36,"T1"}; --The Eye of Divinity
|
||||
[18810] = {48,"T1"}; --Wild Growth Spaulders
|
||||
[18812] = {36,"T1"}; --Wristguards of True Flight
|
||||
|
||||
[17063] = {80,"T1"}; --Band of Accuria
|
||||
[19138] = {28,"T1"}; --Band of Sulfuras
|
||||
[17076] = {24,"T1"}; --Bonereaver's Edge
|
||||
[18814] = {60,"T1"}; --Choker of the Firelord
|
||||
[17102] = {20,"T1"}; --Cloak of the Shrouded Mists
|
||||
[18817] = {56,"T1"}; --Crown of Destruction
|
||||
[17107] = {16,"T1"}; --Dragon's Blood Cape
|
||||
[18815] = {12,"T1"}; --Essence of the Pure Flame
|
||||
[17106] = {16,"T1"}; --Malistar's Defender
|
||||
[19137] = {80,"T1"}; --Onslaught Girdle
|
||||
[18816] = {56,"T1"}; --Perdition's Blade
|
||||
[17082] = {12,"T1"}; --Shard of the Flame
|
||||
[17104] = {20,"T1"}; --Spinal Reaper
|
||||
|
||||
[17204] = {150,"T1"}; --Eye of Sulfuras
|
||||
|
||||
[16834] = {12,"T1"}; --Cenarion Raiment
|
||||
[16836] = {12,"T1"}; --Cenarion Raiment
|
||||
[16833] = {16,"T1"}; --Cenarion Raiment
|
||||
[16830] = {8,"T1"}; --Cenarion Raiment
|
||||
[16831] = {12,"T1"}; --Cenarion Raiment
|
||||
[16828] = {8,"T1"}; --Cenarion Raiment
|
||||
[16835] = {12,"T1"}; --Cenarion Raiment
|
||||
[16829] = {12,"T1"}; --Cenarion Raiment
|
||||
|
||||
[16846] = {12,"T1"}; --Giantstalker Armor
|
||||
[16848] = {12,"T1"}; --Giantstalker Armor
|
||||
[16845] = {16,"T1"}; --Giantstalker Armor
|
||||
[16850] = {8,"T1"}; --Giantstalker Armor
|
||||
[16852] = {12,"T1"}; --Giantstalker Armor
|
||||
[16851] = {8,"T1"}; --Giantstalker Armor
|
||||
[16847] = {12,"T1"}; --Giantstalker Armor
|
||||
[16849] = {12,"T1"}; --Giantstalker Armor
|
||||
|
||||
[16795] = {12,"T1"}; --Arcanist Regalia
|
||||
[16797] = {12,"T1"}; --Arcanist Regalia
|
||||
[16798] = {16,"T1"}; --Arcanist Regalia
|
||||
[16799] = {8,"T1"}; --Arcanist Regalia
|
||||
[16801] = {12,"T1"}; --Arcanist Regalia
|
||||
[16802] = {8,"T1"}; --Arcanist Regalia
|
||||
[16796] = {12,"T1"}; --Arcanist Regalia
|
||||
[16800] = {12,"T1"}; --Arcanist Regalia
|
||||
|
||||
[16813] = {12,"T1"}; --Vestments of Prophecy
|
||||
[16816] = {12,"T1"}; --Vestments of Prophecy
|
||||
[16815] = {16,"T1"}; --Vestments of Prophecy
|
||||
[16819] = {8,"T1"}; --Vestments of Prophecy
|
||||
[16812] = {12,"T1"}; --Vestments of Prophecy
|
||||
[16817] = {8,"T1"}; --Vestments of Prophecy
|
||||
[16814] = {12,"T1"}; --Vestments of Prophecy
|
||||
[16811] = {12,"T1"}; --Vestments of Prophecy
|
||||
|
||||
[16821] = {12,"T1"}; --Nightslayer Armor
|
||||
[16823] = {12,"T1"}; --Nightslayer Armor
|
||||
[16820] = {16,"T1"}; --Nightslayer Armor
|
||||
[16825] = {8,"T1"}; --Nightslayer Armor
|
||||
[16826] = {12,"T1"}; --Nightslayer Armor
|
||||
[16827] = {8,"T1"}; --Nightslayer Armor
|
||||
[16822] = {12,"T1"}; --Nightslayer Armor
|
||||
[16824] = {12,"T1"}; --Nightslayer Armor
|
||||
|
||||
[16842] = {12,"T1"}; --The Earthfury
|
||||
[16844] = {12,"T1"}; --The Earthfury
|
||||
[16841] = {16,"T1"}; --The Earthfury
|
||||
[16840] = {8,"T1"}; --The Earthfury
|
||||
[16839] = {12,"T1"}; --The Earthfury
|
||||
[16838] = {8,"T1"}; --The Earthfury
|
||||
[16843] = {12,"T1"}; --The Earthfury
|
||||
[16837] = {12,"T1"}; --The Earthfury
|
||||
|
||||
[16808] = {12,"T1"}; --Felheart Raiment
|
||||
[16807] = {12,"T1"}; --Felheart Raiment
|
||||
[16809] = {16,"T1"}; --Felheart Raiment
|
||||
[16804] = {8,"T1"}; --Felheart Raiment
|
||||
[16805] = {12,"T1"}; --Felheart Raiment
|
||||
[16806] = {8,"T1"}; --Felheart Raiment
|
||||
[16810] = {12,"T1"}; --Felheart Raiment
|
||||
[16803] = {12,"T1"}; --Felheart Raiment
|
||||
|
||||
[16866] = {12,"T1"}; --Battlegear of Might
|
||||
[16868] = {12,"T1"}; --Battlegear of Might
|
||||
[16865] = {16,"T1"}; --Battlegear of Might
|
||||
[16861] = {8,"T1"}; --Battlegear of Might
|
||||
[16863] = {12,"T1"}; --Battlegear of Might
|
||||
[16864] = {8,"T1"}; --Battlegear of Might
|
||||
[16867] = {12,"T1"}; --Battlegear of Might
|
||||
[16862] = {12,"T1"}; --Battlegear of Might
|
||||
|
||||
---------------------
|
||||
--- Single Bosses ---
|
||||
---------------------
|
||||
[17067] = {12,"T1.5"}; --Ancient Cornerstone Grimoire
|
||||
[17068] = {32,"T1.5"}; --Deathbringer
|
||||
[18205] = {16,"T1.5"}; --Eskhandar's Collar
|
||||
[18705] = {0,"T1.5"}; --Mature Black Dragon Sinew
|
||||
[18813] = {4,"T1.5"}; --Ring of Binding
|
||||
[17078] = {20,"T1.5"}; --Sapphiron Drape
|
||||
[17064] = {68,"T1.5"}; --Shard of the Scale
|
||||
[17075] = {24,"T1.5"}; --Vis'kag the Bloodletter
|
||||
|
||||
[18423] = {48,"T1.5"}; --Head of Onyxia
|
||||
[18403] = {48,"T1.5"}; --Head of Onyxia
|
||||
[18404] = {48,"T1.5"}; --Head of Onyxia
|
||||
[18406] = {48,"T1.5"}; --Head of Onyxia
|
||||
|
||||
[19130] = {52,"T1.5"}; --Cold Snap
|
||||
[19132] = {92,"T1.5"}; --Crystal Adorned Crown
|
||||
[18208] = {12,"T1.5"}; --Drape of Benediction
|
||||
[18202] = {20,"T1.5"}; --Eskhandar's Left Claw
|
||||
[17070] = {36,"T1.5"}; --Fang of the Mystics
|
||||
[18545] = {4,"T1.5"}; --Leggings of Arcane Supremacy
|
||||
[18704] = {0,"T1.5"}; --Mature Black Dragon Sinew
|
||||
[18541] = {68,"T1.5"}; --Puissant Cape
|
||||
[19131] = {80,"T1.5"}; --Snowblind Shoes
|
||||
[18542] = {12,"T1.5"}; --Typhoon
|
||||
[18547] = {4,"T1.5"}; --Unmelting Ice Girdle
|
||||
|
||||
[20625] = {4,"T1.5"}; --Belt of the Dark Bog
|
||||
[20626] = {20,"T1.5"}; --Black Bark Wristbands
|
||||
[20627] = {64,"T1.5"}; --Dark Heart Pants
|
||||
[20628] = {72,"T1.5"}; --Deviate Growth Cap
|
||||
[20630] = {0,"T1.5"}; --Gauntlets of the Shining Light
|
||||
[20629] = {12,"T1.5"}; --Malignant Footguards
|
||||
|
||||
[20619] = {4,"T1.5"}; --Acid Inscribed Greaves
|
||||
[20617] = {28,"T1.5"}; --Ancient Corroded Leggings
|
||||
[20616] = {16,"T1.5"}; --Dragonbone Wristguards
|
||||
[20615] = {16,"T1.5"}; --Dragonspur Wraps
|
||||
[20579] = {4,"T1.5"}; --Green Dragonskin Cloak
|
||||
[20618] = {40,"T1.5"}; --Gloves of Delusional Power
|
||||
[20580] = {32,"T1.5"}; --Hammer of Bestial Fury
|
||||
[20581] = {40,"T1.5"}; --Staff of Rampant Growth
|
||||
[20582] = {20,"T1.5"}; --Trance Stone
|
||||
[20644] = {4,"T1.5"}; --Nightmare Engulfed Object
|
||||
[20600] = {4,"T1.5"}; --Nightmare Engulfed Object
|
||||
|
||||
[20621] = {24,"T1.5"}; --Boots of the Endless Moor
|
||||
[20623] = {32,"T1.5"}; --Circlet of Restless Dreams
|
||||
[20622] = {20,"T1.5"}; --Dragonheart Necklace
|
||||
[20599] = {28,"T1.5"}; --Polished Ironwood Crossbow
|
||||
[20624] = {24,"T1.5"}; --Ring of the Unliving
|
||||
|
||||
[20634] = {24,"T1.5"}; --Boots of Fright
|
||||
[20631] = {40,"T1.5"}; --Mendicant's Slippers
|
||||
[20632] = {20,"T1.5"}; --Mindtear Band
|
||||
[20577] = {36,"T1.5"}; --Nightmare Blade
|
||||
[20633] = {4,"T1.5"}; --Unnatural Leather Spaulders
|
||||
|
||||
[20637] = {4,"T1.5"}; --Acid Inscribed Pauldrons
|
||||
[20578] = {36,"T1.5"}; --Emerald Dragonfang
|
||||
[20636] = {68,"T1.5"}; --Hibernating Crystal
|
||||
[20635] = {36,"T1.5"}; --Jade Inlaid Vestments
|
||||
[20638] = {32,"T1.5"}; --Leggings of the Demented Mind
|
||||
[20639] = {0,"T1.5"}; --Strangely Glyphed Legplates
|
||||
|
||||
[17113] = {24,"T1.5"}; --Amberseal Keeper
|
||||
[19135] = {12,"T1.5"}; --Blacklight Bracer
|
||||
[17111] = {16,"T1.5"}; --Blazefury Medallion
|
||||
[18544] = {20,"T1.5"}; --Doomhide Gauntlets
|
||||
[17112] = {20,"T1.5"}; --Empyrean Demolisher
|
||||
[18204] = {12,"T1.5"}; --Eskhandar's Pelt
|
||||
[19133] = {72,"T1.5"}; --Fel Infused Leggings
|
||||
[19134] = {16,"T1.5"}; --Flayed Doomguard Belt
|
||||
[18546] = {24,"T1.5"}; --Infernal Headcage
|
||||
[18543] = {12,"T1.5"}; --Ring of Entropy
|
||||
[18665] = {0,"T1.5"}; --The Eye of Shadow
|
||||
}
|
||||
sepgp.gp_prices = prices
|
||||
--[[local price_scaling = {
|
||||
["T1"] = 1,
|
||||
["T1.5"] = 1,
|
||||
["T2"] = 3,
|
||||
["T2.5"] = 6,
|
||||
["T3"] = 9
|
||||
}]]
|
||||
local progress_scaling = {
|
||||
["T3"] = {["T3"]=1,["T2.5"]=1,["T2"]=1,["T1.5"]=1,["T1"]=1},
|
||||
["T2.5"] = {["T3"]=1.5,["T2.5"]=1.5,["T2"]=2,["T1.5"]=2,["T1"]=2},
|
||||
["T2"] = {["T3"]=1.5,["T2.5"]=1.5,["T2"]=3,["T1.5"]=3,["T1"]=3},
|
||||
["T1"] = {["T3"]=4.5,["T2.5"]=4.5,["T2"]=4.5,["T1.5"]=9,["T1"]=9}
|
||||
}
|
||||
local function get_adjusted_price(price,tier,progress)
|
||||
if not progress_scaling[progress] then return price end
|
||||
if not progress_scaling[progress][tier] then return price end
|
||||
return math.floor(progress_scaling[progress][tier] * price)
|
||||
end
|
||||
|
||||
sepgp_prices = sepgp:NewModule("sepgp_prices", "AceDB-2.0")
|
||||
|
||||
function sepgp_prices:GetPrice(item,progress)
|
||||
if not progress then progress = "T3" end
|
||||
local itemID,found,_,itemString,data,tier
|
||||
local price
|
||||
if (type(item)=="number") then
|
||||
itemID = tonumber(item)
|
||||
end
|
||||
if (type(item)=="string") then
|
||||
found,_,is = string.find(item,"^item:(%d+):.+")
|
||||
if (found) then
|
||||
itemID = tonumber(is)
|
||||
else
|
||||
found,_,il = string.find(item,"^|c%x+|Hitem:(%d+):.+")
|
||||
if (found) then
|
||||
itemID = tonumber(il)
|
||||
end
|
||||
end
|
||||
end
|
||||
if (itemID) then
|
||||
data = prices[itemID]
|
||||
if (data) then
|
||||
price, tier = data[1], data[2]
|
||||
price = get_adjusted_price(price,tier,progress)
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
return price
|
||||
end
|
||||
@@ -0,0 +1,90 @@
|
||||
local T = AceLibrary("Tablet-2.0")
|
||||
local D = AceLibrary("Dewdrop-2.0")
|
||||
local C = AceLibrary("Crayon-2.0")
|
||||
|
||||
local BC = AceLibrary("Babble-Class-2.2")
|
||||
|
||||
sepgp_reserves = sepgp:NewModule("sepgp_reserves", "AceDB-2.0")
|
||||
|
||||
function sepgp_reserves:OnEnable()
|
||||
if not T:IsRegistered("sepgp_reserves") then
|
||||
T:Register("sepgp_reserves",
|
||||
"children", function()
|
||||
T:SetTitle("shootyepgp reserves")
|
||||
self:OnTooltipUpdate()
|
||||
end,
|
||||
"showTitleWhenDetached", true,
|
||||
"showHintWhenDetached", true,
|
||||
"cantAttach", true,
|
||||
"menu", function()
|
||||
D:AddLine(
|
||||
"text", "Refresh",
|
||||
"tooltipText", "Refresh window",
|
||||
"func", function() sepgp_reserves:Refresh() end
|
||||
)
|
||||
end
|
||||
)
|
||||
end
|
||||
if not T:IsAttached("sepgp_reserves") then
|
||||
T:Open("sepgp_reserves")
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp_reserves:OnDisable()
|
||||
T:Close("sepgp_reserves")
|
||||
end
|
||||
|
||||
function sepgp_reserves:Refresh()
|
||||
T:Refresh("sepgp_reserves")
|
||||
end
|
||||
|
||||
function sepgp_reserves:Toggle(forceShow)
|
||||
if T:IsAttached("sepgp_reserves") then
|
||||
T:Detach("sepgp_reserves")
|
||||
if (T:IsLocked("sepgp_reserves")) then
|
||||
T:ToggleLocked("sepgp_reserves")
|
||||
end
|
||||
elseif (forceShow) then
|
||||
else
|
||||
T:Attach("sepgp_reserves")
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp_reserves:OnClickItem(name)
|
||||
ChatFrame_SendTell(name)
|
||||
end
|
||||
|
||||
function sepgp_reserves:BuildReservesTable()
|
||||
--{name,class,rank,alt}
|
||||
table.sort(sepgp.reserves, function(a,b)
|
||||
if (a[2] ~= b[2]) then return a[2] > b[2]
|
||||
else return a[1] > b[1] end
|
||||
end)
|
||||
return sepgp.reserves
|
||||
end
|
||||
|
||||
function sepgp_reserves:OnTooltipUpdate()
|
||||
local cdcat = T:AddCategory(
|
||||
"columns", 2
|
||||
)
|
||||
cdcat:AddLine(
|
||||
"text", C:Orange("Countdown"),
|
||||
"text2", sepgp.timer.cd_text
|
||||
)
|
||||
local cat = T:AddCategory(
|
||||
"columns", 3,
|
||||
"text", C:Orange("Name"), "child_textR", 1, "child_textG", 1, "child_textB", 1, "child_justify", "LEFT",
|
||||
"text2", C:Orange("Rank"), "child_text2R", 1, "child_text2G", 1, "child_text2B", 0, "child_justify2", "RIGHT",
|
||||
"text3", C:Orange("OnAlt"), "child_text3R", 0, "child_text3G", 1, "child_text3B", 0, "child_justify3", "RIGHT"
|
||||
)
|
||||
local t = self:BuildReservesTable()
|
||||
for i = 1, table.getn(t) do
|
||||
local name, class, rank, alt = unpack(t[i])
|
||||
cat:AddLine(
|
||||
"text", C:Colorize(BC:GetHexColor(class), name),
|
||||
"text2", rank,
|
||||
"text3", alt or "",
|
||||
"func", "OnClickItem", "arg1", self, "arg2", alt or name
|
||||
)
|
||||
end
|
||||
end
|
||||
+906
@@ -0,0 +1,906 @@
|
||||
sepgp = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceHook-2.1", "AceDB-2.0", "AceDebug-2.0", "AceEvent-2.0", "AceModuleCore-2.0", "FuBarPlugin-2.0")
|
||||
sepgp:SetModuleMixins("AceDebug-2.0")
|
||||
local D = AceLibrary("Dewdrop-2.0")
|
||||
|
||||
local playerName = (UnitName("player"))
|
||||
local shooty_basegp = 135
|
||||
local shooty_decay = 0.85
|
||||
local shooty_max = 10000
|
||||
local shooty_timeout = 45
|
||||
local shooty_reservechan = "Reserves"
|
||||
local shooty_reservecall = string.format("{shootyepgp}Type \"+\" in this channel if on main, or \"+<MainName>\" if on alt within %dsec.",shooty_timeout)
|
||||
local shooty_reserveanswer = "^(%+)(%a*)$"
|
||||
local out = "|cff9664c8shootyepgp:|r %s"
|
||||
local lastUpdate = 0
|
||||
local needInit = true
|
||||
local shooty_debugchat
|
||||
local running_check,running_bid
|
||||
local partyUnit,raidUnit = {},{}
|
||||
local reserves_blacklist,bids_blacklist = {},{}
|
||||
do
|
||||
for i=1,40 do
|
||||
raidUnit[i] = "raid"..i
|
||||
end
|
||||
for i=1,4 do
|
||||
partyUnit[i] = "party"..i
|
||||
end
|
||||
end
|
||||
|
||||
sepgp.reserves = {}
|
||||
sepgp.timer = CreateFrame("Frame")
|
||||
sepgp.timer.cd_text = ""
|
||||
sepgp.timer:Hide()
|
||||
sepgp.timer:SetScript("OnUpdate",function() sepgp.OnUpdate(this,arg1) end)
|
||||
|
||||
sepgp.bids_main,sepgp.bids_off,sepgp.bid_item = {},{},{}
|
||||
|
||||
function sepgp:OnInitialize() -- ADDON_LOADED (1) unless LoD
|
||||
if sepgp_saychannel == nil then sepgp_saychannel = "GUILD" end
|
||||
if sepgp_decay == nil then sepgp_decay = shooty_decay end
|
||||
if sepgp_progress == nil then sepgp_progress = "T1" end
|
||||
if sepgp_discount == nil then sepgp_discount = 0.25 end
|
||||
sepgp.extratip = CreateFrame("GameTooltip","shootyepgp_tooltip",UIParent,"GameTooltipTemplate")
|
||||
end
|
||||
|
||||
function sepgp:AceEvent_FullyInitialized() -- SYNTHETIC EVENT, later than PLAYER_LOGIN, PLAYER_ENTERING_WORLD (3)
|
||||
for i=1,NUM_CHAT_WINDOWS do
|
||||
local tab = getglobal("ChatFrame"..i.."Tab")
|
||||
local cf = getglobal("ChatFrame"..i)
|
||||
local tabName = tab:GetText()
|
||||
if tab ~= nil and (string.lower(tabName) == "debug") then
|
||||
shooty_debugchat = cf
|
||||
ChatFrame_RemoveAllMessageGroups(shooty_debugchat)
|
||||
shooty_debugchat:SetMaxLines(1024)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if (not sepgp_main) or (sepgp_main == "") then
|
||||
StaticPopup_Show("SHOOTY_EPGP_SET_MAIN")
|
||||
end
|
||||
|
||||
if not self:IsEventScheduled("shootyepgpChannelInit") then
|
||||
self:ScheduleEvent("shootyepgpChannelInit",self.getReserveStatus,2,self)
|
||||
end
|
||||
|
||||
-- if pfUI loaded, skin the extra tooltip
|
||||
if (pfUI) and pfUI.api and pfUI.api.CreateBackdrop and pfUI_config and pfUI_config.tooltip and pfUI_config.tooltip.alpha then
|
||||
pfUI.api.CreateBackdrop(sepgp.extratip,nil,nil,pfUI_config.tooltip.alpha)
|
||||
end
|
||||
-- hook tooltip to add our GP values
|
||||
sepgp:TipHook()
|
||||
end
|
||||
|
||||
function sepgp:OnEnable() -- PLAYER_LOGIN (2)
|
||||
sepgp:RegisterEvent("GUILD_ROSTER_UPDATE",function()
|
||||
if (arg1) then -- member join /leave
|
||||
self:SetRefresh(true)
|
||||
end
|
||||
end)
|
||||
sepgp:RegisterEvent("RAID_ROSTER_UPDATE",function()
|
||||
self:SetRefresh(true)
|
||||
end)
|
||||
sepgp:RegisterEvent("PARTY_MEMBERS_CHANGED",function()
|
||||
self:SetRefresh(true)
|
||||
end)
|
||||
sepgp:RegisterEvent("CHAT_MSG_RAID","captureLootCall")
|
||||
sepgp:RegisterEvent("CHAT_MSG_RAID_LEADER","captureLootCall")
|
||||
sepgp:RegisterEvent("CHAT_MSG_RAID_WARNING","captureLootCall")
|
||||
sepgp:RegisterEvent("CHAT_MSG_WHISPER","captureBid")
|
||||
|
||||
if (IsInGuild()) then
|
||||
if (GetNumGuildMembers()==0) then
|
||||
GuildRoster()
|
||||
end
|
||||
end
|
||||
|
||||
if AceLibrary("AceEvent-2.0"):IsFullyInitialized() then
|
||||
self:AceEvent_FullyInitialized()
|
||||
else
|
||||
self:RegisterEvent("AceEvent_FullyInitialized")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function sepgp:OnMenuRequest()
|
||||
D:FeedAceOptionsTable(self:buildMenu())
|
||||
end
|
||||
|
||||
function sepgp:TipHook()
|
||||
self:SecureHook(GameTooltip, "SetBagItem", function(this, bag, slot)
|
||||
sepgp:AddDataToTooltip(GameTooltip, GetContainerItemLink(bag, slot))
|
||||
end
|
||||
) -- DEBUG - remove for final
|
||||
self:SecureHook(GameTooltip, "SetLootItem", function(this, slot)
|
||||
sepgp:AddDataToTooltip(GameTooltip, GetLootSlotLink(slot))
|
||||
end
|
||||
)
|
||||
self:SecureHook(GameTooltip, "SetLootRollItem", function(this, id)
|
||||
sepgp:AddDataToTooltip(GameTooltip, GetLootRollItemLink(id))
|
||||
end
|
||||
)
|
||||
self:SecureHook("SetItemRef", function(link, name, button)
|
||||
if (link and name and ItemRefTooltip) then
|
||||
if (strsub(link, 1, 6) ~= "Player") then
|
||||
if (ItemRefTooltip:IsVisible()) then
|
||||
if (not DressUpFrame:IsVisible()) then
|
||||
sepgp:AddDataToTooltip(ItemRefTooltip, link)
|
||||
end
|
||||
ItemRefTooltip.isDisplayDone = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
self:HookScript(GameTooltip, "OnHide", function()
|
||||
if sepgp.extratip:IsVisible() then sepgp.extratip:Hide() end
|
||||
self.hooks[GameTooltip]["OnHide"]()
|
||||
end
|
||||
)
|
||||
self:HookScript(ItemRefTooltip, "OnHide", function()
|
||||
if sepgp.extratip:IsVisible() then sepgp.extratip:Hide() end
|
||||
self.hooks[ItemRefTooltip]["OnHide"]()
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function sepgp:getReserveStatus()
|
||||
if (IsInGuild()) then
|
||||
local guildName = (GetGuildInfo("player"))
|
||||
if (guildName) and guildName ~= "" then
|
||||
sepgp_reservechannel = string.format("%sReserves",(string.gsub(guildName," ","")))
|
||||
end
|
||||
end
|
||||
if sepgp_reservechannel == nil then sepgp_reservechannel = shooty_reservechan end
|
||||
local reservesChannelID = tonumber((GetChannelName(sepgp_reservechannel)))
|
||||
if (reservesChannelID) and (reservesChannelID ~= 0) then
|
||||
sepgp:reservesToggle(true)
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:AddDataToTooltip(tooltip,itemlink,itemstring)
|
||||
local price
|
||||
if (itemstring) then
|
||||
price = sepgp_prices:GetPrice(itemstring,sepgp_progress)
|
||||
elseif (itemlink) then
|
||||
price = sepgp_prices:GetPrice(itemlink,sepgp_progress)
|
||||
end
|
||||
if not price then return end
|
||||
local textRight = string.format("cost:|cff32cd32%d|r offspec:|cff20b2aa%d|r",price,math.floor(price*sepgp_discount))
|
||||
if (tooltip:NumLines() < 29) then
|
||||
tooltip:AddLine(" ")
|
||||
tooltip:AddDoubleLine("|cff9664c8shootyepgp|r",textRight)
|
||||
tooltip:Show()
|
||||
else
|
||||
sepgp.extratip:ClearLines()
|
||||
sepgp.extratip:SetOwner(tooltip,"ANCHOR_NONE")
|
||||
sepgp.extratip:ClearAllPoints()
|
||||
sepgp.extratip:SetPoint("TOPLEFT", tooltip, "BOTTOMLEFT", 0, -5)
|
||||
sepgp.extratip:SetPoint("TOPRIGHT", tooltip, "BOTTOMRIGHT", 0, -5)
|
||||
sepgp.extratip:AddDoubleLine("|cff9664c8shootyepgp|r",textRight)
|
||||
sepgp.extratip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:OnUpdate(elapsed)
|
||||
sepgp.timer.count_down = sepgp.timer.count_down - elapsed
|
||||
lastUpdate = lastUpdate + elapsed
|
||||
if sepgp.timer.count_down <= 0 then
|
||||
running_check = nil
|
||||
sepgp.timer:Hide()
|
||||
sepgp.timer.cd_text = "|cffff0000Finished|r"
|
||||
sepgp_reserves:Refresh()
|
||||
else
|
||||
sepgp.timer.cd_text = string.format("|cff00ff00%02d|r|cffffffffsec|r",sepgp.timer.count_down)
|
||||
end
|
||||
if lastUpdate > 0.5 then
|
||||
lastUpdate = 0
|
||||
sepgp_reserves:Refresh()
|
||||
end
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Communication
|
||||
-------------------
|
||||
function sepgp:flashFrame(frame)
|
||||
local tabFlash = getglobal(frame:GetName().."TabFlash")
|
||||
if ( not frame.isDocked or (frame == SELECTED_DOCK_FRAME) or UIFrameIsFlashing(tabFlash) ) then
|
||||
return
|
||||
end
|
||||
tabFlash:Show()
|
||||
UIFrameFlash(tabFlash, 0.25, 0.25, 60, nil, 0.5, 0.5)
|
||||
end
|
||||
|
||||
function sepgp:debugPrint(msg)
|
||||
if (shooty_debugchat) then
|
||||
shooty_debugchat:AddMessage(string.format(out,msg))
|
||||
sepgp:flashFrame(shooty_debugchat)
|
||||
else
|
||||
sepgp:defaultPrint(msg)
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:defaultPrint(msg)
|
||||
if not DEFAULT_CHAT_FRAME:IsVisible() then
|
||||
FCF_SelectDockFrame(DEFAULT_CHAT_FRAME)
|
||||
end
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format(out,msg))
|
||||
end
|
||||
|
||||
function sepgp:simpleSay(msg)
|
||||
SendChatMessage(string.format("shootyepgp: %s",msg), sepgp_saychannel)
|
||||
end
|
||||
|
||||
function sepgp:adminSay(msg)
|
||||
-- API is broken on Elysium
|
||||
-- local g_listen, g_speak, officer_listen, officer_speak, g_promote, g_demote, g_invite, g_remove, set_gmotd, set_publicnote, view_officernote, edit_officernote, set_guildinfo = GuildControlGetRankFlags()
|
||||
-- if (officer_speak) then
|
||||
SendChatMessage(string.format("shootyepgp: %s",msg),"OFFICER")
|
||||
-- end
|
||||
end
|
||||
|
||||
---------------------
|
||||
-- EPGP Operations
|
||||
---------------------
|
||||
function sepgp:init_notes(guild_index,note,officernote)
|
||||
if not tonumber(note) or (tonumber(note) < 0) then
|
||||
GuildRosterSetPublicNote(guild_index,0)
|
||||
end
|
||||
if not tonumber(officernote) or (tonumber(officernote) < shooty_basegp) then
|
||||
GuildRosterSetOfficerNote(guild_index,shooty_basegp)
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:update_ep(getname,ep)
|
||||
for i = 1, GetNumGuildMembers(1) do
|
||||
local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i)
|
||||
if (name==getname) then
|
||||
sepgp:init_notes(i,note,officernote)
|
||||
GuildRosterSetPublicNote(i,ep)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:update_gp(getname,gp)
|
||||
for i = 1, GetNumGuildMembers(1) do
|
||||
local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i)
|
||||
if (name==getname) then
|
||||
sepgp:init_notes(i,note,officernote)
|
||||
GuildRosterSetOfficerNote(i,gp)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:get_ep(getname,note) -- gets ep by name or note
|
||||
if (note) then
|
||||
if tonumber(note)==nil then return 0 end
|
||||
end
|
||||
for i = 1, GetNumGuildMembers(1) do
|
||||
local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i)
|
||||
if tonumber(note)==nil then note=0 end
|
||||
if (name==getname) then return tonumber(note) end
|
||||
end
|
||||
return(0)
|
||||
end
|
||||
|
||||
function sepgp:get_gp(getname,officernote) -- gets gp by name or officernote
|
||||
if (officernote) then
|
||||
if tonumber(officernote)==nil then return shooty_basegp end
|
||||
end
|
||||
for i = 1, GetNumGuildMembers(1) do
|
||||
local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i)
|
||||
if tonumber(officernote)==nil then officernote=shooty_basegp end
|
||||
if (name==getname) then return tonumber(officernote) end
|
||||
end
|
||||
return(shooty_basegp)
|
||||
end
|
||||
|
||||
function sepgp:award_raid_ep(ep) -- awards ep to raid members in zone
|
||||
if GetNumRaidMembers()>0 then
|
||||
sepgp:simpleSay(string.format("Giving %d ep to all raidmembers",ep))
|
||||
for i = 1, GetNumRaidMembers(true) do
|
||||
local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i)
|
||||
sepgp:givename_ep(name,ep)
|
||||
end
|
||||
else UIErrorsFrame:AddMessage("You aren't in a raid dummy",1,0,0)end
|
||||
end
|
||||
|
||||
function sepgp:award_reserve_ep(ep) -- awards ep to reserve list
|
||||
if table.getn(sepgp.shooty_reserves) > 0 then
|
||||
sepgp:simpleSay(string.format("Giving %d ep to active reserves",ep))
|
||||
for i, name in ipairs(sepgp.shooty_reserves) do
|
||||
sepgp:givename_ep(name,ep)
|
||||
end
|
||||
sepgp.reserves = {}
|
||||
reserves_blacklist = {}
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:givename_ep(getname,ep) -- awards ep to a single character
|
||||
sepgp:debugPrint(string.format("Giving %d ep to %s",ep,getname))
|
||||
ep = ep + sepgp:get_ep(getname)
|
||||
sepgp:update_ep(getname,ep)
|
||||
end
|
||||
|
||||
function sepgp:givename_gp(getname,gp) -- assigns gp to a single character
|
||||
sepgp:debugPrint(string.format("Giving %d gp to %s",gp,getname))
|
||||
local oldgp = sepgp:get_gp(getname)
|
||||
local newgp = gp + oldgp
|
||||
sepgp:adminSay(string.format("Awarding %d GP to %s. (Previous: %d, New: %d)",gp,getname,oldgp,newgp))
|
||||
sepgp:update_gp(getname,newgp)
|
||||
end
|
||||
|
||||
function sepgp:decay_epgp() -- decays entire roster's ep and gp
|
||||
for i = 1, GetNumGuildMembers(1) do
|
||||
local name,_,_,_,class,_,ep,gp,_,_ = GetGuildRosterInfo(i)
|
||||
ep = tonumber(ep)
|
||||
gp = tonumber(gp)
|
||||
if ep == nil then
|
||||
else
|
||||
ep = math.max(0,sepgp:num_round(ep*sepgp_decay))
|
||||
GuildRosterSetPublicNote(i,ep)
|
||||
gp = math.max(shooty_basegp,sepgp:num_round(gp*sepgp_decay))
|
||||
GuildRosterSetOfficerNote(i,gp)
|
||||
end
|
||||
end
|
||||
local msg = string.format("all ep and gp decayed by %d%%",(1-sepgp_decay)*100)
|
||||
sepgp:simpleSay(msg)
|
||||
end
|
||||
|
||||
function sepgp:gp_reset()
|
||||
for i = 1, GetNumGuildMembers(1) do
|
||||
GuildRosterSetOfficerNote(i, shooty_basegp)
|
||||
end
|
||||
sepgp:debugPrint(string.format("All GP has been reset to %d.",shooty_basegp))
|
||||
end
|
||||
|
||||
---------
|
||||
-- Menu
|
||||
---------
|
||||
local T = AceLibrary("Tablet-2.0")
|
||||
|
||||
sepgp.defaultMinimapPosition = 180
|
||||
sepgp.cannotDetachTooltip = true
|
||||
sepgp.tooltipHidderWhenEmpty = false
|
||||
sepgp.hasIcon = "Interface\\Icons\\INV_Misc_Orb_04"
|
||||
|
||||
function sepgp:OnTooltipUpdate()
|
||||
T:SetHint("|cffffff00Click|r to toggle Standings. \n|cffffff00Ctrl+Click|r to toggle Reserves. \n|cffffff00Alt+Click|r to toggle Bids. \n|cffffff00Right-Click|r for Options.")
|
||||
end
|
||||
|
||||
function sepgp:OnClick()
|
||||
if (IsControlKeyDown()) then
|
||||
sepgp_reserves:Toggle()
|
||||
elseif (IsAltKeyDown()) then
|
||||
sepgp_bids:Toggle()
|
||||
else
|
||||
sepgp_standings:Toggle()
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:SetRefresh(flag)
|
||||
needRefresh = flag
|
||||
if (flag) then
|
||||
sepgp_standings:Refresh()
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:buildRosterTable()
|
||||
local g, r = { }, { }
|
||||
local numGuildMembers = GetNumGuildMembers(1)
|
||||
if (sepgp_raidonly) and GetNumRaidMembers() > 0 then
|
||||
for i = 1, GetNumRaidMembers(true) do
|
||||
local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i)
|
||||
r[name] = true
|
||||
end
|
||||
end
|
||||
for i = 1, numGuildMembers do
|
||||
local member_name,_,_,_,class,_,ep,gp,_,_ = GetGuildRosterInfo(i)
|
||||
if (sepgp_raidonly) and next(r) then
|
||||
if r[member_name] then
|
||||
table.insert(g,{["name"]=member_name,["class"]=class})
|
||||
end
|
||||
else
|
||||
table.insert(g,{["name"]=member_name,["class"]=class})
|
||||
end
|
||||
end
|
||||
return g
|
||||
end
|
||||
|
||||
function sepgp:buildClassMemberTable(roster,epgp)
|
||||
local desc,usage
|
||||
if epgp == "ep" then
|
||||
desc = "Account EPs to %s."
|
||||
usage = "<EP>"
|
||||
elseif epgp == "gp" then
|
||||
desc = "Account GPs to %s."
|
||||
usage = "<GP>"
|
||||
end
|
||||
local c = { }
|
||||
for i,member in ipairs(roster) do
|
||||
local class,name = member.class, member.name
|
||||
if c[class] == nil then
|
||||
c[class] = { }
|
||||
c[class].type = "group"
|
||||
c[class].name = class
|
||||
c[class].desc = class .. " members"
|
||||
c[class].hidden = function() return not (CanEditOfficerNote() and CanEditPublicNote()) end
|
||||
c[class].args = { }
|
||||
end
|
||||
if c[class].args[name] == nil then
|
||||
c[class].args[name] = { }
|
||||
c[class].args[name].type = "text"
|
||||
c[class].args[name].name = name
|
||||
c[class].args[name].desc = string.format(desc,name)
|
||||
c[class].args[name].usage = usage
|
||||
c[class].args[name].get = false
|
||||
if epgp == "ep" then
|
||||
c[class].args[name].set = function(v) sepgp:givename_ep(name, tonumber(v)) end
|
||||
elseif epgp == "gp" then
|
||||
c[class].args[name].set = function(v) sepgp:givename_gp(name, tonumber(v)) end
|
||||
end
|
||||
c[class].args[name].validate = function(v) return (type(v) == "number" or tonumber(v)) and tonumber(v) < shooty_max end
|
||||
end
|
||||
end
|
||||
return c
|
||||
end
|
||||
|
||||
local options
|
||||
function sepgp:buildMenu()
|
||||
if not (options) then
|
||||
options = {
|
||||
type = "group",
|
||||
desc = "shootyepgp options",
|
||||
args = { }
|
||||
}
|
||||
options.args["ep"] = {
|
||||
type = "group",
|
||||
name = "+EPs to Member",
|
||||
desc = "Account EPs for member.",
|
||||
order = 10,
|
||||
hidden = function() return not (CanEditOfficerNote() and CanEditPublicNote()) end,
|
||||
}
|
||||
options.args["ep_raid"] = {
|
||||
type = "text",
|
||||
name = "+EPs to Raid",
|
||||
desc = "Award EPs to all raid members.",
|
||||
order = 20,
|
||||
get = false,
|
||||
set = function(v) sepgp:award_raid_ep(tonumber(v)) end,
|
||||
usage = "<EP>",
|
||||
hidden = function() return not (CanEditOfficerNote() and CanEditPublicNote()) end,
|
||||
validate = function(v)
|
||||
local n = tonumber(v)
|
||||
return n and n >= 0 and n < shooty_max
|
||||
end
|
||||
}
|
||||
options.args["gp"] = {
|
||||
type = "group",
|
||||
name = "+GPs to Member",
|
||||
desc = "Account GPs for member.",
|
||||
order = 30,
|
||||
hidden = function() return not (CanEditOfficerNote() and CanEditPublicNote()) end,
|
||||
}
|
||||
options.args["ep_reserves"] = {
|
||||
type = "text",
|
||||
name = "+EPs to Reserves",
|
||||
desc = "Award EPs to all active Reserves.",
|
||||
order = 40,
|
||||
get = false,
|
||||
set = function(v) sepgp:award_reserve_ep(tonumber(v))end,
|
||||
usage = "<EP>",
|
||||
hidden = function() return not (CanEditOfficerNote() and CanEditPublicNote()) end,
|
||||
validate = function(v)
|
||||
local n = tonumber(v)
|
||||
return n and n >= 0 and n < shooty_max
|
||||
end
|
||||
}
|
||||
options.args["reserves"] = {
|
||||
type = "toggle",
|
||||
name = "Enable Reserves",
|
||||
desc = "Participate in Reserves Functionality.\n|cffff0000Needs Main Set in Options.|r",
|
||||
order = 50,
|
||||
get = function() return (sepgp.reservesChannelID ~= nil) and (sepgp.reservesChannelID ~= 0) end,
|
||||
set = function(v) sepgp:reservesToggle(v) end,
|
||||
disabled = function() return (sepgp_main == nil) end
|
||||
}
|
||||
options.args["afkcheck_reserves"] = {
|
||||
type = "execute",
|
||||
name = "AFK Check Reserves",
|
||||
desc = "AFK Check Reserves List",
|
||||
order = 60,
|
||||
hidden = function() return not (CanEditOfficerNote() and CanEditPublicNote()) end,
|
||||
func = function() sepgp:afkcheck_reserves() end
|
||||
}
|
||||
options.args["set_main"] = {
|
||||
type = "text",
|
||||
name = "Set Main",
|
||||
desc = "Set your Main Character for Reserve List.",
|
||||
order = 70,
|
||||
usage = "<MainChar>",
|
||||
get = function() return sepgp_main end,
|
||||
set = function(v) sepgp_main = (sepgp:verifyGuildMember(v)) end,
|
||||
}
|
||||
options.args["raid_only"] = {
|
||||
type = "toggle",
|
||||
name = "Raid Only",
|
||||
desc = "Only show members in raid.",
|
||||
order = 80,
|
||||
get = function() return not not sepgp_raidonly end,
|
||||
set = function(v)
|
||||
sepgp_raidonly = not sepgp_raidonly
|
||||
sepgp:SetRefresh(true)
|
||||
end,
|
||||
}
|
||||
options.args["report_channel"] = {
|
||||
type = "text",
|
||||
name = "Reporting channel",
|
||||
desc = "Channel used by reporting functions.",
|
||||
order = 90,
|
||||
get = function() return sepgp_saychannel end,
|
||||
set = function(v) sepgp_saychannel = v end,
|
||||
validate = { "PARTY", "RAID", "GUILD", "OFFICER" },
|
||||
}
|
||||
options.args["progress_tier"] = {
|
||||
type = "text",
|
||||
name = "Raid Progress",
|
||||
desc = "Highest Tier the Guild is raiding.\nUsed to adjust GP Prices.",
|
||||
order = 95,
|
||||
get = function() return sepgp_progress end,
|
||||
set = function(v) sepgp_progress = v sepgp_bids:Refresh() end,
|
||||
validate = { ["T3"]="4.Naxxramas", ["T2.5"]="3.Temple of Ahn\'Qiraj", ["T2"]="2.Blackwing Lair", ["T1"]="1.Molten Core"},
|
||||
}
|
||||
options.args["decay"] = {
|
||||
type = "execute",
|
||||
name = "Decay EPGP",
|
||||
desc = string.format("Decays all EPGP by %d%%",(1-(sepgp_decay or shooty_decay))*100),
|
||||
order = 100,
|
||||
hidden = function() return not (CanEditOfficerNote() and CanEditPublicNote()) end,
|
||||
func = function() sepgp:decay_epgp() end
|
||||
}
|
||||
options.args["set_decay"] = {
|
||||
type = "range",
|
||||
name = "Set Decay %",
|
||||
desc = "Set Decay percentage (Admin only).",
|
||||
order = 110,
|
||||
usage = "<Decay>",
|
||||
get = function() return (1.0-sepgp_decay) end,
|
||||
set = function(v) sepgp_decay = (1 - v) end,
|
||||
min = 0.01,
|
||||
max = 0.5,
|
||||
step = 0.01,
|
||||
bigStep = 0.05,
|
||||
isPercent = true,
|
||||
hidden = function() return not (IsGuildLeader()) end,
|
||||
}
|
||||
options.args["set_discount"] = {
|
||||
type = "range",
|
||||
name = "Offspec Price %",
|
||||
desc = "Set Offspec / Resistance Items GP Percent.",
|
||||
order = 115,
|
||||
get = function() return sepgp_discount end,
|
||||
set = function(v) sepgp_discount = v end,
|
||||
min = 0,
|
||||
max = 1,
|
||||
step = 0.05,
|
||||
isPercent = true
|
||||
}
|
||||
options.args["reset"] = {
|
||||
type = "execute",
|
||||
name = "Reset GP",
|
||||
desc = string.format("gives everybody %d basic GP (Admin only).",shooty_basegp),
|
||||
order = 120,
|
||||
hidden = function() return not (IsGuildLeader()) end,
|
||||
func = function() sepgp:gp_reset() end
|
||||
}
|
||||
end
|
||||
if (needInit) or (needRefresh) then
|
||||
local members = sepgp:buildRosterTable()
|
||||
self:debugPrint(string.format("Scanning %d members for EP/GP data. (%s)",table.getn(members),(sepgp_raidonly and "Raid" or "Full")))
|
||||
options.args["ep"].args = sepgp:buildClassMemberTable(members,"ep")
|
||||
options.args["gp"].args = sepgp:buildClassMemberTable(members,"gp")
|
||||
if (needInit) then needInit = false end
|
||||
if (needRefresh) then needRefresh = false end
|
||||
end
|
||||
return options
|
||||
end
|
||||
|
||||
---------------
|
||||
-- Reserves
|
||||
---------------
|
||||
function sepgp:reservesToggle(flag)
|
||||
local reservesChannelID = tonumber((GetChannelName(sepgp_reservechannel)))
|
||||
if (flag) then -- we want in
|
||||
if (reservesChannelID) and reservesChannelID ~= 0 then
|
||||
sepgp.reservesChannelID = reservesChannelID
|
||||
return true
|
||||
else
|
||||
sepgp:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE","reservesChannelChange")
|
||||
JoinChannelByName(sepgp_reservechannel)
|
||||
return
|
||||
end
|
||||
else -- we want out
|
||||
if (reservesChannelID) and reservesChannelID ~= 0 then
|
||||
sepgp:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE","reservesChannelChange")
|
||||
LeaveChannelByName(sepgp_reservechannel)
|
||||
return
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:reservesChannelChange(msg,_,_,_,_,_,_,_,channel)
|
||||
if (msg) and (channel) and (channel == sepgp_reservechannel) then
|
||||
if msg == "YOU_JOINED" then
|
||||
sepgp.reservesChannelID = tonumber((GetChannelName(sepgp_reservechannel)))
|
||||
RemoveChatWindowChannel(DEFAULT_CHAT_FRAME:GetID(), sepgp_reservechannel)
|
||||
sepgp:RegisterEvent("CHAT_MSG_CHANNEL","captureReserveChatter")
|
||||
elseif msg == "YOU_LEFT" then
|
||||
sepgp.reservesChannelID = nil
|
||||
if sepgp:IsEventRegistered("CHAT_MSG_CHANNEL") then
|
||||
sepgp:UnregisterEvent("CHAT_MSG_CHANNEL")
|
||||
end
|
||||
end
|
||||
sepgp:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE")
|
||||
D:Close()
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:afkcheck_reserves()
|
||||
if (running_check) then return end
|
||||
if sepgp.reservesChannelID ~= nil and ((GetChannelName(sepgp.reservesChannelID)) == sepgp.reservesChannelID) then
|
||||
reserves_blacklist = {}
|
||||
sepgp.reserves = {}
|
||||
running_check = true
|
||||
sepgp.timer.count_down = shooty_timeout
|
||||
sepgp.timer:Show()
|
||||
SendChatMessage(shooty_reservecall,"CHANNEL",nil,sepgp.reservesChannelID)
|
||||
sepgp_reserves:Toggle(true)
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:sendReserverResponce()
|
||||
if sepgp.reservesChannelID ~= nil then
|
||||
if (sepgp_main) then
|
||||
if sepgp_main == playerName then
|
||||
SendChatMessage("+","CHANNEL",nil,sepgp.reservesChannelID)
|
||||
else
|
||||
SendChatMessage(string.format("+%s",sepgp_main),"CHANNEL",nil,sepgp.reservesChannelID)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:captureReserveChatter(text, sender, _, _, _, _, _, _, channel)
|
||||
if not (channel) or not (channel == sepgp_reservechannel) then return end
|
||||
local reserve, reserve_class, reserve_rank, reserve_alt = nil,nil,nil,nil
|
||||
local r,_,rdy,name = string.find(text,shooty_reserveanswer)
|
||||
if (r) and (running_check) then -- need to check that the same person is not declaring multiple mains (cheaters)
|
||||
if (rdy) then
|
||||
if (name) and (name ~= "") then
|
||||
reserve, reserve_class, reserve_rank = sepgp:verifyGuildMember(name)
|
||||
if reserve ~= sender then
|
||||
reserve_alt = sender
|
||||
end
|
||||
else
|
||||
reserve, reserve_class, reserve_rank = sepgp:verifyGuildMember(sender)
|
||||
end
|
||||
if reserve and reserve_class and reserve_rank then
|
||||
if reserve_alt then
|
||||
if not reserves_blacklist[reserve_alt] then
|
||||
reserves_blacklist[reserve_alt] = true
|
||||
table.insert(sepgp.reserves,{reserve,reserve_class,reserve_rank,reserve_alt})
|
||||
else
|
||||
sepgp:defaultPrint(string.format("|cffff0000%s|r has already added a member to Reserves. Discarding!"))
|
||||
end
|
||||
else
|
||||
if not reserves_blacklist[reserve] then
|
||||
reserves_blacklist[reserve] = true
|
||||
table.insert(sepgp.reserves,{reserve,reserve_class,reserve_rank})
|
||||
else
|
||||
sepgp:defaultPrint(string.format("|cffff0000%s|r has already added a member to Reserves. Discarding!"))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
local q = string.find(text,"^{shootyepgp}Type")
|
||||
if (q) and not (running_check) then
|
||||
if (not UnitInRaid("player")) or (not sepgp:inRaid(sender)) then
|
||||
StaticPopup_Show("SHOOTY_EPGP_RESERVE_AFKCHECK_RESPONCE")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---------
|
||||
-- Bids
|
||||
---------
|
||||
local lootCall = {}
|
||||
lootCall.whisp = {
|
||||
"^(w)[%s%p%c]+.+",".+[%s%p%c]+(w)$",".+[%s%p%c]+(w)[%s%p%c]+.*",".*[%s%p%c]+(w)[%s%p%c]+.+",
|
||||
"^(whisper)[%s%p%c]+.+",".+[%s%p%c]+(whisper)$",".+[%s%p%c]+(whisper)[%s%p%c]+.*",".*[%s%p%c]+(whisper)[%s%p%c]+.+",
|
||||
".+[%s%p%c]+(bid)[%s%p%c]*.*",".*[%s%p%c]*(bid)[%s%p%c]+.+"
|
||||
}
|
||||
lootCall.ms = {".+(%+).*",".*(%+).+", ".+(ms).*",".*(ms).+", ".+(mainspec).*",".*(mainspec).+"}
|
||||
lootCall.os = {".+(%-).*",".*(%-).+", ".+(os).*",".*(os).+", ".+(offspec).*",".*(offspec).+"}
|
||||
function sepgp:captureLootCall(text, sender)
|
||||
if not (IsRaidLeader() or self:lootMaster()) then return end
|
||||
if not sender == playerName then return end
|
||||
if not (string.find(text, "|Hitem:", 1, true)) then return end
|
||||
local lowtext = string.lower(text)
|
||||
local whisperkw_found, mskw_found, oskw_found, link_found
|
||||
local _, itemLink, itemColor, itemString, itemName
|
||||
for _,f in ipairs(lootCall.whisp) do
|
||||
whisperkw_found = string.find(lowtext,f)
|
||||
if (whisperkw_found) then break end
|
||||
end
|
||||
for _,f in ipairs(lootCall.ms) do
|
||||
mskw_found = string.find(lowtext,f)
|
||||
if (mskw_found) then break end
|
||||
end
|
||||
for _,f in ipairs(lootCall.os) do
|
||||
oskw_found = string.find(lowtext,f)
|
||||
if (oskw_found) then break end
|
||||
end
|
||||
if (whisperkw_found) or (mskw_found) or (oskw_found) then
|
||||
_,_,itemLink = string.find(text,"(|c%x+|H.+|h%[.+%]|h|r)")
|
||||
if (itemLink) and (itemLink ~= "") then
|
||||
link_found, _, itemColor, itemString, itemName = string.find(itemLink, "^(|c%x+)|H(.+)|h(%[.+%])")
|
||||
end
|
||||
if (link_found) then
|
||||
self:clearBids()
|
||||
sepgp.bid_item.link = itemString
|
||||
sepgp.bid_item.linkFull = itemLink
|
||||
sepgp.bid_item.name = string.format("%s%s|r",itemColor,itemName)
|
||||
self:ScheduleEvent("shootyepgpBidTimeout",self.clearBids,360,self)
|
||||
running_bid = true
|
||||
self:debugPrint("Capturing Bids for 6min.")
|
||||
sepgp_bids:Toggle(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local lootBid = {}
|
||||
lootBid.ms = {"(%+)",".+(%+).*",".*(%+).+",".*(%+).*","(ms)"}
|
||||
lootBid.os = {"(%-)",".+(%-).*",".*(%-).+",".*(%-).*","(os)"}
|
||||
function sepgp:captureBid(text, sender)
|
||||
if not (running_bid) then return end
|
||||
if not (IsRaidLeader() or self:lootMaster()) then return end
|
||||
if not sepgp.bid_item.link then return end
|
||||
local mskw_found,oskw_found
|
||||
local lowtext = string.lower(text)
|
||||
for _,f in ipairs(lootBid.ms) do
|
||||
mskw_found = string.find(text,f)
|
||||
if (mskw_found) then break end
|
||||
end
|
||||
for _,f in ipairs(lootBid.os) do
|
||||
oskw_found = string.find(text,f)
|
||||
if (oskw_found) then break end
|
||||
end
|
||||
if (mskw_found) or (oskw_found) then
|
||||
if self:inRaid(sender) then
|
||||
if bids_blacklist[sender] == nil then
|
||||
for i = 1, GetNumGuildMembers(1) do
|
||||
local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i)
|
||||
if name == sender then
|
||||
local ep = self:get_ep(name,note)
|
||||
local gp = self:get_gp(name,officernote)
|
||||
if (mskw_found) then
|
||||
bids_blacklist[sender] = true
|
||||
table.insert(sepgp.bids_main,{name,class,ep,gp,ep/gp})
|
||||
elseif (oskw_found) then
|
||||
bids_blacklist[sender] = true
|
||||
table.insert(sepgp.bids_off,{name,class,ep,gp,ep/gp})
|
||||
end
|
||||
sepgp_bids:Toggle(true)
|
||||
sepgp_bids:Refresh()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp:clearBids()
|
||||
sepgp:defaultPrint("clearBids")
|
||||
sepgp.bid_item = {}
|
||||
sepgp.bids_main = {}
|
||||
sepgp.bids_off = {}
|
||||
bids_blacklist = {}
|
||||
if self:IsEventScheduled("shootyepgpBidTimeout") then
|
||||
self:CancelScheduledEvent("shootyepgpBidTimeout")
|
||||
end
|
||||
running_bid = false
|
||||
sepgp_bids:Refresh()
|
||||
end
|
||||
|
||||
------------
|
||||
-- Utility
|
||||
------------
|
||||
function sepgp:num_round(i)
|
||||
return math.floor(i+0.5)
|
||||
end
|
||||
|
||||
function sepgp:verifyGuildMember(name)
|
||||
for i=1,GetNumGuildMembers(1) do
|
||||
local g_name, g_rank, g_rankIndex, g_level, g_class, g_zone, g_note, g_officernote, g_online = GetGuildRosterInfo(i)
|
||||
if (string.lower(name) == string.lower(g_name)) and (tonumber(g_level) == MAX_PLAYER_LEVEL) then
|
||||
return g_name, g_class, g_rank
|
||||
end
|
||||
end
|
||||
if (name) and name ~= "" then
|
||||
sepgp:defaultPrint(string.format("%s not found in the guild or not max level!",name))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function sepgp:inRaid(name)
|
||||
for i=1,GetNumRaidMembers() do
|
||||
if name == (UnitName(raidUnit[i])) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function sepgp:lootMaster()
|
||||
local method, lootmasterID = GetLootMethod()
|
||||
if method == "master" and lootmasterID == 0 then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-------------
|
||||
-- Dialogs
|
||||
-------------
|
||||
StaticPopupDialogs["SHOOTY_EPGP_SET_MAIN"] = {
|
||||
text = "Set your main to be able to participate in Reserve List EPGP Checks.",
|
||||
button1 = TEXT(ACCEPT),
|
||||
button2 = TEXT(CANCEL),
|
||||
hasEditBox = 1,
|
||||
maxLetters = 12,
|
||||
OnAccept = function()
|
||||
local editBox = getglobal(this:GetParent():GetName().."EditBox")
|
||||
sepgp_main = sepgp:verifyGuildMember(editBox:GetText())
|
||||
end,
|
||||
OnShow = function()
|
||||
getglobal(this:GetName().."EditBox"):SetText(sepgp_main or "")
|
||||
getglobal(this:GetName().."EditBox"):SetFocus()
|
||||
end,
|
||||
OnHide = function()
|
||||
if ( ChatFrameEditBox:IsVisible() ) then
|
||||
ChatFrameEditBox:SetFocus()
|
||||
end
|
||||
getglobal(this:GetName().."EditBox"):SetText("")
|
||||
end,
|
||||
EditBoxOnEnterPressed = function()
|
||||
local editBox = getglobal(this:GetParent():GetName().."EditBox")
|
||||
sepgp_main = sepgp:verifyGuildMember(editBox:GetText())
|
||||
this:GetParent():Hide()
|
||||
end,
|
||||
EditBoxOnEscapePressed = function()
|
||||
this:GetParent():Hide()
|
||||
end,
|
||||
timeout = 0,
|
||||
exclusive = 1,
|
||||
whileDead = 1,
|
||||
hideOnEscape = 1
|
||||
}
|
||||
StaticPopupDialogs["SHOOTY_EPGP_RESERVE_AFKCHECK_RESPONCE"] = {
|
||||
text = "Reserves: AFKCheck. Are you available?",
|
||||
button1 = TEXT(YES),
|
||||
button2 = TEXT(NO),
|
||||
OnAccept = function()
|
||||
sepgp:sendReserverResponce()
|
||||
end,
|
||||
timeout = shooty_timeout,
|
||||
exclusive = 1,
|
||||
showAlert = 1,
|
||||
whileDead = 1,
|
||||
hideOnEscape = 1
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
## Interface: 11200
|
||||
## Title: shootyepgp
|
||||
## Notes: Effort Points/Gear Points Loot System
|
||||
## Author: shooty, Roadblock
|
||||
## Version: 2.0
|
||||
## OptionalDeps: Ace2
|
||||
## SavedVariables: sepgp_saychannel,sepgp_groupbyclass,sepgp_raidonly,sepgp_decay,sepgp_reservechannel,sepgp_main,sepgp_progress,sepgp_discount
|
||||
## SavedVariablesPerCharacter:
|
||||
|
||||
Libs\AceLibrary\AceLibrary.lua
|
||||
Libs\AceOO-2.0\AceOO-2.0.lua
|
||||
Libs\AceEvent-2.0\AceEvent-2.0.lua
|
||||
Libs\AceAddon-2.0\AceAddon-2.0.lua
|
||||
Libs\AceHook-2.0\AceHook-2.0.lua
|
||||
Libs\AceConsole-2.0\AceConsole-2.0.lua
|
||||
Libs\AceModuleCore-2.0\AceModuleCore-2.0.lua
|
||||
Libs\AceDB-2.0\AceDB-2.0.lua
|
||||
Libs\AceDebug-2.0\AceDebug-2.0.lua
|
||||
Libs\AceLocale-2.2\AceLocale-2.2.lua
|
||||
|
||||
Libs\Babble-Class-2.2\Babble-Class-2.2.lua
|
||||
Libs\Crayon-2.0\Crayon-2.0.lua
|
||||
Libs\Compost-2.0\Compost-2.0.lua
|
||||
Libs\Dewdrop-2.0\Dewdrop-2.0.lua
|
||||
Libs\FuBarPlugin-2.0\FuBarPlugin-2.0.lua
|
||||
Libs\Tablet-2.0\Tablet-2.0.lua
|
||||
|
||||
shootyepgp.lua
|
||||
standings.lua
|
||||
reserves.lua
|
||||
bids.lua
|
||||
prices.lua
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
local T = AceLibrary("Tablet-2.0")
|
||||
local D = AceLibrary("Dewdrop-2.0")
|
||||
local C = AceLibrary("Crayon-2.0")
|
||||
|
||||
local BC = AceLibrary("Babble-Class-2.2")
|
||||
|
||||
sepgp_standings = sepgp:NewModule("sepgp_standings", "AceDB-2.0")
|
||||
local shooty_export = CreateFrame("Frame", "shooty_exportframe", UIParent)
|
||||
shooty_export:SetWidth(250)
|
||||
shooty_export:SetHeight(150)
|
||||
shooty_export:SetPoint('TOP', UIParent, 'TOP', 0,-80)
|
||||
shooty_export:SetFrameStrata('DIALOG')
|
||||
shooty_export:Hide()
|
||||
shooty_export:SetBackdrop({
|
||||
bgFile = [[Interface\Buttons\WHITE8x8]],
|
||||
insets = {left = 3, right = 3, top = 4, bottom = 3
|
||||
}})
|
||||
shooty_export:SetBackdropColor(0, 0, 0, 0.7)
|
||||
shooty_export.title = shooty_export:CreateFontString(nil,"OVERLAY")
|
||||
shooty_export.title:SetPoint("TOP",0,0)
|
||||
shooty_export.title:SetFont("Fonts\\FRIZQT__.TTF", 12)
|
||||
shooty_export.title:SetWidth(200)
|
||||
shooty_export.title:SetJustifyH("LEFT")
|
||||
shooty_export.title:SetJustifyV("CENTER")
|
||||
shooty_export.title:SetText("Ctrl-C to copy. Esc to close.")
|
||||
shooty_export.title:SetTextColor(204/255,204/255,0)
|
||||
shooty_export.title:SetShadowOffset(1, -1)
|
||||
shooty_export.edit = CreateFrame("EditBox", "shooty_exportedit", shooty_export)
|
||||
shooty_export.edit:SetMultiLine(true)
|
||||
shooty_export.edit:SetAutoFocus(true)
|
||||
shooty_export.edit:EnableMouse(true)
|
||||
shooty_export.edit:SetMaxLetters(0)
|
||||
shooty_export.edit:SetHistoryLines(1)
|
||||
shooty_export.edit:SetFont('Fonts\\ARIALN.ttf', 12, 'THINOUTLINE')
|
||||
shooty_export.edit:SetWidth(290)
|
||||
shooty_export.edit:SetHeight(190)
|
||||
shooty_export.edit:SetScript("OnEscapePressed", function()
|
||||
shooty_export.edit:SetText("")
|
||||
shooty_export:Hide()
|
||||
end)
|
||||
shooty_export.AddSelectText = function(txt)
|
||||
shooty_export.edit:SetText(txt)
|
||||
shooty_export.edit:HighlightText()
|
||||
end
|
||||
shooty_export.scroll = CreateFrame("ScrollFrame", "shooty_exportscroll", shooty_export, 'UIPanelScrollFrameTemplate')
|
||||
shooty_export.scroll:SetPoint('TOPLEFT', shooty_export, 'TOPLEFT', 8, -30)
|
||||
shooty_export.scroll:SetPoint('BOTTOMRIGHT', shooty_export, 'BOTTOMRIGHT', -30, 8)
|
||||
shooty_export.scroll:SetScrollChild(shooty_export.edit)
|
||||
table.insert(UISpecialFrames,"shooty_exportframe")
|
||||
|
||||
function sepgp_standings:OnEnable()
|
||||
if not T:IsRegistered("sepgp_standings") then
|
||||
T:Register("sepgp_standings",
|
||||
"children", function()
|
||||
T:SetTitle("shootyepgp standings")
|
||||
self:OnTooltipUpdate()
|
||||
end,
|
||||
"showTitleWhenDetached", true,
|
||||
"showHintWhenDetached", true,
|
||||
"cantAttach", true,
|
||||
"menu", function()
|
||||
D:AddLine(
|
||||
"text", "Raid Only",
|
||||
"tooltipText", "Only show members in raid.",
|
||||
"checked", sepgp_raidonly,
|
||||
"func", function() sepgp_standings:ToggleRaidOnly() end
|
||||
)
|
||||
D:AddLine(
|
||||
"text", "Group by class",
|
||||
"tooltipText", "Group members by class.",
|
||||
"checked", sepgp_groupbyclass,
|
||||
"func", function() sepgp_standings:ToggleGroupByClass() end
|
||||
)
|
||||
D:AddLine(
|
||||
"text", "Refresh",
|
||||
"tooltipText", "Refresh window",
|
||||
"func", function() sepgp_standings:Refresh() end
|
||||
)
|
||||
D:AddLine(
|
||||
"text", "Export",
|
||||
"tooltipText", "Export standings to csv.",
|
||||
"func", function() sepgp_standings:Export() end
|
||||
)
|
||||
end
|
||||
)
|
||||
end
|
||||
if not T:IsAttached("sepgp_standings") then
|
||||
T:Open("sepgp_standings")
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp_standings:OnDisable()
|
||||
T:Close("sepgp_standings")
|
||||
end
|
||||
|
||||
function sepgp_standings:Refresh()
|
||||
T:Refresh("sepgp_standings")
|
||||
end
|
||||
|
||||
function sepgp_standings:Export()
|
||||
local t = {}
|
||||
for i = 1, GetNumGuildMembers(1) do
|
||||
local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i)
|
||||
local ep = sepgp:get_ep(name,note)
|
||||
local gp = sepgp:get_gp(name,officernote)
|
||||
if ep > 0 then
|
||||
table.insert(t,{name,ep,gp,ep/gp})
|
||||
end
|
||||
end
|
||||
table.sort(t, function(a,b)
|
||||
return tonumber(a[4]) > tonumber(b[4])
|
||||
end)
|
||||
shooty_export:Show()
|
||||
local txt = "Name;EP;GP;PR\n"
|
||||
for i,val in ipairs(t) do
|
||||
txt = string.format("%s%s;%d;%d;%.4f\n",txt,val[1],val[2],val[3],val[4])
|
||||
end
|
||||
shooty_export.AddSelectText(txt)
|
||||
end
|
||||
|
||||
function sepgp_standings:Toggle()
|
||||
if T:IsAttached("sepgp_standings") then
|
||||
T:Detach("sepgp_standings")
|
||||
if (T:IsLocked("sepgp_standings")) then
|
||||
T:ToggleLocked("sepgp_standings")
|
||||
end
|
||||
else
|
||||
T:Attach("sepgp_standings")
|
||||
end
|
||||
end
|
||||
|
||||
function sepgp_standings:ToggleGroupByClass()
|
||||
sepgp_groupbyclass = not sepgp_groupbyclass
|
||||
self:Refresh()
|
||||
end
|
||||
|
||||
function sepgp_standings:ToggleRaidOnly()
|
||||
sepgp_raidonly = not sepgp_raidonly
|
||||
self:Refresh()
|
||||
sepgp:SetRefresh(true)
|
||||
end
|
||||
|
||||
-- Builds a standings table with record:
|
||||
-- name, class, EP, GP, PR
|
||||
-- and sorted by PR
|
||||
function sepgp_standings:BuildStandingsTable()
|
||||
local t = { }
|
||||
local r = { }
|
||||
if (sepgp_raidonly) and GetNumRaidMembers() > 0 then
|
||||
for i = 1, GetNumRaidMembers(true) do
|
||||
local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i)
|
||||
r[name] = true
|
||||
end
|
||||
end
|
||||
for i = 1, GetNumGuildMembers(1) do
|
||||
local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i)
|
||||
local ep = sepgp:get_ep(name)
|
||||
local gp = sepgp:get_gp(name)
|
||||
if ep > 0 then
|
||||
if (sepgp_raidonly) and next(r) then
|
||||
if r[name] then
|
||||
table.insert(t,{name,class,ep,gp,ep/gp})
|
||||
end
|
||||
else
|
||||
table.insert(t,{name,class,ep,gp,ep/gp})
|
||||
end
|
||||
end
|
||||
end
|
||||
if (sepgp_groupbyclass) then
|
||||
table.sort(t, function(a,b)
|
||||
if (a[2] ~= b[2]) then return a[2] > b[2]
|
||||
else return a[5] > b[5] end
|
||||
end)
|
||||
else
|
||||
table.sort(t, function(a,b)
|
||||
return a[5] > b[5]
|
||||
end)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function sepgp_standings:OnTooltipUpdate()
|
||||
local cat = T:AddCategory(
|
||||
"columns", 4,
|
||||
"text", C:Orange("Name"), "child_textR", 1, "child_textG", 1, "child_textB", 1, "child_justify", "LEFT",
|
||||
"text2", C:Orange("ep"), "child_text2R", 1, "child_text2G", 1, "child_text2B", 1, "child_justify2", "RIGHT",
|
||||
"text3", C:Orange("gp"), "child_text3R", 1, "child_text3G", 1, "child_text3B", 1, "child_justify3", "RIGHT",
|
||||
"text4", C:Orange("pr"), "child_text4R", 1, "child_text4G", 1, "child_text4B", 0, "child_justify4", "RIGHT"
|
||||
)
|
||||
local t = self:BuildStandingsTable()
|
||||
for i = 1, table.getn(t) do
|
||||
local name, class, ep, gp, pr = unpack(t[i])
|
||||
cat:AddLine(
|
||||
"text", C:Colorize(BC:GetHexColor(class), name),
|
||||
"text2", string.format("%.4g", ep),
|
||||
"text3", string.format("%.4g", gp),
|
||||
"text4", string.format("%.4g", pr)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user