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)