You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
13 KiB
321 lines
13 KiB
|
2 years ago
|
local _, Cell = ...
|
||
|
|
local L = Cell.L
|
||
|
|
local F = Cell.funcs
|
||
|
|
local I = Cell.iFuncs
|
||
|
|
local LCG = LibStub("LibCustomGlow-1.0")
|
||
|
|
|
||
|
|
local UnitIsVisible = UnitIsVisible
|
||
|
|
local UnitGUID = UnitGUID
|
||
|
|
local UnitIsUnit = UnitIsUnit
|
||
|
|
local UnitIsEnemy = UnitIsEnemy
|
||
|
|
local UnitCastingInfo = UnitCastingInfo
|
||
|
|
local UnitChannelInfo = UnitChannelInfo
|
||
|
|
|
||
|
|
-------------------------------------------------
|
||
|
|
-- show / hide
|
||
|
|
-------------------------------------------------
|
||
|
|
local function HideCasts(b)
|
||
|
|
b.indicators.targetedSpells:Hide()
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ShowCasts(b, inListFound, start, duration, icon, isChanneling, num)
|
||
|
|
b.indicators.targetedSpells.cooldown:SetReverse(not isChanneling)
|
||
|
|
b.indicators.targetedSpells:SetCooldown(start, duration, icon, num)
|
||
|
|
-- glow if not 0
|
||
|
|
if inListFound then
|
||
|
|
b.indicators.targetedSpells:ShowGlow(unpack(Cell.vars.targetedSpellsGlow))
|
||
|
|
else
|
||
|
|
b.indicators.targetedSpells:ShowGlow()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-------------------------------------------------
|
||
|
|
-- targeted spells
|
||
|
|
-------------------------------------------------
|
||
|
|
local casts, castsOnUnit = {}, {}
|
||
|
|
local showAllSpells
|
||
|
|
|
||
|
|
local function GetCastsOnUnit(guid)
|
||
|
|
if castsOnUnit[guid] then
|
||
|
|
wipe(castsOnUnit[guid])
|
||
|
|
else
|
||
|
|
castsOnUnit[guid] = {}
|
||
|
|
end
|
||
|
|
|
||
|
|
for sourceGUID, castInfo in pairs(casts) do
|
||
|
|
if guid == castInfo["targetGUID"] then
|
||
|
|
if castInfo["endTime"] > GetTime() then -- not expired
|
||
|
|
tinsert(castsOnUnit[guid], castInfo)
|
||
|
|
else
|
||
|
|
casts[sourceGUID] = nil
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return castsOnUnit[guid]
|
||
|
|
end
|
||
|
|
|
||
|
|
local function UpdateCastsOnUnit(guid)
|
||
|
|
local allCasts = 0
|
||
|
|
local startTime, endTime, spellId, icon, isChanneling
|
||
|
|
local inListFound
|
||
|
|
|
||
|
|
for _, castInfo in pairs(GetCastsOnUnit(guid)) do
|
||
|
|
allCasts = allCasts + 1
|
||
|
|
|
||
|
|
if not endTime then --! init
|
||
|
|
startTime, endTime, spellId, icon, isChanneling = castInfo["startTime"], castInfo["endTime"], castInfo["spellId"], castInfo["icon"], castInfo["isChanneling"]
|
||
|
|
else
|
||
|
|
spellId = castInfo["spellId"]
|
||
|
|
if Cell.vars.targetedSpellsList[spellId] then --! [IN LIST]
|
||
|
|
if not inListFound or endTime > castInfo["endTime"] then --! NOT FOUND BEFORE or SHORTER DURATION
|
||
|
|
startTime, endTime, icon, isChanneling = castInfo["startTime"], castInfo["endTime"], castInfo["icon"], castInfo["isChanneling"]
|
||
|
|
end
|
||
|
|
elseif not inListFound and endTime > castInfo["endTime"] then --! [NOT IN LIST] NOT FOUND BEFORE and SHORTER DURATION
|
||
|
|
startTime, endTime, icon, isChanneling = castInfo["startTime"], castInfo["endTime"], castInfo["icon"], castInfo["isChanneling"]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if Cell.vars.targetedSpellsList[spellId] then
|
||
|
|
inListFound = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if allCasts == 0 then
|
||
|
|
F:HandleUnitButton("guid", guid, HideCasts)
|
||
|
|
else
|
||
|
|
F:HandleUnitButton("guid", guid, ShowCasts, inListFound, startTime, endTime-startTime, icon, isChanneling, allCasts)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local eventFrame = CreateFrame("Frame")
|
||
|
|
eventFrame:SetScript("OnEvent", function(_, event, sourceUnit)
|
||
|
|
if event == "ENCOUNTER_END" then
|
||
|
|
wipe(casts)
|
||
|
|
wipe(castsOnUnit)
|
||
|
|
F:IterateAllUnitButtons(function(b)
|
||
|
|
b.indicators.targetedSpells:Hide()
|
||
|
|
end, true)
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
if sourceUnit and UnitIsEnemy(sourceUnit, "player") then
|
||
|
|
local sourceGUID = UnitGUID(sourceUnit)
|
||
|
|
local previousTarget
|
||
|
|
|
||
|
|
-- check if expired
|
||
|
|
if casts[sourceGUID] and casts[sourceGUID]["endTime"] <= GetTime() then
|
||
|
|
previousTarget = casts[sourceGUID]["targetGUID"]
|
||
|
|
casts[sourceGUID] = nil
|
||
|
|
UpdateCastsOnUnit(previousTarget)
|
||
|
|
end
|
||
|
|
|
||
|
|
if event == "UNIT_SPELLCAST_START" or event == "UNIT_SPELLCAST_DELAYED" or event == "UNIT_SPELLCAST_CHANNEL_START" or event == "UNIT_SPELLCAST_CHANNEL_UPDATE"
|
||
|
|
or event == "UNIT_TARGET" or event == "NAME_PLATE_UNIT_ADDED" then
|
||
|
|
local isChanneling
|
||
|
|
-- name, text, texture, startTimeMS, endTimeMS, isTradeSkill, castID, notInterruptible, spellId
|
||
|
|
local name, _, texture, startTimeMS, endTimeMS, _, _, notInterruptible, spellId = UnitCastingInfo(sourceUnit)
|
||
|
|
if not name then
|
||
|
|
-- name, text, texture, startTimeMS, endTimeMS, isTradeSkill, notInterruptible, spellId
|
||
|
|
name, _, texture, startTimeMS, endTimeMS, _, notInterruptible, spellId = UnitChannelInfo(sourceUnit)
|
||
|
|
isChanneling = true
|
||
|
|
end
|
||
|
|
|
||
|
|
-- print(name, spellId)
|
||
|
|
|
||
|
|
if casts[sourceGUID] then previousTarget = casts[sourceGUID]["targetGUID"] end
|
||
|
|
|
||
|
|
if spellId and (Cell.vars.targetedSpellsList[spellId] or showAllSpells) then
|
||
|
|
local targetUnit = sourceUnit.."target"
|
||
|
|
targetUnit = F:GetTargetUnitID(targetUnit) -- units in group (players/pets), no npcs
|
||
|
|
if targetUnit and UnitIsVisible(targetUnit) then
|
||
|
|
local targetGUID = UnitGUID(targetUnit)
|
||
|
|
casts[sourceGUID] = {
|
||
|
|
["startTime"] = startTimeMS/1000,
|
||
|
|
["endTime"] = endTimeMS/1000,
|
||
|
|
["spellId"] = spellId,
|
||
|
|
["icon"] = texture,
|
||
|
|
["targetGUID"] = targetGUID,
|
||
|
|
["isChanneling"] = isChanneling,
|
||
|
|
-- ["sourceUnit"] = sourceUnit,
|
||
|
|
-- ["targetUnit"] = targetUnit,
|
||
|
|
}
|
||
|
|
UpdateCastsOnUnit(targetGUID)
|
||
|
|
|
||
|
|
-- NOTE: double check
|
||
|
|
C_Timer.After(0.1, function()
|
||
|
|
local newSourceGUID = UnitGUID(sourceUnit) -- NOTE: if sourceUnit == "target", it can change
|
||
|
|
if newSourceGUID == sourceGUID and not UnitIsUnit(sourceUnit.."target", targetUnit) then
|
||
|
|
-- print("old:", sourceUnit, targetUnit)
|
||
|
|
if casts[sourceGUID] then
|
||
|
|
-- update new
|
||
|
|
local newTarget = F:GetTargetUnitID(sourceUnit.."target")
|
||
|
|
if newTarget and UnitIsVisible(newTarget) then
|
||
|
|
-- print("new:", sourceUnit, newTarget)
|
||
|
|
newTarget = UnitGUID(newTarget)
|
||
|
|
casts[sourceGUID]["targetGUID"] = newTarget
|
||
|
|
UpdateCastsOnUnit(newTarget)
|
||
|
|
else
|
||
|
|
casts[sourceGUID] = nil
|
||
|
|
end
|
||
|
|
-- update old
|
||
|
|
UpdateCastsOnUnit(targetGUID)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if previousTarget then UpdateCastsOnUnit(previousTarget) end
|
||
|
|
|
||
|
|
elseif event == "UNIT_SPELLCAST_STOP" or event == "UNIT_SPELLCAST_INTERRUPTED" or event == "UNIT_SPELLCAST_FAILED" or event == "UNIT_SPELLCAST_FAILED_QUIET" or event == "UNIT_SPELLCAST_CHANNEL_STOP"
|
||
|
|
or event == "NAME_PLATE_UNIT_REMOVED" then
|
||
|
|
if casts[sourceGUID] then
|
||
|
|
previousTarget = casts[sourceGUID]["targetGUID"]
|
||
|
|
casts[sourceGUID] = nil
|
||
|
|
UpdateCastsOnUnit(previousTarget)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
-------------------------------------------------
|
||
|
|
-- create
|
||
|
|
-------------------------------------------------
|
||
|
|
local function SetCooldown(frame, start, duration, icon, count)
|
||
|
|
frame.duration:Hide()
|
||
|
|
|
||
|
|
if count ~= 1 then
|
||
|
|
frame.stack:Show()
|
||
|
|
frame.stack:SetText(count)
|
||
|
|
else
|
||
|
|
frame.stack:Hide()
|
||
|
|
end
|
||
|
|
|
||
|
|
frame.border:Show()
|
||
|
|
frame.cooldown:Show()
|
||
|
|
frame.cooldown:SetSwipeColor(unpack(Cell.vars.targetedSpellsGlow[2]))
|
||
|
|
frame.cooldown:SetCooldown(start, duration)
|
||
|
|
frame.icon:SetTexture(icon)
|
||
|
|
frame:Show()
|
||
|
|
end
|
||
|
|
|
||
|
|
local function SetFont(frame, font, size, flags, anchor, xOffset, yOffset, color)
|
||
|
|
I:SetFont(frame.stack, frame, font, size, flags, anchor, xOffset, yOffset, color)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ShowGlowPreview(frame)
|
||
|
|
frame:ShowGlow(unpack(Cell.vars.targetedSpellsGlow))
|
||
|
|
end
|
||
|
|
|
||
|
|
local function HideGlowPreview(frame)
|
||
|
|
LCG.ButtonGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.PixelGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.AutoCastGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.ProcGlow_Stop(frame.tsGlowFrame)
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ShowGlow(frame, glowType, color, arg1, arg2, arg3, arg4)
|
||
|
|
if glowType == "Normal" then
|
||
|
|
LCG.PixelGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.AutoCastGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.ProcGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.ButtonGlow_Start(frame.tsGlowFrame, color)
|
||
|
|
elseif glowType == "Pixel" then
|
||
|
|
LCG.ButtonGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.AutoCastGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.ProcGlow_Stop(frame.tsGlowFrame)
|
||
|
|
-- color, N, frequency, length, thickness
|
||
|
|
LCG.PixelGlow_Start(frame.tsGlowFrame, color, arg1, arg2, arg3, arg4)
|
||
|
|
elseif glowType == "Shine" then
|
||
|
|
LCG.ButtonGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.PixelGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.ProcGlow_Stop(frame.tsGlowFrame)
|
||
|
|
-- color, N, frequency, scale
|
||
|
|
LCG.AutoCastGlow_Start(frame.tsGlowFrame, color, arg1, arg2, arg3)
|
||
|
|
elseif glowType == "Proc" then
|
||
|
|
LCG.ButtonGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.PixelGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.AutoCastGlow_Stop(frame.tsGlowFrame)
|
||
|
|
-- color, duration
|
||
|
|
LCG.ProcGlow_Start(frame.tsGlowFrame, {color=color, duration=arg1, startAnim=false})
|
||
|
|
else
|
||
|
|
LCG.ButtonGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.PixelGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.AutoCastGlow_Stop(frame.tsGlowFrame)
|
||
|
|
LCG.ProcGlow_Stop(frame.tsGlowFrame)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function I:CreateTargetedSpells(parent)
|
||
|
|
local frame = I:CreateAura_BorderIcon(parent:GetName().."TargetedSpells", parent.widget.overlayFrame, 2)
|
||
|
|
parent.indicators.targetedSpells = frame
|
||
|
|
frame:Hide()
|
||
|
|
|
||
|
|
frame.tsGlowFrame = parent.widget.tsGlowFrame
|
||
|
|
frame.ShowGlow = ShowGlow
|
||
|
|
frame.SetCooldown = SetCooldown
|
||
|
|
frame.SetFont = SetFont
|
||
|
|
frame.ShowGlowPreview = ShowGlowPreview
|
||
|
|
frame.HideGlowPreview = HideGlowPreview
|
||
|
|
|
||
|
|
frame.cooldown:SetScript("OnCooldownDone", function()
|
||
|
|
frame:Hide()
|
||
|
|
end)
|
||
|
|
|
||
|
|
frame:SetScript("OnHide", function()
|
||
|
|
LCG.ButtonGlow_Stop(parent.widget.tsGlowFrame)
|
||
|
|
LCG.PixelGlow_Stop(parent.widget.tsGlowFrame)
|
||
|
|
LCG.AutoCastGlow_Stop(parent.widget.tsGlowFrame)
|
||
|
|
LCG.ProcGlow_Stop(parent.widget.tsGlowFrame)
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
-------------------------------------------------
|
||
|
|
-- functions
|
||
|
|
-------------------------------------------------
|
||
|
|
-- NOTE: in case there's a casting spell, hide!
|
||
|
|
local function EnterLeaveInstance()
|
||
|
|
F:IterateAllUnitButtons(function(b)
|
||
|
|
b.indicators.targetedSpells:Hide()
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
function I:EnableTargetedSpells(enabled)
|
||
|
|
if enabled then
|
||
|
|
-- UNIT_SPELLCAST_DELAYED UNIT_SPELLCAST_FAILED UNIT_SPELLCAST_FAILED_QUIET UNIT_SPELLCAST_INTERRUPTED UNIT_SPELLCAST_START UNIT_SPELLCAST_STOP
|
||
|
|
-- UNIT_SPELLCAST_CHANNEL_START UNIT_SPELLCAST_CHANNEL_STOP UNIT_SPELLCAST_CHANNEL_UPDATE
|
||
|
|
-- UNIT_TARGET ENCOUNTER_END
|
||
|
|
|
||
|
|
eventFrame:RegisterEvent("UNIT_SPELLCAST_START")
|
||
|
|
eventFrame:RegisterEvent("UNIT_SPELLCAST_STOP")
|
||
|
|
eventFrame:RegisterEvent("UNIT_SPELLCAST_DELAYED")
|
||
|
|
eventFrame:RegisterEvent("UNIT_SPELLCAST_FAILED")
|
||
|
|
eventFrame:RegisterEvent("UNIT_SPELLCAST_FAILED_QUIET")
|
||
|
|
eventFrame:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
|
||
|
|
eventFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START")
|
||
|
|
eventFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP")
|
||
|
|
eventFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE")
|
||
|
|
|
||
|
|
-- eventFrame:RegisterEvent("UNIT_TARGET") --! Fired when the target of yourself, raid, and party members change, Should also work for 'pet' and 'focus'.
|
||
|
|
eventFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED")
|
||
|
|
eventFrame:RegisterEvent("NAME_PLATE_UNIT_REMOVED")
|
||
|
|
|
||
|
|
eventFrame:RegisterEvent("ENCOUNTER_END")
|
||
|
|
|
||
|
|
Cell:RegisterCallback("EnterInstance", "TargetedSpells_EnterInstance", EnterLeaveInstance)
|
||
|
|
Cell:RegisterCallback("LeaveInstance", "TargetedSpells_LeaveInstance", EnterLeaveInstance)
|
||
|
|
else
|
||
|
|
eventFrame:UnregisterAllEvents()
|
||
|
|
|
||
|
|
Cell:UnregisterCallback("EnterInstance", "TargetedSpells_EnterInstance")
|
||
|
|
Cell:UnregisterCallback("LeaveInstance", "TargetedSpells_LeaveInstance")
|
||
|
|
|
||
|
|
F:IterateAllUnitButtons(function(b)
|
||
|
|
b.indicators.targetedSpells:Hide()
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function I:ShowAllTargetedSpells(showAll)
|
||
|
|
showAllSpells = showAll
|
||
|
|
end
|