From 7ac6afa0f19819914c5080f291d83f237b379b3f Mon Sep 17 00:00:00 2001 From: James Whitehead II Date: Mon, 1 Jan 2007 22:08:15 +0000 Subject: [PATCH] * Made settings in Aggro/Range persistent * Added Babelfish.lua for easy localisation * Moved options from PerfectRaidOptions to PerfectRaid_Options * Added Dongle-0.5.0-Alpha --- Babelfish.lua | 50 +++ Dongle.lua | 776 +++++++++++++++++++++++++++++++++++++++++++++++ DongleUtils.lua | 419 +++++++++++++++++++++++++ Localization.enUS.lua | 61 +++- PerfectRaidOptions.lua | 66 ---- PerfectRaid_Aggro.lua | 18 +- PerfectRaid_Options.lua | 103 +++++++ PerfectRaid_Range.lua | 21 +- 8 files changed, 1442 insertions(+), 72 deletions(-) create mode 100644 Babelfish.lua create mode 100644 Dongle.lua create mode 100644 DongleUtils.lua delete mode 100644 PerfectRaidOptions.lua create mode 100644 PerfectRaid_Options.lua diff --git a/Babelfish.lua b/Babelfish.lua new file mode 100644 index 0000000..98d236b --- /dev/null +++ b/Babelfish.lua @@ -0,0 +1,50 @@ +#!/usr/local/bin/lua + +local strings = {} + +for i=1,#arg do + local file = io.open(arg[i], "r") + assert(file, "Could not open " .. arg[i]) + local text = file:read("*all") + + for match in string.gmatch(text, "L%[\"(.-)\"%]") do + strings[match] = true + end +end + +local work = {} + +for k,v in pairs(strings) do table.insert(work, k) end +table.sort(work) + +local values = { + STATUS_ARCANEINT = "Int", + STATUS_BLESSINGKINGS = "BoK", + STATUS_BLESSINGLIGHT = "BoL", + STATUS_BLESSINGMIGHT = "BoM", + STATUS_BLESSINGSALVATION = "BoS", + STATUS_BLESSINGSANCTUARY = "BoSn", + STATUS_BLESSINGWISDOM = "BoW", + STATUS_DIVINESPIRIT = "Spi", + STATUS_FEARWARD = "FW", + STATUS_FORT = "F", + STATUS_INNERVATE = "Inn", + STATUS_MOTW = "M", + STATUS_POWERINFUSION = "PwI", + STATUS_PWS = "PwS", + STATUS_REGROWTH = "Rg", + STATUS_REJUV = "Rj", + STATUS_RENEW = "Rn", + STATUS_SHADOWPROT = "Sh", + STATUS_SOULSTONE = "Ss", + STATUS_THORNS = "Th", + STATUS_WEAKENEDSOUL = "Ws", +} + +print("--Localization.enUS.lua\n") +print("PerfectRaidLocals = {") +for idx,match in ipairs(work) do + local val = values[match] or match + print(string.format("\t[\"%s\"] = \"%s\",", match, val)) +end +print("}\n") diff --git a/Dongle.lua b/Dongle.lua new file mode 100644 index 0000000..d2cd929 --- /dev/null +++ b/Dongle.lua @@ -0,0 +1,776 @@ +--[[------------------------------------------------------------------------- + Copyright (c) 2006, Dongle Development Team + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the Dongle Development Team nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------]] + +local major = "Dongle" +local minor = tonumber(string.match("$Revision: 188 $", "(%d+)") or 1) + +assert(DongleStub, string.format("%s requires DongleStub.", major)) +if not DongleStub:IsNewerVersion(major, minor) then return end + +Dongle = {} +local methods = { + "RegisterEvent", "UnregisterEvent", "UnregisterAllEvents", "TriggerEvent", + "EnableDebug", "Print", "PrintF", "Debug", "DebugF", + "InitializeDB", + "InitializeSlashCommand", + "NewModule", "HasModule", "IterateModules", +} + +local registry = {} +local lookup = {} +local loadqueue = {} +local loadorder = {} +local events = {} +local databases = {} +local commands = {} + +local function assert(level,condition,message) + if not condition then + error(message,level) + end +end + +local function argcheck(value, num, ...) + assert(1, type(num) == "number", + "Bad argument #2 to 'argcheck' (number expected, got " .. type(level) .. ")") + + for i=1,select("#", ...) do + if type(value) == select(i, ...) then return end + end + + local types = strjoin(", ", ...) + local name = string.match(debugstack(), "`argcheck'.-[`<](.-)['>]") or "Unknown" + error(string.format("bad argument #%d to '%s' (%s expected, got %s)", + num, name, types, type(value)), 3) +end + +local function safecall(func,...) + local success,err = pcall(func,...) + if not success then + geterrorhandler()(err) + end +end + +function Dongle:New(name, obj) + argcheck(name, 2, "string") + argcheck(obj, 3, "table", "nil") + + if not obj then + obj = {} + end + + if registry[name] then + error("A Dongle with the name '"..name.."' is already registered.") + end + + local reg = {["obj"] = obj, ["name"] = name} + + registry[name] = reg + lookup[obj] = reg + lookup[name] = reg + + for k,v in pairs(methods) do + obj[v] = self[v] + end + + -- Add this Dongle to the end of the queue + table.insert(loadqueue, obj) + return obj,name +end + +function Dongle:NewModule(name, obj) + local reg = lookup[self] + assert(3, reg, "You must call 'NewModule' from a registered Dongle.") + argcheck(name, 2, "string") + argcheck(obj, 3, "table", "nil") + + obj,name = Dongle:New(name, obj) + + if not reg.modules then reg.modules = {} end + reg.modules[obj] = obj + reg.modules[name] = obj + table.insert(reg.modules, name) + table.sort(reg.modules) + + return obj,name +end + +function Dongle:HasModule(module) + local reg = lookup[self] + assert(3, reg, "You must call 'HasModule' from a registered Dongle.") + argcheck(module, 2, "string", "table") + + return reg.modules[module] +end + +local NIL_FUNC = function() end + +function Dongle:IterateModules() + local reg = lookup[self] + assert(3, reg, "You must call 'IterateModules' from a registered Dongle.") + + if not reg.modules or not next(reg.modules) then return NIL_FUNC end + + local i=1 + return function() + local name = reg.modules[i] + if not name then return end + i = i + 1 + return name, reg.modules[name] + end +end + +function Dongle:ADDON_LOADED(event, ...) + for i=1, #loadqueue do + local obj = loadqueue[i] + table.insert(loadorder, obj) + + if type(obj.Initialize) == "function" then + safecall(obj.Initialize, obj) + end + + if self.initialized and type(obj.Enable) == "function" then + safecall(obj.Enable, obj) + end + loadqueue[i] = nil + end +end + +function Dongle:PLAYER_LOGIN() + self.initialized = true + for i,obj in ipairs(loadorder) do + if type(obj.Enable) == "function" then + safecall(obj.Enable, obj) + end + end +end + +function Dongle:TriggerEvent(event, ...) + argcheck(event, 2, "string") + local eventTbl = events[event] + if eventTbl then + for obj,func in pairs(eventTbl) do + if type(func) == "string" then + if type(obj[func]) == "function" then + safecall(obj[func], obj, event, ...) + end + else + safecall(func,event,...) + end + end + end +end + +function Dongle:OnEvent(frame, event, ...) + local eventTbl = events[event] + if eventTbl then + for obj,func in pairs(eventTbl) do + if type(func) == "string" then + if type(obj[func]) == "function" then + obj[func](obj, event, ...) + end + else + func(event, ...) + end + end + end +end + +function Dongle:RegisterEvent(event, func) + local reg = lookup[self] + assert(3, reg, "You must call 'RegisterEvent' from a registered Dongle.") + argcheck(event, 2, "string") + argcheck(func, 3, "string", "function", "nil") + + -- Name the method the same as the event if necessary + if not func then func = event end + + if not events[event] then + events[event] = {} + frame:RegisterEvent(event) + end + events[event][self] = func +end + +function Dongle:UnregisterEvent(event) + local reg = lookup[self] + assert(3, reg, "You must call 'UnregisterEvent' from a registered Dongle.") + argcheck(event, 2, "string") + + if events[event] then + events[event][self] = nil + if not next(events[event]) then + events[event] = nil + frame:UnregisterEvent(event) + end + end +end + +function Dongle:UnregisterAllEvents() + assert(3, lookup[self], "You must call 'UnregisterAllEvents' from a registered Dongle.") + + for event,tbl in pairs(events) do + tbl[self] = nil + if not next(tbl) then + events[event] = nil + frame:UnregisterEvent(event) + end + end +end + +function Dongle:AdminEvents(event) + local method + if event == "PLAYER_LOGOUT" then + Dongle:ClearDBDefaults() + method = "Disable" + elseif event == "PLAYER_REGEN_DISABLED" then + method = "CombatLockdown" + elseif event == "PLAYER_REGEN_ENABLED" then + method = "CombatUnlock" + end + + if method then + for k,v in pairs(registry) do + local obj = v.obj + if obj[method] then obj[method](obj) end + end + end +end + +function Dongle:EnableDebug(level) + local reg = lookup[self] + assert(3, reg, "You must call 'EnableDebug' from a registered Dongle.") + argcheck(level, 2, "number", "nil") + + reg.debugLevel = level +end + +do + local function argsToStrings(a1, ...) + if select("#", ...) > 0 then + return tostring(a1), argsToStrings(...) + else + return tostring(a1) + end + end + + local function printHelp(obj, method, msg, ...) + local reg = lookup[obj] + assert(4, reg, "You must call '"..method.."' from a registered Dongle.") + + local name = reg.name + msg = "|cFF33FF99"..name.."|r: "..tostring(msg) + if select("#", ...) > 0 then + msg = string.join(", ", msg, argsToStrings(...)) + end + + ChatFrame1:AddMessage(msg) + end + + local function printFHelp(obj, method, msg, ...) + local reg = lookup[obj] + assert(4, reg, "You must call '"..method.."' from a registered Dongle.") + + local name = reg.name + local success,txt = pcall(string.format, "|cFF33FF99%s|r: "..msg, name, ...) + if success then + ChatFrame1:AddMessage(txt) + else + error(string.gsub(txt, "'%?'", string.format("'%s'", method)), 3) + end + end + + function Dongle:Print(...) + return printHelp(self, "Print", ...) + end + + function Dongle:PrintF(...) + return printFHelp(self, "PrintF", ...) + end + + function Dongle:Debug(level, ...) + local reg = lookup[self] + assert(3, reg, "You must call 'Debug' from a registered Dongle.") + argcheck(level, 2, "number") + + if reg.debugLevel and level <= reg.debugLevel then + printHelp(self, "Debug", ...) + end + end + + function Dongle:DebugF(level, ...) + local reg = lookup[self] + assert(3, reg, "You must call 'DebugF' from a registered Dongle.") + argcheck(level, 2, "number") + + if reg.debugLevel and level <= reg.debugLevel then + printFHelp(self, "DebugF", ...) + end + end +end + +local dbMethods = { + "RegisterDefaults", "SetProfile", "GetProfiles", "DeleteProfile", "CopyProfile", + "ResetProfile", "ResetDB", +} + +local function initdb(parent, name, defaults, defaultProfile, olddb) + local sv = getglobal(name) + + if not sv then + sv = {} + setglobal(name, sv) + + -- Lets do the initial setup + + sv.char = {} + sv.faction = {} + sv.realm = {} + sv.class = {} + sv.global = {} + sv.profiles = {} + end + + -- Initialize the specific databases + local char = string.format("%s of %s", UnitName("player"), GetRealmName()) + local realm = string.format("%s", GetRealmName()) + local class = UnitClass("player") + local race = select(2, UnitRace("player")) + local faction = UnitFactionGroup("player") + + -- Initialize the containers + if not sv.char then sv.char = {} end + if not sv.realm then sv.realm = {} end + if not sv.class then sv.class = {} end + if not sv.faction then sv.faction = {} end + if not sv.global then sv.global = {} end + if not sv.profiles then sv.profiles = {} end + if not sv.profileKeys then sv.profileKeys = {} end + + -- Initialize this characters profiles + if not sv.char[char] then sv.char[char] = {} end + if not sv.realm[realm] then sv.realm[realm] = {} end + if not sv.class[class] then sv.class[class] = {} end + if not sv.faction[faction] then sv.faction[faction] = {} end + + -- Try to get the profile selected from the char db + local profileKey = sv.profileKeys[char] or defaultProfile or char + sv.profileKeys[char] = profileKey + + local profileCreated + if not sv.profiles[profileKey] then sv.profiles[profileKey] = {} profileCreated = true end + + if olddb then + for k,v in pairs(olddb) do olddb[k] = nil end + end + + local db = olddb or {} + db.char = sv.char[char] + db.realm = sv.realm[realm] + db.class = sv.class[class] + db.faction = sv.faction[faction] + db.profile = sv.profiles[profileKey] + db.global = sv.global + db.profiles = sv.profiles + + -- Copy methods locally + for idx,method in pairs(dbMethods) do + db[method] = Dongle[method] + end + + -- Set some properties in the object we're returning + db.sv = sv + db.sv_name = name + db.profileKey = profileKey + db.parent = parent + db.charKey = char + db.realmKey = realm + db.classKey = class + db.factionKey = faction + + databases[db] = true + + if defaults then + db:RegisterDefaults(defaults) + end + + return db,profileCreated +end + +function Dongle:InitializeDB(name, defaults, defaultProfile) + local reg = lookup[self] + assert(3, reg, "You must call 'InitializeDB' from a registered Dongle.") + argcheck(name, 2, "string") + argcheck(defaults, 3, "table", "nil") + argcheck(defaultProfile, 4, "string", "nil") + + local db,profileCreated = initdb(self, name, defaults, defaultProfile) + + if profileCreated then + Dongle:TriggerEvent("DONGLE_PROFILE_CREATED", db, self, db.sv_name, db.profileKey) + end + return db +end + +local function copyDefaults(dest, src, force) + for k,v in pairs(src) do + if type(v) == "table" then + if not dest[k] then dest[k] = {} end + copyDefaults(dest[k], v, force) + else + if (dest[k] == nil) or force then + dest[k] = v + end + end + end +end + +-- This function operates on a Dongle DB object +function Dongle.RegisterDefaults(db, defaults) + assert(3, databases[db], "You must call 'RegisterDefaults' from a Dongle database object.") + argcheck(defaults, 2, "table") + + if defaults.char then copyDefaults(db.char, defaults.char) end + if defaults.realm then copyDefaults(db.realm, defaults.realm) end + if defaults.class then copyDefaults(db.class, defaults.class) end + if defaults.faction then copyDefaults(db.faction, defaults.faction) end + if defaults.global then copyDefaults(db.global, defaults.global) end + if defaults.profile then copyDefaults(db.profile, defaults.profile) end + + db.defaults = defaults +end + +local function removeDefaults(db, defaults) + if not db then return end + for k,v in pairs(defaults) do + if type(v) == "table" and db[k] then + removeDefaults(db[k], v) + if not next(db[k]) then + db[k] = nil + end + else + if db[k] == defaults[k] then + db[k] = nil + end + end + end +end + +function Dongle:ClearDBDefaults() + for db in pairs(databases) do + local defaults = db.defaults + local sv = db.sv + + if db and defaults then + if defaults.char then removeDefaults(db.char, defaults.char) end + if defaults.realm then removeDefaults(db.realm, defaults.realm) end + if defaults.class then removeDefaults(db.class, defaults.class) end + if defaults.faction then removeDefaults(db.faction, defaults.faction) end + if defaults.global then removeDefaults(db.global, defaults.global) end + if defaults.profile then + for k,v in pairs(sv.profiles) do + removeDefaults(sv.profiles[k], defaults.profile) + end + end + + -- Remove any blank "profiles" + if not next(db.char) then sv.char[db.charKey] = nil end + if not next(db.realm) then sv.realm[db.realmKey] = nil end + if not next(db.class) then sv.class[db.classKey] = nil end + if not next(db.faction) then sv.faction[db.factionKey] = nil end + if not next(db.global) then sv.global = nil end + end + end +end + +function Dongle.SetProfile(db, name) + assert(3, databases[db], "You must call 'SetProfile' from a Dongle database object.") + argcheck(name, 2, "string") + + local sv = db.sv + local old = sv.profiles[db.profileKey] + local new = sv.profiles[name] + local profileCreated + + if not new then + sv.profiles[name] = {} + new = sv.profiles[name] + profileCreated = true + end + + if db.defaults and db.defaults.profile then + -- Remove the defaults from the old profile + removeDefaults(old, db.defaults.profile) + + -- Inject the defaults into the new profile + copyDefaults(new, db.defaults.profile) + end + + db.profile = new + + -- Save this new profile name + sv.profileKeys[db.charKey] = name + db.profileKey = name + + if profileCreated then + Dongle:TriggerEvent("DONGLE_PROFILE_CREATED", db, db.parent, db.sv_name, db.profileKey) + end + + Dongle:TriggerEvent("DONGLE_PROFILE_CHANGED", db, db.parent, db.sv_name, db.profileKey) +end + +function Dongle.GetProfiles(db, t) + assert(3, databases[db], "You must call 'GetProfiles' from a Dongle database object.") + argcheck(t, 2, "table", "nil") + + t = t or {} + local i = 1 + for profileKey in pairs(db.profiles) do + t[i] = profileKey + i = i + 1 + end + return t, i - 1 +end + +function Dongle.DeleteProfile(db, name) + assert(3, databases[db], "You must call 'DeleteProfile' from a Dongle database object.") + argcheck(name, 2, "string") + + if db.profileKey == name then + error("You cannot delete your active profile. Change profiles, then attempt to delete.", 2) + end + + db.sv.profiles[name] = nil + Dongle:TriggerEvent("DONGLE_PROFILE_DELETED", db, db.parent, db.sv_name, name) +end + +function Dongle.CopyProfile(db, name) + assert(3, databases[db], "You must call 'CopyProfile' from a Dongle database object.") + argcheck(name, 2, "string") + + assert(3, db.profileKey ~= name, "Source/Destination profile cannot be the same profile") + assert(3, type(db.sv.profiles[name]) == "table", "Profile \""..name.."\" doesn't exist.") + + local profile = db.profile + local source = db.sv.profiles[name] + + copyDefaults(profile, source, true) + Dongle:TriggerEvent("DONGLE_PROFILE_COPIED", db, db.parent, db.sv_name, name, db.profileKey) +end + +function Dongle.ResetProfile(db) + assert(3, databases[db], "You must call 'ResetProfile' from a Dongle database object.") + + local profile = db.profile + + for k,v in pairs(profile) do + profile[k] = nil + end + if db.defaults and db.defaults.profile then + copyDefaults(profile, db.defaults.profile) + end + Dongle:TriggerEvent("DONGLE_PROFILE_RESET", db, db.parent, db.sv_name, db.profileKey) +end + + +function Dongle.ResetDB(db, defaultProfile) + assert(3, databases[db], "You must call 'ResetDB' from a Dongle database object.") + argcheck(defaultProfile, 2, "nil", "string") + + local sv = db.sv + for k,v in pairs(sv) do + sv[k] = nil + end + + local parent = db.parent + + initdb(parent, db.sv_name, db.defaults, defaultProfile, db) + Dongle:TriggerEvent("DONGLE_DATABASE_RESET", db, parent, db.sv_name, db.profileKey) + Dongle:TriggerEvent("DONGLE_PROFILE_CREATED", db, db.parent, db.sv_name, db.profileKey) + Dongle:TriggerEvent("DONGLE_PROFILE_CHANGED", db, db.parent, db.sv_name, db.profileKey) + return db +end + +local slashCmdMethods = { + "RegisterSlashHandler", + "PrintUsage", +} + +local function OnSlashCommand(cmd, cmd_line) + if cmd.patterns then + for pattern, tbl in pairs(cmd.patterns) do + if string.match(cmd_line, pattern) then + if type(tbl.handler) == "string" then + cmd.parent[tbl.handler](cmd.parent, string.match(cmd_line, pattern)) + else + tbl.handler(cmd.parent, string.match(cmd_line, pattern)) + end + return + end + end + end + cmd:PrintUsage() +end + +function Dongle:InitializeSlashCommand(desc, name, ...) + local reg = lookup[self] + assert(3, reg, "You must call 'InitializeSlashCommand' from a registered Dongle.") + argcheck(desc, 2, "string") + argcheck(name, 3, "string") + argcheck(select(1, ...), 4, "string") + for i = 2,select("#", ...) do + argcheck(select(i, ...), i+2, "string") + end + + local cmd = {} + cmd.desc = desc + cmd.name = name + cmd.parent = self + cmd.slashes = { ... } + for idx,method in pairs(slashCmdMethods) do + cmd[method] = Dongle[method] + end + + local genv = getfenv(0) + + for i = 1,select("#", ...) do + genv["SLASH_"..name..tostring(i)] = "/"..select(i, ...) + end + + genv.SlashCmdList[name] = function(...) OnSlashCommand(cmd, ...) end + return cmd +end + +function Dongle.RegisterSlashHandler(cmd, desc, pattern, handler) + argcheck(desc, 2, "string") + argcheck(pattern, 3, "string") + argcheck(handler, 4, "function", "string") + + if not cmd.patterns then + cmd.patterns = {} + end + cmd.patterns[pattern] = { + ["desc"] = desc, + ["handler"] = handler, + } +end + +function Dongle.PrintUsage(cmd) + local usage = cmd.desc.."\n".."/"..table.concat(cmd.slashes, ", /")..":\n" + if cmd.patterns then + local descs = {} + for pattern,tbl in pairs(cmd.patterns) do + table.insert(descs, tbl.desc) + end + table.sort(descs) + for _,desc in pairs(descs) do + usage = usage.." - "..desc.."\n" + end + end + cmd.parent:Print(usage) +end + +--[[------------------------------------------------------------------------- + Begin DongleStub required functions and registration +---------------------------------------------------------------------------]] + +function Dongle:GetVersion() return major,minor end + +function Dongle:Activate(old) + if old then + self.registry = old.registry or registry + self.lookup = old.lookup or lookup + self.loadqueue = old.loadqueue or loadqueue + self.loadorder = old.loadorder or loadorder + self.events = old.events or events + self.databases = old.databases or databases + self.commands = old.commands or commands + + registry = self.registry + lookup = self.lookup + loadqueue = self.loadqueue + loadorder = self.loadorder + events = self.events + databases = self.databases + commands = self.commands + + frame = old.frame + self.registry[major].obj = self + else + self.registry = registry + self.lookup = lookup + self.loadqueue = loadqueue + self.loadorder = loadorder + self.events = events + self.databases = databases + self.commands = commands + + local reg = {obj = self, name = "Dongle"} + registry[major] = reg + lookup[self] = reg + lookup[major] = reg + end + + if not frame then + frame = CreateFrame("Frame") + end + + self.frame = frame + frame:SetScript("OnEvent", function(...) self:OnEvent(...) end) + + -- Register for events using Dongle itself + self:RegisterEvent("ADDON_LOADED") + self:RegisterEvent("PLAYER_LOGIN") + self:RegisterEvent("PLAYER_LOGOUT", "AdminEvents") + self:RegisterEvent("PLAYER_REGEN_ENABLED", "AdminEvents") + self:RegisterEvent("PLAYER_REGEN_DISABLED", "AdminEvents") + + -- Convert all the modules handles + for name,obj in pairs(registry) do + for k,v in ipairs(methods) do + obj[k] = self[v] + end + end + + -- Convert all database methods + for db in pairs(databases) do + for idx,method in ipairs(dbMethods) do + db[method] = self[method] + end + end +end + +function Dongle:Deactivate(new) + lookup[self] = nil + self:UnregisterAllEvents() +end + +DongleStub:Register(Dongle) diff --git a/DongleUtils.lua b/DongleUtils.lua new file mode 100644 index 0000000..a1c5ae0 --- /dev/null +++ b/DongleUtils.lua @@ -0,0 +1,419 @@ +--[[------------------------------------------------------------------------- + Copyright (c) 2006, Dongle Development Team + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the Dongle Development Team nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------]] + +local majorUtil, majorGrat, majorMetro = "DongleUtils", "GratuityMini", "MetrognomeNano" +local minor = tonumber(string.match("$Revision: 178 $", "(%d+)") or 1) +if not DongleStub:IsNewerVersion(majorUtil, minor) then return end + + +-------------------------------- +-- DongleUtils -- +-- Misc handy utils -- +-------------------------------- + +local DongleUtils = {} + + +function DongleUtils:GetVersion() + return majorUtil, minor +end + + +function DongleUtils:Activate(old) + +end + + +function DongleUtils:Deactivate(new) + DongleUtils = nil +end + + +--------------------------- +-- Common locale strings -- +--------------------------- + +local locale = GetLocale() +-- Localized class names. Index == enUS, value == localized +DongleUtils.classnames = locale == "deDE" and { + ["Warlock"] = "Hexenmeister", + ["Warrior"] = "Krieger", + ["Hunter"] = "Jäger", + ["Mage"] = "Magier", + ["Priest"] = "Priester", + ["Druid"] = "Druide", + ["Paladin"] = "Paladin", + ["Shaman"] = "Schamane", + ["Rogue"] = "Schurke", +} or locale == "frFR" and { + ["Warlock"] = "D\195\169moniste", + ["Warrior"] = "Guerrier", + ["Hunter"] = "Chasseur", + ["Mage"] = "Mage", + ["Priest"] = "Pr\195\170tre", + ["Druid"] = "Druide", + ["Paladin"] = "Paladin", + ["Shaman"] = "Chaman", + ["Rogue"] = "Voleur", +} or { + ["Warlock"] = "Warlock", + ["Warrior"] = "Warrior", + ["Hunter"] = "Hunter", + ["Mage"] = "Mage", + ["Priest"] = "Priest", + ["Druid"] = "Druid", + ["Paladin"] = "Paladin", + ["Shaman"] = "Shaman", + ["Rogue"] = "Rogue", +} + +-- Reversed version of .classnames, for locale -> enUS translation +DongleUtils.classnamesreverse = {} +for i,v in pairs(DongleUtils.classnames) do DongleUtils.classnamesreverse[v] = i end + + +-- Handy method to attach to secure frames, to aid in setting attributes quickly +-- Example: someframe:SetManyAttributes("type1", "spell", "spell", "Innervate", "unit1", "player") +function DongleUtils.SetManyAttributes(self, ...) + for i=1,select("#", ...),2 do + local att,val = select(i, ...) + if not att then return end + self:SetAttribute(att,val) + end +end + + +function DongleUtils.RGBToHex(r, g, b) + return string.format("%02x%02x%02x", r, g, b) +end + + +function DongleUtils.RGBPercToHex(r, g, b) + return string.format("%02x%02x%02x", r*255, g*255, b*255) +end + + +function DongleUtils.HexToRGB(hex) + local rhex, ghex, bhex = string.sub(hex, 1, 2), string.sub(hex, 3, 4), string.sub(hex, 5, 6) + return tonumber(rhex, 16), tonumber(ghex, 16), tonumber(bhex, 16) +end + + +function DongleUtils.HexToRGBPerc(hex) + local rhex, ghex, bhex = string.sub(hex, 1, 2), string.sub(hex, 3, 4), string.sub(hex, 5, 6) + return tonumber(rhex, 16)/255, tonumber(ghex, 16)/255, tonumber(bhex, 16)/255 +end + + +function DongleUtils.ColorGradient(perc, ...) + local num = select("#", ...) + local hexes = type(select(1, ...)) == "string" + + if perc == 1 then + if hexes then return select(num, ...) + else return select(num-2, ...), select(num-1, ...), select(num, ...) end + end + + if not hexes then num = num / 3 end + + local segment, relperc = math.modf(perc*(num-1)) + local r1, g1, b1, r2, g2, b2 + if hexes then + r1, g1, b1 = DongleUtils.HexToRGBPerc(select(segment+1, ...)) + r2, g2, b2 = DongleUtils.HexToRGBPerc(select(segment+2, ...)) + else + r1, g1, b1 = select((segment*3)+1, ...), select((segment*3)+2, ...), select((segment*3)+3, ...) + r2, g2, b2 = select((segment*3)+4, ...), select((segment*3)+5, ...), select((segment*3)+6, ...) + end + + if hexes then + return DongleUtils.RGBToHex(r1 + (r2-r1)*relperc, + g1 + (g2-g1)*relperc, + b1 + (b2-b1)*relperc) + else + return r1 + (r2-r1)*relperc, + g1 + (g2-g1)*relperc, + b1 + (b2-b1)*relperc + end +end + + +function DongleUtils.GetHPSeverity(perc, class) + if not class then return DongleUtils.ColorGradient(perc, 1,0,0, 1,1,0, 0,1,0) + else + local c = RAID_CLASS_COLORS[class] + return DongleUtils.ColorGradient(perc, 1,0,0, 1,1,0, c.r,c.g,c.b) + end +end + + +DongleStub:Register(DongleUtils) + + +--------------------------------------- +-- GratuityMini -- +-- Tooltip parsing library -- +--------------------------------------- + +local GratuityMini = {} +local CreateTooltip + +function GratuityMini:GetVersion() + return majorGrat, minor +end + + +function GratuityMini:Activate(old) + self.tooltip = old and old.tooltip or CreateTooltip() + CreateTooltip = nil +end + + +function GratuityMini:Deactivate(new) + GratuityMini = nil +end + + +function GratuityMini:GetTooltip() + return self.tooltip +end + + +CreateTooltip = function() + local tip = CreateFrame("GameTooltip") + tip:SetOwner(WorldFrame, "ANCHOR_NONE") + tip.Llines, tip.Rlines = {}, {} + for i=1,30 do + tip.Llines[i], tip.Rlines[i] = tip:CreateFontString(), tip:CreateFontString() + tip.Llines[i]:SetFontObject(GameFontNormal); tip.Rlines[i]:SetFontObject(GameFontNormal) + tip:AddFontStrings(tip.Llines[i], tip.Rlines[i]) + end + + tip.Erase = function(self) + self:ClearLines() -- Ensures tooltip's NumLines is reset + for i=1,30 do + self.Rlines[i]:SetText() -- Clear text from right side (ClearLines only hides them) + self.L[i], self.R[i] = nil, nil -- Flush the metatable cache + end + if not self:IsOwned(WorldFrame) then self:SetOwner(WorldFrame, "ANCHOR_NONE") end + end + + local methods = {"SetMerchantCostItem", "SetBagItem", "SetAction", "SetAuctionItem", "SetAuctionSellItem", "SetBuybackItem", + "SetCraftItem", "SetCraftSpell", "SetHyperlink", "SetInboxItem", "SetInventoryItem", "SetLootItem", "SetLootRollItem", + "SetMerchantItem", "SetPetAction", "SetPlayerBuff", "SetQuestItem", "SetQuestLogItem", "SetQuestRewardSpell", + "SetSendMailItem", "SetShapeshift", "SetSpell", "SetTalent", "SetTrackingSpell", "SetTradePlayerItem", "SetTradeSkillItem", + "SetTradeTargetItem", "SetTrainerService", "SetUnit", "SetUnitBuff", "SetUnitDebuff"} + for _,m in pairs(methods) do + local orig = tip[m] + tip[m] = function(self, ...) + self:Erase() + return orig(self, ...) + end + end + + tip.L, tip.R = {}, {} + setmetatable(tip.L, { + __index = function(t, key) + if tip:NumLines() >= key and tip.Llines[key] then + local v = tip.Llines[key]:GetText() + t[key] = v + return v + end + return nil + end, + }) + setmetatable(tip.R, { + __index = function(t, key) + if tip:NumLines() >= key and tip.Rlines[key] then + local v = tip.Rlines[key]:GetText() + t[key] = v + return v + end + return nil + end, + }) + + return tip +end + + +DongleStub:Register(GratuityMini) + + +-------------------------------------------------- +-- MetrognomeNano -- +-- OnUpdate and delayed event manager -- +-------------------------------------------------- + +local Metrognome = {} +local frame, handlers, eventargs + + +function Metrognome:GetVersion() + return majorMetro, minor +end + + +function Metrognome:Activate(old) + self.eventargs = old and old.eventargs or {} + self.handlers = old and old.handlers or {} + self.frame = old and old.frame or CreateFrame("Frame") + handlers, frame, eventargs = self.handlers, self.frame, self.eventargs + if not old then frame:Hide() end + frame.name = "MetrognomeNano Frame" + frame:SetScript("OnUpdate", self.OnUpdate) + + if old then + self.olds = old.olds or {} + if not getmetatable(self.olds) then setmetatable(self.olds, {__mode = "k"}) end + self.olds[old] = true + + for o in pairs(self.olds) do + for i,v in pairs(self) do + if i ~= "GetVersion" and i ~= "Activate" and i ~= "Deactivate" then o[i] = v end + end + end + end + self.Activate = nil +end + + +function Metrognome:Deactivate(new) + Metrognome, frame, handlers, eventargs = nil, nil, nil, nil + self.Deactivate = nil +end + + +function Metrognome:FireDelayedEvent(event, delay, ...) + local id = event..GetTime() + + self:Register(self, id, "DelayedEventHandler", rate, id, event, ...) + self:Start(id, 1) + + return id +end + + +function Metrognome:DelayedEventHandler(id, event, ...) + self:Unregister(id) + + if Dongle then Dongle:FireEvent(event, ...) end +end + + +function Metrognome:Register(addon, name, func, rate, ...) +--~ self:argCheck(name, 2, "string") +--~ self:argCheck(func, 3, "function") +--~ self:assert(not handlers[name], "A timer with the name "..name.." is already registered") + + handlers[name] = { + handler = type(func) == "string" and addon, + name = name, + func = func, + rate = rate or 0, + ... + } + + return true +end + + +function Metrognome:Unregister(name) +--~ self:argCheck(name, 2, "string") + + if not handlers[name] then return end + handlers[name] = nil + if not next(handlers) then frame:Hide() end + return true +end + + +function Metrognome:Start(name, numexec) +--~ self:argCheck(name, 2, "string") + + if not handlers[name] then return end + handlers[name].limit = numexec + handlers[name].elapsed = 0 + handlers[name].running = true + frame:Show() + return true +end + + +function Metrognome:Stop(name) +--~ self:argCheck(name, 2, "string") + + if not handlers[name] then return end + handlers[name].running = nil + handlers[name].limit = nil + if not next(handlers) then frame:Hide() end + return true +end + + +function Metrognome:ChangeRate(name, newrate) +--~ self:argCheck(name, 2, "string") + + if not handlers[name] then return end + + local t = handlers[name] + t.elapsed = 0 + t.rate = newrate or 0 + return true +end + + +function Metrognome:GetHandlerTable(name) +--~ self:argCheck(name, 2, "string") + + return handlers[name] +end + + +function Metrognome.OnUpdate(frame, elapsed) + for i,v in pairs(handlers) do + if v.running then + v.elapsed = v.elapsed + elapsed + if v.elapsed >= v.rate then + if v.handler then v.handler[v.func](v.handler, v.elapsed, unpack(v)) + else v.func(v.elapsed, unpack(v)) end + v.elapsed = 0 + if v.limit then + v.limit = v.limit - 1 + if v.limit <= 0 then Metrognome:Stop(i) end + end + end + end + end +end + + +DongleStub:Register(Metrognome) diff --git a/Localization.enUS.lua b/Localization.enUS.lua index e0dfb82..c5d75ee 100644 --- a/Localization.enUS.lua +++ b/Localization.enUS.lua @@ -1,6 +1,65 @@ +--Localization.enUS.lua + PerfectRaidLocals = { + ["Adding defaults to new profile \"%s\""] = "Adding defaults to new profile \"%s\"", + ["Aggro"] = "Aggro", + ["Arcane Brilliance"] = "Arcane Brilliance", + ["Arcane Intellect"] = "Arcane Intellect", + ["Blessing of Kings"] = "Blessing of Kings", + ["Blessing of Light"] = "Blessing of Light", + ["Blessing of Might"] = "Blessing of Might", + ["Blessing of Salvation"] = "Blessing of Salvation", + ["Blessing of Sanctuary"] = "Blessing of Sanctuary", + ["Blessing of Wisdom"] = "Blessing of Wisdom", ["Dead"] = "Dead", + ["Divine Spirit"] = "Divine Spirit", + ["Fear Ward"] = "Fear Ward", ["Ghost"] = "Ghost", + ["Gift of the Wild"] = "Gift of the Wild", + ["Greater Blessing of Kings"] = "Greater Blessing of Kings", + ["Greater Blessing of Light"] = "Greater Blessing of Light", + ["Greater Blessing of Might"] = "Greater Blessing of Might", + ["Greater Blessing of Salvation"] = "Greater Blessing of Salvation", + ["Greater Blessing of Sanctuary"] = "Greater Blessing of Sanctuary", + ["Greater Blessing of Wisdom"] = "Greater Blessing of Wisdom", + ["Innervate"] = "Innervate", + ["Mark of the Wild"] = "Mark of the Wild", + ["Mortal Strike"] = "Mortal Strike", ["Offline"] = "Offline", - ["Aggro"] = "|cFFFF1111Aggro|r", + ["Power Infusion"] = "Power Infusion", + ["Power Word: Fortitude"] = "Power Word: Fortitude", + ["Power Word: Shield"] = "Power Word: Shield", + ["Prayer Spirit"] = "Prayer Spirit", + ["Prayer of Fortitude"] = "Prayer of Fortitude", + ["Prayer of Shadow Protection"] = "Prayer of Shadow Protection", + ["Regrowth"] = "Regrowth", + ["Rejuvenation"] = "Rejuvenation", + ["Renew"] = "Renew", + ["STATUS_ARCANEINT"] = "Int", + ["STATUS_BLESSINGKINGS"] = "BoK", + ["STATUS_BLESSINGLIGHT"] = "BoL", + ["STATUS_BLESSINGMIGHT"] = "BoM", + ["STATUS_BLESSINGSALVATION"] = "BoS", + ["STATUS_BLESSINGSANCTUARY"] = "BoSn", + ["STATUS_BLESSINGWISDOM"] = "BoW", + ["STATUS_DIVINESPIRIT"] = "Spi", + ["STATUS_FEARWARD"] = "FW", + ["STATUS_FORT"] = "F", + ["STATUS_INNERVATE"] = "Inn", + ["STATUS_MORTALSTRIKE"] = "Ms", + ["STATUS_MOTW"] = "M", + ["STATUS_POWERINFUSION"] = "PwI", + ["STATUS_PWS"] = "PwS", + ["STATUS_REGROWTH"] = "Rg", + ["STATUS_REJUV"] = "Rj", + ["STATUS_RENEW"] = "Rn", + ["STATUS_SHADOWPROT"] = "Sh", + ["STATUS_SOULSTONE"] = "Ss", + ["STATUS_THORNS"] = "Th", + ["STATUS_WEAKENEDSOUL"] = "Ws", + ["Shadow Protection"] = "Shadow Protection", + ["Soulstone"] = "Soulstone", + ["Thorns"] = "Thorns", + ["Weakened Soul"] = "Weakened Soul", } + diff --git a/PerfectRaidOptions.lua b/PerfectRaidOptions.lua deleted file mode 100644 index d9db593..0000000 --- a/PerfectRaidOptions.lua +++ /dev/null @@ -1,66 +0,0 @@ ---[[------------------------------------------------------------------------- - Copyright (c) 2006, Jim Whitehead II - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of PerfectRaid nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------]] - -local Options = PerfectRaid:NewModule("PerfectRaid-Options") - -function Options:Initialize() -end - -function Options:Enable() -end - -function Options:CreateOptions() -foo = CreateFrame("Frame", "PRTestOptions", UIParent, "PROptionsTemplate") -foo:SetHeight(300) foo:SetWidth(450) -foo:SetPoint("CENTER", 0, 0) -foo:Show() - -local tab1 = CreateFrame("Button", "PRTab1", foo, "PRTabTemplate") -tab1:SetPoint("TOPLEFT", foo, "BOTTOMLEFT", 10, 12) -tab1:Show() - -local tab2 = CreateFrame("Button", "PRTab2", foo, "PRTabTemplate") -tab2:SetPoint("TOPLEFT", tab1, "TOPRIGHT", 3, 0) -tab2:Show() - -local tab3 = CreateFrame("Button", "PRTab3", foo, "PRTabTemplate") -tab3:SetPoint("TOPLEFT", tab2, "TOPRIGHT", 3, 0) -tab3:SetWidth(150) -tab3:Show() - -local check1 = CreateFrame("CheckButton", "PRCheck1", foo, "PRCheckTemplate") -check1:SetHeight(16) check1:SetWidth(16) -check1:SetPoint("TOPLEFT", 20, -30) -check1:Show() - -local button1 = CreateFrame("Button", "PRButton1", foo, "PRButtonTemplate") -button1:SetPoint("BOTTOMRIGHT", foo, -15, 17) -button1:Show() diff --git a/PerfectRaid_Aggro.lua b/PerfectRaid_Aggro.lua index c6aa998..8b285ae 100644 --- a/PerfectRaid_Aggro.lua +++ b/PerfectRaid_Aggro.lua @@ -35,13 +35,15 @@ local frames,aggro local victims = {} local targets = {} local marked = {} +local rate function Aggro:Initialize() PerfectRaid.defaults.profile.AggroCheck = true - PerfectRaid.defaults.profile.AggroRate = 0.2 + PerfectRaid.defaults.profile.AggroRate = 1.0 frames = PerfectRaid.frames aggro = PerfectRaid.aggro + self:RegisterEvent("DONGLE_PROFILE_CHANGED") end function Aggro:Enable() @@ -50,6 +52,7 @@ function Aggro:Enable() self.frame = CreateFrame("Frame") end self.frame:SetScript("OnUpdate", self.OnUpdate) + rate = PerfectRaid.db.profile.AggroRate end function Aggro:Disable() @@ -59,11 +62,22 @@ function Aggro:Disable() for k,v in pairs(aggro) do aggro[k] = 0 end end +function Aggro:DONGLE_PROFILE_CHANGED(event, addon, svname, name) + if svname == "PerfectRaidDB" then + rate = PerfectRaid.db.profile.AggroRate + if PerfectRaid.db.profile.AggroCheck then + self:Enable() + else + self:Disable() + end + end +end + local elapsed = 0 function Aggro.OnUpdate() local self = Aggro elapsed = elapsed + arg1 - if elapsed >= 0.2 then + if elapsed >= rate then for unit,tbl in pairs(frames) do -- Aggro check for unit,tbl in pairs(frames) do diff --git a/PerfectRaid_Options.lua b/PerfectRaid_Options.lua new file mode 100644 index 0000000..68402e2 --- /dev/null +++ b/PerfectRaid_Options.lua @@ -0,0 +1,103 @@ +--[[------------------------------------------------------------------------- + Copyright (c) 2006, Jim Whitehead II + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of PerfectRaid nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------------]] + +local Options = PerfectRaid:NewModule("PerfectRaid-Options") + +function Options:Initialize() +end + +function Options:Enable() + self.cmd = self:InitializeSlashCommand("PerfectRaid Options", "PERFECTRAID", "praid", "perfectraid") + self.cmd:RegisterSlashHandler("Show options GUI", ".*", "ShowOptions") +end + +function Options:ShowOptions() + if not PROptions then + self:CreateOptions() + PROptions:Show() + elseif PROptions:IsVisible() then + PROptions:Hide() + else + PROptions:Show() + end +end + +function Options:CreateOptions() + local frame = CreateFrame("Frame", "PROptions", UIParent, "PROptionsTemplate") + frame:SetHeight(300) + frame:SetWidth(450) + frame:SetPoint("CENTER", 0, 0) + + for name,module in PerfectRaid:IterateModules() do + if module ~= self and type(module.CreateOptions) == "function" then + module:CreateOptions(self) + end + end +end + +local tabs = {} +function Options:AddOptionsTab(title, frame) + local num = #tabs + 1 + local name = "PROptionsTab"..num + local tab = CreateFrame("Button", name, PROptions, "PRTabTemplate") + + if num == 1 then + tab:SetPoint("TOPLEFT", PROptions, "BOTTOMLEFT", 10, 12) + else + local prev = getglobal("PROptionsTab"..num-1) + tab:SetPoint("TOPLEFT", prev, "TOPRIGHT", 3, 0) + end + + tab.Name:SetText(title) + tab.frame = frame + local width = tab.Name:GetWidth() + tab:SetWidth(width + 30) + tab:Show() + + table.insert(tabs, tab) +end + +local tabselected +function Options:TabOnClick(tab) + if tabselected then + tabselected.Left:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\OrangeTheme\\TabLeftInactive") + tabselected.Middle:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\OrangeTheme\\TabMiddleInactive") + tabselected.Right:SetTexture("Interface\\AddOns\\Perfectraid\\images\\OrangeTheme\\TabRightInactive") + tabselected.frame:Hide() + end + tab.Left:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\OrangeTheme\\TabLeft") + tab.Middle:SetTexture("Interface\\AddOns\\PerfectRaid\\images\\OrangeTheme\\TabMiddle") + tab.Right:SetTexture("Interface\\AddOns\\Perfectraid\\images\\OrangeTheme\\TabRight") + tab.frame:SetPoint("TOPLEFT", 15, -25) + tab.frame:SetPoint("BOTTOMRIGHT", -15, 15) + tab.frame:Show() + tabselected = tab +end diff --git a/PerfectRaid_Range.lua b/PerfectRaid_Range.lua index bd92537..20a48b2 100644 --- a/PerfectRaid_Range.lua +++ b/PerfectRaid_Range.lua @@ -30,7 +30,7 @@ ---------------------------------------------------------------------------]] local Range = PerfectRaid:NewModule("PerfectRaid-Range") -local frames, rangespell +local frames, rangespell, rate, alpha function Range:Initialize() PerfectRaid.defaults.profile.RangeCheck = true @@ -56,6 +56,9 @@ function Range:Enable() self.frame = CreateFrame("Frame") end self.frame:SetScript("OnUpdate", self.OnUpdate) + rate = PerfectRaid.db.profile.RangeRate + alpha = PerfectRaid.db.profile.RangeAlpha + self:RegisterEvent("DONGLE_PROFILE_CHANGED") end function Range:Disable() @@ -69,13 +72,25 @@ function Range:Disable() end end +function Range:DONGLE_PROFILE_CHANGED(event, addon, svname, name) + if svname == "PerfectRaidDB" then + rate = PerfectRaid.db.profile.RangeRate + alpha = PerfectRaid.db.profile.RangeAlphaa + if PerfectRaid.db.profile.RangeCheck then + self:Enable() + else + self:Disable() + end + end +end + local elapsed = 0 function Range.OnUpdate() elapsed = elapsed + arg1 - if elapsed >= 0.2 then + if elapsed >= rate then for unit,tbl in pairs(frames) do local range = IsSpellInRange(rangespell, unit) == 1 - local alpha = range and 1.0 or 0.3 + local alpha = range and 1.0 or alpha for frame in pairs(tbl) do frame:SetAlpha(alpha) end -- 1.7.9.5