WoWInterface SVN RaidWatch2

[/] [trunk/] [RaidWatch_Core/] [Prototypes/] [Timers.lua] - Rev 22

Compare with Previous | Blame | View Log

-- TODO: Handle colors
local RW = LibStub("AceAddon-3.0"):GetAddon("Raid Watch")
local L = LibStub("AceLocale-3.0"):GetLocale("RW2-Plugin-Base")

local Boss = RW.BossPrototype
local timerProt = {}
local mt = {__index = timerProt}

local Party = RW.Party
local Utils = RW.Utils
local RoleBits = Utils.Constants.RoleBits


-- If text is a number this warning is considered not a custom one
-- If text is not a number then it is custom and it can be possibly sent as a table,
-- then the first value in the table will be the actual text, and the second oen will be the option text as its show in the GUI
-- 3rd value in the table will be the tooltip text
local spell
function Boss:_Timer(tType, time, text, icon, optionName, default, color, endMessage, displayText)
        if type(text) == "number" then
                spell = text
                return self:_Timer(tType, time, GetSpellInfo(text), icon or text, optionName or text, default, color, endMessage, displayText)  
        end
        if type(icon) == "number" then 
                spell = icon
                return self:_Timer(tType, time, text, select(3, GetSpellInfo(icon)), optionName or icon, default, color, endMessage, displayText) 
        end
        
        optionName = type(optionName) == "number" and Utils.SpellName[optionName] or optionName
        
        -- If no option name is found by now we use the text as default
        if not optionName then optionName = type(text) == "table" and text[1] or text end
        
        self:AddToCategory(nil, optionName)
        
        default = Utils:BuildRoleDefaults(default)
        
        local defaults = self:AddDefaults(optionName, "BAR", tType ~= "CUSTOM" and tType or text[2], default)
        defaults.color = color
        defaults.endMessage = endMessage
        defaults.Anchor = "Default"
                
        local base = self:GetBaseAlertObject(optionName)
        if not base then
                base = {
                        icon = icon,                    
                        id = optionName,
                        spell = spell,
                        displayText = displayText,
                        mod = self,
                        scheduled = {},
                }
                tinsert(self.BaseAlertObjects, base)
        end
        
        local obj = setmetatable({
                mainType = "BAR",
                type = tType,
                time = time,
                running = {},           
                text = type(text) == "table" and text[1] or text,
                optText = type(text) == "table" and text[2] or nil,
                base = base,
        }, mt)
        
        self.AlertObjects.BAR = self.AlertObjects.BAR or {}
        tinsert(self.AlertObjects.BAR, obj)
        
        spell = nil
        
        return obj
end

--------------------------------------
-- API

function Boss:Timer(...)
        return self:_Timer("NORMAL", ...)
end

function Boss:CDTimer(...)
        return self:_Timer("CD", ...)
end

function Boss:DurTimer(...)
        return self:_Timer("DUR", ...)
end

function Boss:DurTargetTimer(...)
        return self:_Timer("DUR_TARGET", ...)
end

function Boss:DurTargetStackTimer(...)
        return self:_Timer("DUR_TARGET_STACK", ...)
end

function Boss:DurStackTimer(...)
        return self:_Timer("DUR_STACK", ...)
end

function Boss:BerserkTimer(time, text, icon, option, default, color, endMessage)
        local dispText = text and text or L.BERSKER_OPTION:format(Utils:TimeToStringShort(time))
        return self:_Timer("BERSERK", time, text or 35595, icon, option, default, color, endMessage, dispText)
end

function Boss:AchievementTimer(time, achievementID, text, icon, default, ...)
        local IDNumber, Name, Points, Completed, Month, Day, Year, Description, Flags, Image, RewardText = GetAchievementInfo(achievementID)
        Name = Name:gsub("%(.*%)", "")
        return self:_Timer("NORMAL", time, text or Name, icon or Image, Name, default)
end

function Boss:CustomTimer(time, text, optText, ...)
        --@debug
        assert(type(text) == "string", self:GetName()..": CustomTimer, variable \"text\" is not of type text")
        assert(type(optText) == "string", self:GetName()..": CustomTimer, variable \"optText\" is not of type text")
        --@end-debug
        return self:_Timer("CUSTOM", time, {text, optText}, ...)
end

function Boss:CastTimer(time, ...)
        if time > 1000 then
                local castTime = select(7, GetSpellInfo(time))
                local spellHaste = select(7, GetSpellInfo(53142)) / 10000
                local spell = time
                time = castTime/spellHaste/1000
                return self:CastTimer(time, spell, ...)
        end
        return self:_Timer("CAST", time, ...)
end

function Boss:StopAllTimers()
        if not self.AlertObjects.BAR then return end
        for i, timer in pairs(self.AlertObjects.BAR) do
                for j, runningID in pairs(timer.running) do
                        RW.Callbacks:Fire("BarStop", runningID)
                        timer.running[j] = nil
                end
        end
end

------------------------------------
-- Interaction

function Boss:BarFinished(event, id, text, icon)
        if not self.AlertObjects.BAR then return end
        for i, timer in pairs(self.AlertObjects.BAR) do
                for j, runningID in pairs(timer.running) do
                        if runningID == id then
                                if self.db.profile[timer.base.id].endMessage then
                                        local c = timer.mod.db.profile[timer.base.id].Colors[timer.customOptName or "BAR"..timer..base.id]
                                        if not c then c = {1, 1, 1, 1} end
                                        RW.Callbacks:Fire("MessageShow", text, c[1], c[2], c[3], c[4], icon)
                                end
                                timer.running[j] = nil
                        end
                end
        end
end

function timerProt:SetIcon(icon)
        self.base.icon = icon
end

local function BuildID(bar, info)
        return bar.type..bar.base.id..bar.text..(info or "")
end

function timerProt:Start(time, info, ...)
        if not self.base.mod.DB[self.base.id].enabled then return end
        if not Utils:EvaluateRoleOption(self.base.mod.DB[self.base.id].BAR[self.optText or self.type].enabled) then return end
        if time and type(time) ~= "number" then return self:Start(nil, time, info, ...) end
        
        local text
        if self.optText then            
                text = Utils:Format(self.text, info, ...)
        else
                text = Utils:Format(L["FORMAT_BAR_"..self.type], self.text, info, ...)  
        end
        
        local c = self.base.mod.DB[self.base.id].BAR[self.optText or self.type].color
        local anchor = self.base.mod.DB[self.base.id].BAR[self.optText or self.type].Anchor
        RW.Callbacks:Fire("BarStart", BuildID(self, info), time or self.time, text, self.base.icon, c, anchor)
        tinsert(self.running, self.type..self.base.id..self.text..(info or ""))
end

function timerProt:Stop(extraID)
        if extraID then
                RW.Callbacks:Fire("BarStop", BuildID(self, extraID))
        else
                for i, id in pairs(self.running) do
                        RW.Callbacks:Fire("BarStop", id)
                end
        end
end
timerProt.Cancel = timerProt.Stop


-----------------------------------
-- Scheduling 

local function startTimer(timer, ...)
        timer:Start(...)
end

function timerProt:Schedule(stime, time, info, ...)
        if time and type(time) ~= "number" then return self:Schedule(stime, nil, time, info, ...) end
        self.base.mod:Schedule("BAR"..BuildID(self, info), stime, startTimer, self, time, info, ...)
        tinsert(self.base.scheduled, "BAR"..BuildID(self, info))
end

function timerProt:ScheduleRepeating(stime, now, time, info, ...)
        if time and type(time) ~= "number" then return self:ScheduleRepeating(stime, now, nil, time, info, ...) end
        self.base.mod:ScheduleRepeating("BAR"..BuildID(self, info), stime, startTimer, now, self, time, info, ...)
        tinsert(self.base.scheduled, "BAR"..BuildID(self, info))
end

function timerProt:Unschedule(extraID)
        if not extraID then
                for i, scheduleID in pairs(self.base.scheduled) do
                        self.base.mod:Unschedule(scheduleID)
                end
                wipe(self.base.scheduled)
        else
                self.base.mod:Unschedule("BAR"..BuildID(self, extraID))
                Utils:TRemove(self.base.scheduled, "BAR"..BuildID(self, extraID))
        end
end

------------------------------------
-- Options

function timerProt:GetOption()
        local Options = RW:GetPlugin("Options")
        local boss = self.base.mod
        local AceGUI = LibStub("AceGUI-3.0")
        local UIF = LibStub("LibGUIFactory-1.0"):GetFactory("RW")
        
        local BarsPlugin = RW:GetPlugin("Bars2")
        local Anchorlist
        if BarsPlugin then
                Anchorlist = BarsPlugin:GetAnchorList()
        end
        
        
        local subGroup = UIF:InlineGroup("")
        subGroup:SetLayout("flow")
        
        -- Workaround for old non-default values
        if type(boss.DB[self.base.id].BAR[self.optText or self.type].enabled) ~= "table" then
                boss.DB[self.base.id].BAR[self.optText or self.type].enabled = boss.defaults[self.base.id].BAR[self.optText or self.type].enabled
        end
        -- End workaroudn
        local enabledDrop = UIF:MultiSelectDropdown(L.ENABLED, boss.DB[self.base.id].BAR[self.optText or self.type].enabled, nil, Utils.Constants.EnableList, 0.5)
        local anchorDrop = UIF:Dropdown("Anchor", boss.DB[self.base.id].BAR[self.optText or self.type], "Anchor", nil, Anchorlist, 0.5)
        
        if self.type == "CUSTOM" then
                subGroup:SetTitle(self.optText)                         
        else
                subGroup:SetTitle(L["BAR_"..self.type])
        end                     
        
        local color = UIF:ColorSelect(L.COLOR, boss.DB[self.base.id].BAR[self.optText or self.type], "color")
        color:SetRelativeWidth(0.5)
                
        
        local reset = UIF:Button(L.RESET, function()
                boss.DB[self.base.id].BAR[self.optText or self.type].color = boss.defaults[self.base.id].BAR[self.optText or self.type].color           
                
                if type(boss.defaults[self.base.id].BAR[self.optText or self.type].enabled) == "table" then
                        for i, v in pairs(boss.defaults[self.base.id].BAR[self.optText or self.type].enabled) do
                                boss.DB[self.base.id].BAR[self.optText or self.type].enabled[i] = v
                                enabledDrop:SetItemValue(i, v)
                        end
                else
                        boss.DB[self.base.id].BAR[self.optText or self.type].enabled = boss.defaults[self.base.id].BAR[self.optText or self.type].enabled
                end
                
                enabledDrop:SetValue(boss.DB[self.base.id].BAR[self.optText or self.type].enabled)
                anchorDrop:SetValue(boss.DB[self.base.id].BAR[self.optText or self.type].Anchor)
                local colorvalue = boss.DB[self.base.id].BAR[self.optText or self.type].color or nil
                if colorvalue then 
                        color:SetColor(unpack(colorvalue))
                else
                        color:SetColor("")
                end
        end)
        reset:SetRelativeWidth(0.33)
        
        subGroup:AddChild(enabledDrop)
        subGroup:AddChild(anchorDrop)
        subGroup:AddChild(color)        
        subGroup:AddChild(reset)
                
        return subGroup
end 

Compare with Previous | Blame