local Chorus = Chorus
local GetTime = GetTime
local UnitCastingInfo = Chorus.test.UnitCastingInfo or UnitCastingInfo
local UnitChannelInfo = Chorus.test.UnitChannelInfo or UnitChannelInfo
local UnitExists = Chorus.test.UnitExists or UnitExists
local UnitIsUnit = Chorus.test.UnitIsUnit or UnitIsUnit
local SecureButton_GetUnit = Chorus.test.SecureButton_GetUnit or SecureButton_GetUnit
local function getDurationRemainingSec(nowMili, startInstanceMili, endInstanceMili)
assert(nowMili ~= nil)
assert('number' == type(nowMili))
assert(startInstanceMili ~= nil)
assert('number' == type(startInstanceMili))
assert(endInstanceMili ~= nil)
assert('number' == type(endInstanceMili))
local durationRemainingSec = (endInstanceMili - nowMili) / 1000
assert(durationRemainingSec ~= nil)
assert('number' == type(durationRemainingSec))
assert(durationRemainingSec >= 0 or durationRemainingSec <= 0)
return durationRemainingSec
end
local function getCastInfo(unitDesignation)
assert(unitDesignation ~= nil)
local spellName = UnitCastingInfo(unitDesignation)
if spellName then
return UnitCastingInfo(unitDesignation)
else
return UnitChannelInfo(unitDesignation)
end
end
local function castFrameEventIsRelevant(self, eventCategory, ...)
assert(self ~= nil)
assert(eventCategory ~= nil)
local u = SecureButton_GetUnit(self)
local eu = select(1, ...)
if eu and u then
return UnitIsUnit(u, eu)
else
return true
end
end
local function applyArtworkSpellIcon(self, pictureFile)
assert(self ~= nil)
if not pictureFile then
pictureFile = 'Interface\\Icons\\INV_Misc_QuestionMark'
end
assert(pictureFile ~= nil)
assert('string' == type(pictureFile))
pictureFile = strtrim(pictureFile)
assert(string.len(pictureFile) >= 1)
assert(string.len(pictureFile) <= 8192)
--[[ Artwork1: spell icon ]]--
local artwork1 = self.artwork1 or _G[self:GetName() .. 'Artwork1']
assert(artwork1 ~= nil)
artwork1:SetTexture(pictureFile)
end
local function applySpellName(self, spellName)
assert(self ~= nil)
if not spellName then
spellName = 'Unknown'
end
assert(spellName ~= nil)
assert('string' == type(spellName))
spellName = strtrim(spellName)
assert(string.len(spellName) >= 1)
assert(string.len(spellName) <= 8192)
local label1 = self.label1 or _G[self:GetName() .. 'Text1']
assert(label1 ~= nil)
label1:SetText(spellName)
end
local function applyArtworkCastBar(self, unitDesignation, shieldedFlag)
assert(self ~= nil)
assert(unitDesignation ~= nil)
assert('string' == type(unitDesignation))
unitDesignation = string.lower(strtrim(unitDesignation))
assert(string.len(unitDesignation) >= 1)
assert(string.len(unitDesignation) <= 256)
local label1 = self.label1 or _G[self:GetName() .. 'Text1']
assert(label1 ~= nil)
--[[ Artwork2: bar texture ]]--
local artwork2 = self.artwork2 or _G[self:GetName() .. 'Artwork2']
assert(artwork2 ~= nil)
if shieldedFlag then
artwork2:SetVertexColor(248 / 255, 248 / 255, 1)
label1:SetTextColor(1, 215 / 255, 0)
elseif UnitIsFriend('player', unitDesignation) then
artwork2:SetVertexColor(143 / 255, 188 / 255, 143 / 255)
label1:SetTextColor(248 / 255, 248 / 255, 1)
else
artwork2:SetVertexColor(1, 69 / 255, 0)
label1:SetTextColor(248 / 255, 248 / 255, 1)
end
end
local function applyDurationRemainingSec(self, durationRemainingSec)
assert(self ~= nil)
assert(durationRemainingSec ~= nil)
assert('number' == type(durationRemainingSec))
local label2 = self.label2 or _G[self:GetName() .. 'Text2']
assert(label2 ~= nil)
local t = string.format('%.1f', durationRemainingSec)
label2:SetText(t)
end
local function applyBounds(self, startInstance, endInstance)
assert(self ~= nil)
assert(startInstance ~= nil)
assert('number' == type(startInstance))
startInstance = math.abs(startInstance)
assert(startInstance >= 0)
assert(endInstance ~= nil)
assert('number' == type(endInstance))
endInstance = math.abs(endInstance)
assert(endInstance >= 0)
local x = math.min(startInstance, endInstance)
local y = math.max(startInstance, endInstance)
assert(x <= y)
self:SetMinMaxValues(x, y)
end
local function applyCurrentInstanceMili(self, nowMili)
assert(self ~= nil)
assert(nowMili ~= nil)
assert('number' == type(nowMili))
nowMili = math.abs(nowMili)
assert(nowMili >= 0)
self:SetValue(nowMili)
end
local function castFrameEventProcessor(self, eventCategory, ...)
assert(self ~= nil)
if not castFrameEventIsRelevant(self, eventCategory, ...) then
return
end
local u = SecureButton_GetUnit(self)
if not u or not UnitExists(u) then
self:Hide()
return
end
local label2 = self.label2 or _G[self:GetName() .. 'Text2']
assert(label2 ~= nil)
local spellName, _, _, pictureFile, startInstance, endInstance, _, _, shieldedFlag = getCastInfo(u)
local castOngoingFlag = spellName ~= nil
if castOngoingFlag then
applyBounds(self, startInstance, endInstance)
local now = GetTime() * 1000
applyCurrentInstanceMili(self, now)
local dur = getDurationRemainingSec(now, startInstance, endInstance)
applyDurationRemainingSec(self, dur)
applyArtworkSpellIcon(self, pictureFile)
applyArtworkCastBar(self, u, shieldedFlag)
applySpellName(self, spellName)
self:Show()
else
self:Hide()
end
end
local function castFrameUpdateProcessor(self)
assert(self ~= nil)
local u = SecureButton_GetUnit(self)
if not u then
return
end
local now = GetTime() * 1000
applyCurrentInstanceMili(self, now)
local a, b = self:GetMinMaxValues()
local durationRemainingSec = getDurationRemainingSec(now, a, b)
applyDurationRemainingSec(self, durationRemainingSec)
end
local function castFrameMain(self)
assert(self ~= nil)
local n = self:GetName()
assert(n ~= nil)
self.artwork1 = _G[n .. 'Artwork1']
assert(self.artwork1 ~= nil)
self.artwork2 = _G[n .. 'Artwork2']
assert(self.artwork2 ~= nil)
self.label1 = _G[n .. 'Text1']
assert(self.label1 ~= nil)
self.label2 = _G[n .. 'Text2']
assert(self.label2 ~= nil)
self:SetScript('OnEvent', castFrameEventProcessor)
self:SetScript('OnUpdate', castFrameUpdateProcessor)
self:RegisterEvent("PLAYER_ENTERING_WORLD");
self:RegisterEvent("PLAYER_FOCUS_CHANGED");
self:RegisterEvent("PLAYER_TARGET_CHANGED");
self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START");
self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP");
self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE");
self:RegisterEvent("UNIT_SPELLCAST_DELAYED");
self:RegisterEvent("UNIT_SPELLCAST_FAILED");
self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED");
self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTIBLE");
self:RegisterEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE");
self:RegisterEvent("UNIT_SPELLCAST_START");
self:RegisterEvent("UNIT_SPELLCAST_STOP");
end
Chorus.castFrameMain = function(...)
return castFrameMain(...)
end