ESOUI SVN GCDMonitorRevised

[/] [GCDMonitor.lua] - Rev 3

Compare with Previous | Blame | View Log

local ADDON_NAME = "GCDMonitor"
local ADDON_AUTHOR = "|c33ff33Armondeniz, CaffeinatedMayhem|r"
local ADDON_VERSION = "1.9"
local ADDON_TITLE = "Global Cooldown Monitor"
local ADDON_TITLE_DISPLAY = "Global Cooldown Monitor"
local ADDON_SAVEDVARS = "GCDMonitor_Settings"
local ADDON_SAVEDVARS_VER = 3

GCDM = {}
local GCDM = GCDM
GCDM.savedVariables = {}

local EM = GetEventManager()
local LAM = LibAddonMenu2

--default settings
local defaultSettings = {
        ["FrameLeft"] = GuiRoot:GetWidth()/2 + 30,
        ["FrameTop"] = GuiRoot:GetHeight()/2 + 30,
        ["FrameSize"] = 50,
        ["LATime"] = 100,
        ["AlertColor"] = {0, 1, 0, 1},
        ["CDColor"] = {1, 1, 1, 1},
        ["AlertLong"] = false,
        ["AutoHide"] = false,
        ["cTimeAdd"] = 100,
        ["cLATime"] = 100,
        ["hideBG"] = false,
        ["globalSetting"] = true,
}

local showingChanneled = false
local abilitySlotUsed = 3
local alerted = false
local channelStart = 0
local channelFinish = 0
local inCombat = false

-- get the ui element
local gcd = GCDMonitorFrame
local cooldown = gcd:GetNamedChild("Cooldown")
local backdrop = gcd:GetNamedChild("Backdrop")
local backcolor = gcd:GetNamedChild("Colorfill")
GCDM.fragment = ZO_HUDFadeSceneFragment:New(gcd, nil, 0)

-- core utility
local function RefreshCooldown()

        local remain = 0
        local alert = false

        if showingChanneled then
                remain = math.max(channelFinish - GetGameTimeMilliseconds(),0)
                alert = remain >= 0 and remain < GCDM.savedVariables.cLATime
        else
                local duration, global, globalSlotType = 0,0,0,0
                for i = ACTION_BAR_FIRST_NORMAL_SLOT_INDEX + 1, ACTION_BAR_FIRST_NORMAL_SLOT_INDEX + ACTION_BAR_SLOTS_PER_PAGE - 1 do
                        remain, duration, global, globalSlotType = GetSlotCooldownInfo(i)
                        if global == true then 
                                alert = remain >= 0 and remain <GCDM.savedVariables.LATime
                                break
                        end
                end
        end

        if alert ~= false and alerted == false then
                cooldown:SetFillColor(unpack(GCDM.savedVariables.AlertColor))
                alerted = true
        end

        if remain <= 0 then
                cooldown:SetHidden(true)
                cooldown:ResetCooldown()
                gcd:SetHandler("OnUpdate", nil)
                showingChanneled = false

                if GCDM.savedVariables.AlertLong then
                        backcolor:SetCenterColor(unpack(GCDM.savedVariables.AlertColor))
                        backcolor:SetEdgeColor(unpack(GCDM.savedVariables.AlertColor))
                        backcolor:SetHidden(false)
                else
                        backcolor:SetHidden(true)
                end
        end
end

local function HandleCooldown(remain, duration, showCooldown)

        cooldown:SetHidden(not showCooldown)
        alerted = false

        if showCooldown then
                backcolor:SetHidden(true)
                cooldown:SetFillColor(unpack(GCDM.savedVariables.CDColor))
                cooldown:StartCooldown(remain, duration, CD_TYPE_RADIAL, CD_TIME_TYPE_TIME_REMAINING, NO_LEADING_EDGE)
                cooldown:SetHidden(false)
                gcd:SetHandler("OnUpdate", function() RefreshCooldown() end)
        end
end

local function OnAbilityUsed(event, slotnum)

        if slotnum < 3 or slotnum > 8 then return end
        abilitySlotUsed = slotnum

        local abilityId = GetSlotBoundId(slotnum)
        local isChanneled, durationValue = GetAbilityCastInfo(abilityId)
        if isChanneled or durationValue > 0 then
                local duration = durationValue + GCDM.savedVariables.cTimeAdd
                duration = math.max(duration, 1000)
                local remain = duration

                showingChanneled = true
                channelStart = GetGameTimeMilliseconds()
                channelFinish = channelStart + duration
                HandleCooldown(remain, duration, true)
        end
end

local function OnCooldownUpdate(event)

        if showingChanneled then return end
        remain, duration, global, globalSlotType = GetSlotCooldownInfo(abilitySlotUsed)
        local isInCooldown = duration > 0
        local showCooldown = isInCooldown and global and globalSlotType == ACTION_TYPE_ABILITY
        --d("Not Channeled")
        HandleCooldown(remain, duration, showCooldown)
end

local function OnPlayerCombatState(event, combatState)

        if combatState ~= inCombat then
                inCombat = combatState
                if combatState then
                        gcd:SetHidden(false)
                        EM:RegisterForEvent(GCDM.name, EVENT_ACTION_SLOT_ABILITY_USED, OnAbilityUsed)
                        EM:RegisterForEvent(GCDM.name, EVENT_ACTION_UPDATE_COOLDOWNS, OnCooldownUpdate)
                else
                        gcd:SetHidden(true)
                        EM:UnregisterForEvent(GCDM.name, EVENT_ACTION_SLOT_ABILITY_USED)
                        EM:UnregisterForEvent(GCDM.name, EVENT_ACTION_UPDATE_COOLDOWNS)
                end
        end
end

local function ToggleUtility()

        if GCDM.savedVariables.AutoHide == false then
                HUD_SCENE:AddFragment(GCDM.fragment)
                HUD_UI_SCENE:AddFragment(GCDM.fragment)

                EM:UnregisterForEvent(GCDM.name, EVENT_PLAYER_COMBAT_STATE)
                EM:RegisterForEvent(GCDM.name, EVENT_ACTION_SLOT_ABILITY_USED, OnAbilityUsed)
                EM:RegisterForEvent(GCDM.name, EVENT_ACTION_UPDATE_COOLDOWNS, OnCooldownUpdate)
                gcd:SetHidden(false)
                return
        else
                HUD_SCENE:RemoveFragment(GCDM.fragment)
                HUD_UI_SCENE:RemoveFragment(GCDM.fragment)
                -- Init combat state
                inCombat = IsUnitInCombat('player')
                gcd:SetHidden(not inCombat)
                if inCombat then
                        EM:RegisterForEvent(GCDM.name, EVENT_ACTION_SLOT_ABILITY_USED, OnAbilityUsed)
                        EM:RegisterForEvent(GCDM.name, EVENT_ACTION_UPDATE_COOLDOWNS, OnCooldownUpdate)
                end
                EM:RegisterForEvent(GCDM.name, EVENT_PLAYER_COMBAT_STATE, OnPlayerCombatState)
        end
end

-- UI setting functions
function GCDM.OnFrameMoveStop()

        GCDM.savedVariables.FrameLeft = gcd:GetLeft()
        GCDM.savedVariables.FrameTop = gcd:GetTop()
end

local function RestorePosition()

        local left = GCDM.savedVariables.FrameLeft
        local top = GCDM.savedVariables.FrameTop

        gcd:ClearAnchors()
        gcd:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, left, top)
end

local function RestoreSize()

        local size = GCDM.savedVariables.FrameSize

        gcd:SetDimensions(size, size)
end

local function RestoreBC()

        backcolor:SetCenterColor(unpack(GCDM.savedVariables.AlertColor))
        backcolor:SetEdgeColor(unpack(GCDM.savedVariables.AlertColor))
end

local function RestoreSettings()

        RestorePosition()
        RestoreSize()
        RestoreBC()

        backcolor:SetHidden(not GCDM.savedVariables.AlertLong)
        backdrop:SetHidden(GCDM.savedVariables.hideBG)
end

-- Menu
local function BuildMenu()

        local panelData = {
                type = "panel",
                name = ADDON_NAME,
                displayName = ADDON_TITLE_DISPLAY,
                author = ADDON_AUTHOR,
                version = ADDON_VERSION,
                registerForRefresh = true,
        }

        local optionsData = {
                [1] = {
                        type = "header",
                        name = "UI Settings",
                        width = "full",
                },
                [2] = {
                        type = "checkbox",
                        name = "Use Accountwide Settings",
                        tooltip = "",
                        requiresReload = true,
                        getFunc = function() return GCDM.savedVariables.globalSetting end,
                        setFunc = function(value) GCDM.savedVariables.globalSetting = value end,
                },
                [3] = {
                        type = "slider",
                        name = "Monitor Size",
                        min = 10,
                        max = 100,
                        step = 1,
                        getFunc = function() local x,y = gcd:GetDimensions();return x end,
                        setFunc = function(value) GCDM.savedVariables.FrameSize = value;RestoreSize() end,
                        default = defaultSettings.FrameSize,
                },
                [4] = {
                        type = "colorpicker",
                        name = "Alert Color",
                        tooltip = "The color to remind you to do next light attack.",
                        getFunc = function() return unpack(GCDM.savedVariables.AlertColor) end,
                        setFunc = function(r,g,b,a) GCDM.savedVariables.AlertColor = {r, g, b, a};RestoreBC() end,
                },
                [5] = {
                        type = "colorpicker",
                        name = "Cooldown Color",
                        tooltip = "The color of the cooldown timer.",
                        getFunc = function() return unpack(GCDM.savedVariables.CDColor) end,
                        setFunc = function(r,g,b,a) GCDM.savedVariables.CDColor = {r, g, b, a} end,
                },
                [6] = {
                        type = "checkbox",
                        name = "Auto hide out of combat",
                        tooltip = "",
                        getFunc = function() return GCDM.savedVariables.AutoHide end,
                        setFunc = function(value) GCDM.savedVariables.AutoHide = value;ToggleUtility() end,
                },
                [7] = {
                        type = "checkbox",
                        name = "Hide background",
                        tooltip = "",
                        getFunc = function() return GCDM.savedVariables.hideBG end,
                        setFunc = function(value) GCDM.savedVariables.hideBG = value;backdrop:SetHidden(value) end,
                },
                [8] = {
                        type = "header",
                        name = "Normal Ability Settings",
                        width = "full",
                },
                [9] = {
                        type = "slider",
                        name = "Light Attack Alert Time",
                        tooltip = "The cooldown timer will change color before its end, to remind you of doing next Light Attack.",
                        min = 0,
                        max = 500,
                        step = 1,
                        getFunc = function() return GCDM.savedVariables.LATime end,
                        setFunc = function(value) GCDM.savedVariables.LATime = value end,
                        default = defaultSettings.LATime,
                },
                [10] = {
                        type = "checkbox",
                        name = "Show alert color after cooldown",
                        tooltip = "Whether to keep showing alert color after the cooldown's end.",
                        getFunc = function() return GCDM.savedVariables.AlertLong end,
                        setFunc = function(value) GCDM.savedVariables.AlertLong = value;backcolor:SetHidden(not value) end,
                },
                [11] = {
                        type = "header",
                        name = "Channeled Ability Settings",
                        width = "full",
                },
                [12] = {
                        type = "slider",
                        name = "Channel Time Delay",
                        tooltip = "The cooldown will be a bit longer than its channel time, to give you time for light attack.",
                        min = 0,
                        max = 500,
                        step = 1,
                        getFunc = function() return GCDM.savedVariables.cTimeAdd end,
                        setFunc = function(value) GCDM.savedVariables.cTimeAdd = value end,
                        default = defaultSettings.cTimeAdd,
                },
                [13] = {
                        type = "slider",
                        name = "Channeled Ability Alert Time",
                        tooltip = "Light attack alert time for channeled abilities, better to set it equal or shorter than Channel Time Delay.",
                        min = 0,
                        max = 500,
                        step = 1,
                        getFunc = function() return GCDM.savedVariables.cLATime end,
                        setFunc = function(value) GCDM.savedVariables.cLATime = value end,
                        default = defaultSettings.cLATime,
                },
                [14] = {

                        type = "button",
                        name = "Reset",
                        tooltip = "Set all settings to default value.",
                        func = function() 
                                for i, v in pairs(defaultSettings) do
                                        GCDM.savedVariables[i] = v
                                end
                                RestoreSettings() 
                        end,
                        width = "full",
                        warning = "All your settings will be LOST!",
                },
        }

        LAM:RegisterAddonPanel("GCDMPanel", panelData)
        LAM:RegisterOptionControls("GCDMPanel", optionsData)
end

-- Init
local function Initialize()

        GCDM.savedVariables = ZO_SavedVars:NewAccountWide(ADDON_SAVEDVARS, ADDON_SAVEDVARS_VER, "Settings", defaultSettings)

        if GCDM.savedVariables.globalSetting == false then
                GCDM.savedVariables = ZO_SavedVars:NewCharacterIdSettings(ADDON_SAVEDVARS,ADDON_SAVEDVARS_VER, "Settings", defaultSettings)
        end

        ToggleUtility()
        RestoreSettings()
        BuildMenu()
end

function OnAddonLoaded(event, addonName)

        if addonName ~= ADDON_NAME then return end
        
        Initialize()

        EM:UnregisterForEvent(ADDON_NAME, EVENT_ADD_ON_LOADED)

end
-- register load event
EM:RegisterForEvent(ADDON_NAME, EVENT_ADD_ON_LOADED, OnAddonLoaded)

Compare with Previous | Blame