跟随版本 0.8.19
This commit is contained in:
434
Units/Pet.lua
434
Units/Pet.lua
@@ -350,7 +350,9 @@ function SFrames.Pet:Initialize()
|
||||
self.frame = f
|
||||
self.frame.unit = "pet"
|
||||
f:Hide()
|
||||
|
||||
|
||||
self:CreateAuras()
|
||||
self:CreateHappinessWarning()
|
||||
self:CreateCastbar()
|
||||
|
||||
SFrames:RegisterEvent("UNIT_PET", function() if arg1 == "player" then self:UpdateAll() end end)
|
||||
@@ -395,6 +397,7 @@ function SFrames.Pet:UpdateAll()
|
||||
if SFramesDB and SFramesDB.showPetFrame == false then
|
||||
self.frame:Hide()
|
||||
if self.foodPanel then self.foodPanel:Hide() end
|
||||
self:HideAuras()
|
||||
return
|
||||
end
|
||||
|
||||
@@ -403,6 +406,7 @@ function SFrames.Pet:UpdateAll()
|
||||
self:UpdatePowerType()
|
||||
self:UpdatePower()
|
||||
self:UpdateHappiness()
|
||||
self:UpdateAuras()
|
||||
|
||||
local name = UnitName("pet")
|
||||
if name == UNKNOWNOBJECT or name == "未知目标" or name == "Unknown" then
|
||||
@@ -415,6 +419,7 @@ function SFrames.Pet:UpdateAll()
|
||||
else
|
||||
self.frame:Hide()
|
||||
if self.foodPanel then self.foodPanel:Hide() end
|
||||
self:HideAuras()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -452,6 +457,7 @@ function SFrames.Pet:UpdateHappiness()
|
||||
local happiness = GetPetHappiness()
|
||||
if not happiness then
|
||||
self.frame.happinessBG:Hide()
|
||||
self:HideHappinessWarning()
|
||||
self:UpdateFoodButton()
|
||||
return
|
||||
end
|
||||
@@ -471,8 +477,10 @@ function SFrames.Pet:UpdateHappiness()
|
||||
self.frame.happiness:SetTexCoord(0, 0.1875, 0, 0.359375)
|
||||
self.frame.happinessBG:Show()
|
||||
end
|
||||
self:ShowHappinessWarning(happiness)
|
||||
else
|
||||
self.frame.happinessBG:Hide()
|
||||
self:HideHappinessWarning()
|
||||
end
|
||||
self:UpdateFoodButton()
|
||||
end
|
||||
@@ -1018,6 +1026,430 @@ function SFrames.Pet:UpdateFoodButton()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Pet Buff / Debuff Auras
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local PET_AURA_SIZE = 20
|
||||
local PET_AURA_SPACING = 2
|
||||
local PET_AURA_ROW_SPACING = 1
|
||||
local PET_AURAS_PER_ROW = 6
|
||||
local PET_BUFF_COUNT = 16
|
||||
local PET_DEBUFF_COUNT = 16
|
||||
|
||||
function SFrames.Pet:CreateAuras()
|
||||
local f = self.frame
|
||||
f.buffs = {}
|
||||
f.debuffs = {}
|
||||
|
||||
for i = 1, PET_BUFF_COUNT do
|
||||
local b = CreateFrame("Button", "SFramesPetBuff" .. i, f)
|
||||
b:SetWidth(PET_AURA_SIZE)
|
||||
b:SetHeight(PET_AURA_SIZE)
|
||||
SFrames:CreateUnitBackdrop(b)
|
||||
|
||||
b.icon = b:CreateTexture(nil, "ARTWORK")
|
||||
b.icon:SetAllPoints()
|
||||
b.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
|
||||
|
||||
b.cdText = SFrames:CreateFontString(b, 8, "CENTER")
|
||||
b.cdText:SetPoint("BOTTOM", b, "BOTTOM", 0, 1)
|
||||
b.cdText:SetTextColor(1, 0.82, 0)
|
||||
b.cdText:SetShadowColor(0, 0, 0, 1)
|
||||
b.cdText:SetShadowOffset(1, -1)
|
||||
|
||||
b:SetScript("OnEnter", function()
|
||||
GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT")
|
||||
GameTooltip:SetUnitBuff("pet", this:GetID())
|
||||
end)
|
||||
b:SetScript("OnLeave", function() GameTooltip:Hide() end)
|
||||
|
||||
if i == 1 then
|
||||
b:SetPoint("TOPLEFT", f, "BOTTOMLEFT", 0, -1)
|
||||
elseif math.mod(i - 1, PET_AURAS_PER_ROW) == 0 then
|
||||
b:SetPoint("TOP", f.buffs[i - PET_AURAS_PER_ROW], "BOTTOM", 0, -PET_AURA_ROW_SPACING)
|
||||
else
|
||||
b:SetPoint("LEFT", f.buffs[i - 1], "RIGHT", PET_AURA_SPACING, 0)
|
||||
end
|
||||
b:Hide()
|
||||
f.buffs[i] = b
|
||||
end
|
||||
|
||||
for i = 1, PET_DEBUFF_COUNT do
|
||||
local b = CreateFrame("Button", "SFramesPetDebuff" .. i, f)
|
||||
b:SetWidth(PET_AURA_SIZE)
|
||||
b:SetHeight(PET_AURA_SIZE)
|
||||
SFrames:CreateUnitBackdrop(b)
|
||||
|
||||
b.icon = b:CreateTexture(nil, "ARTWORK")
|
||||
b.icon:SetAllPoints()
|
||||
b.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
|
||||
|
||||
b.cdText = SFrames:CreateFontString(b, 8, "CENTER")
|
||||
b.cdText:SetPoint("BOTTOM", b, "BOTTOM", 0, 1)
|
||||
b.cdText:SetTextColor(1, 0.82, 0)
|
||||
b.cdText:SetShadowColor(0, 0, 0, 1)
|
||||
b.cdText:SetShadowOffset(1, -1)
|
||||
|
||||
b:SetScript("OnEnter", function()
|
||||
GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT")
|
||||
GameTooltip:SetUnitDebuff("pet", this:GetID())
|
||||
end)
|
||||
b:SetScript("OnLeave", function() GameTooltip:Hide() end)
|
||||
|
||||
if i == 1 then
|
||||
b:SetPoint("TOPLEFT", f, "BOTTOMLEFT", 0, -1)
|
||||
elseif math.mod(i - 1, PET_AURAS_PER_ROW) == 0 then
|
||||
b:SetPoint("TOP", f.debuffs[i - PET_AURAS_PER_ROW], "BOTTOM", 0, -PET_AURA_ROW_SPACING)
|
||||
else
|
||||
b:SetPoint("LEFT", f.debuffs[i - 1], "RIGHT", PET_AURA_SPACING, 0)
|
||||
end
|
||||
b:Hide()
|
||||
f.debuffs[i] = b
|
||||
end
|
||||
|
||||
SFrames:RegisterEvent("UNIT_AURA", function()
|
||||
if arg1 == "pet" then SFrames.Pet:UpdateAuras() end
|
||||
end)
|
||||
|
||||
self.petAuraUpdater = CreateFrame("Frame", nil, f)
|
||||
self.petAuraUpdater.timer = 0
|
||||
self.petAuraUpdater:SetScript("OnUpdate", function()
|
||||
this.timer = this.timer + arg1
|
||||
if this.timer >= 0.25 then
|
||||
SFrames.Pet:TickAuras()
|
||||
this.timer = 0
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function SFrames.Pet:UpdateAuras()
|
||||
if not UnitExists("pet") then return end
|
||||
local f = self.frame
|
||||
if not f.buffs then return end
|
||||
|
||||
local numBuffs = 0
|
||||
for i = 1, PET_BUFF_COUNT do
|
||||
local texture = UnitBuff("pet", i)
|
||||
local b = f.buffs[i]
|
||||
b:SetID(i)
|
||||
if texture then
|
||||
b.icon:SetTexture(texture)
|
||||
|
||||
if SFrames.Tooltip then
|
||||
SFrames.Tooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
SFrames.Tooltip:ClearLines()
|
||||
SFrames.Tooltip:SetUnitBuff("pet", i)
|
||||
end
|
||||
local timeLeft = SFrames:GetAuraTimeLeft("pet", i, true)
|
||||
if SFrames.Tooltip then SFrames.Tooltip:Hide() end
|
||||
|
||||
if timeLeft and timeLeft > 0 then
|
||||
b.expirationTime = GetTime() + timeLeft
|
||||
b.cdText:SetText(SFrames:FormatTime(timeLeft))
|
||||
else
|
||||
b.expirationTime = nil
|
||||
b.cdText:SetText("")
|
||||
end
|
||||
|
||||
b:Show()
|
||||
numBuffs = numBuffs + 1
|
||||
else
|
||||
b.expirationTime = nil
|
||||
b.cdText:SetText("")
|
||||
b:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local firstDebuff = f.debuffs[1]
|
||||
if firstDebuff then
|
||||
firstDebuff:ClearAllPoints()
|
||||
if numBuffs > 0 then
|
||||
local lastRowStart = math.floor((numBuffs - 1) / PET_AURAS_PER_ROW) * PET_AURAS_PER_ROW + 1
|
||||
firstDebuff:SetPoint("TOP", f.buffs[lastRowStart], "BOTTOM", 0, -PET_AURA_ROW_SPACING)
|
||||
else
|
||||
firstDebuff:SetPoint("TOPLEFT", f, "BOTTOMLEFT", 0, -1)
|
||||
end
|
||||
end
|
||||
|
||||
local hasNP = NanamiPlates_SpellDB and NanamiPlates_SpellDB.UnitDebuff
|
||||
local npFormat = NanamiPlates_Auras and NanamiPlates_Auras.FormatTime
|
||||
|
||||
for i = 1, PET_DEBUFF_COUNT do
|
||||
local texture, debuffCount, debuffType = UnitDebuff("pet", i)
|
||||
local b = f.debuffs[i]
|
||||
b:SetID(i)
|
||||
if texture then
|
||||
b.icon:SetTexture(texture)
|
||||
|
||||
if debuffType and DebuffTypeColor and DebuffTypeColor[debuffType] then
|
||||
local c = DebuffTypeColor[debuffType]
|
||||
b:SetBackdropBorderColor(c.r, c.g, c.b, 1)
|
||||
else
|
||||
b:SetBackdropBorderColor(0.8, 0, 0, 1)
|
||||
end
|
||||
|
||||
local timeLeft = 0
|
||||
local effectName = nil
|
||||
|
||||
if hasNP then
|
||||
local effect, rank, _, stacks, dtype, duration, npTimeLeft, isOwn = NanamiPlates_SpellDB:UnitDebuff("pet", i)
|
||||
effectName = effect
|
||||
if npTimeLeft and npTimeLeft > 0 then
|
||||
timeLeft = npTimeLeft
|
||||
elseif effect and effect ~= "" and duration and duration > 0
|
||||
and NanamiPlates_Auras and NanamiPlates_Auras.timers then
|
||||
local unitKey = (UnitGUID and UnitGUID("pet")) or UnitName("pet") or ""
|
||||
local cached = NanamiPlates_Auras.timers[unitKey .. "_" .. effect]
|
||||
if not cached and UnitName("pet") then
|
||||
cached = NanamiPlates_Auras.timers[UnitName("pet") .. "_" .. effect]
|
||||
end
|
||||
if cached and cached.startTime and cached.duration then
|
||||
local remaining = cached.duration - (GetTime() - cached.startTime)
|
||||
if remaining > 0 then timeLeft = remaining end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if timeLeft <= 0 then
|
||||
if SFrames.Tooltip then
|
||||
SFrames.Tooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
SFrames.Tooltip:ClearLines()
|
||||
SFrames.Tooltip:SetUnitDebuff("pet", i)
|
||||
end
|
||||
timeLeft = SFrames:GetAuraTimeLeft("pet", i, false)
|
||||
if SFrames.Tooltip then SFrames.Tooltip:Hide() end
|
||||
end
|
||||
|
||||
if timeLeft and timeLeft > 0 then
|
||||
b.expirationTime = GetTime() + timeLeft
|
||||
b.effectName = effectName
|
||||
if npFormat then
|
||||
local text, r, g, bc, a = npFormat(timeLeft)
|
||||
b.cdText:SetText(text)
|
||||
if r then b.cdText:SetTextColor(r, g, bc, a or 1) end
|
||||
else
|
||||
b.cdText:SetText(SFrames:FormatTime(timeLeft))
|
||||
end
|
||||
else
|
||||
b.expirationTime = nil
|
||||
b.effectName = nil
|
||||
b.cdText:SetText("")
|
||||
end
|
||||
|
||||
b:Show()
|
||||
else
|
||||
b.expirationTime = nil
|
||||
b.effectName = nil
|
||||
b.cdText:SetText("")
|
||||
b:SetBackdropBorderColor(0, 0, 0, 1)
|
||||
b:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SFrames.Pet:TickAuras()
|
||||
if not UnitExists("pet") then return end
|
||||
local f = self.frame
|
||||
if not f.buffs then return end
|
||||
|
||||
local timeNow = GetTime()
|
||||
local npFormat = NanamiPlates_Auras and NanamiPlates_Auras.FormatTime
|
||||
local hasNP = NanamiPlates_SpellDB and NanamiPlates_SpellDB.FindEffectData
|
||||
|
||||
local petName, petLevel, petGUID
|
||||
if hasNP then
|
||||
petName = UnitName("pet")
|
||||
petLevel = UnitLevel("pet") or 0
|
||||
petGUID = UnitGUID and UnitGUID("pet")
|
||||
end
|
||||
|
||||
for i = 1, PET_BUFF_COUNT do
|
||||
local b = f.buffs[i]
|
||||
if b:IsShown() and b.expirationTime then
|
||||
local timeLeft = b.expirationTime - timeNow
|
||||
if timeLeft > 0 and timeLeft < 3600 then
|
||||
if npFormat then
|
||||
local text, r, g, bc, a = npFormat(timeLeft)
|
||||
b.cdText:SetText(text)
|
||||
if r then b.cdText:SetTextColor(r, g, bc, a or 1) end
|
||||
else
|
||||
b.cdText:SetText(SFrames:FormatTime(timeLeft))
|
||||
end
|
||||
else
|
||||
b.cdText:SetText("")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, PET_DEBUFF_COUNT do
|
||||
local b = f.debuffs[i]
|
||||
if b:IsShown() then
|
||||
local timeLeft = nil
|
||||
|
||||
if hasNP and b.effectName then
|
||||
local data = petGUID and NanamiPlates_SpellDB:FindEffectData(petGUID, petLevel, b.effectName)
|
||||
if not data and petName then
|
||||
data = NanamiPlates_SpellDB:FindEffectData(petName, petLevel, b.effectName)
|
||||
end
|
||||
if data and data.start and data.duration then
|
||||
local remaining = data.duration + data.start - timeNow
|
||||
if remaining > 0 then
|
||||
timeLeft = remaining
|
||||
b.expirationTime = timeNow + remaining
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not timeLeft and b.expirationTime then
|
||||
timeLeft = b.expirationTime - timeNow
|
||||
end
|
||||
|
||||
if timeLeft and timeLeft > 0 and timeLeft < 3600 then
|
||||
if npFormat then
|
||||
local text, r, g, bc, a = npFormat(timeLeft)
|
||||
b.cdText:SetText(text)
|
||||
if r then b.cdText:SetTextColor(r, g, bc, a or 1) end
|
||||
else
|
||||
b.cdText:SetText(SFrames:FormatTime(timeLeft))
|
||||
end
|
||||
else
|
||||
b.cdText:SetText("")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SFrames.Pet:HideAuras()
|
||||
local f = self.frame
|
||||
if not f or not f.buffs then return end
|
||||
for i = 1, PET_BUFF_COUNT do
|
||||
f.buffs[i].expirationTime = nil
|
||||
f.buffs[i].cdText:SetText("")
|
||||
f.buffs[i]:Hide()
|
||||
end
|
||||
for i = 1, PET_DEBUFF_COUNT do
|
||||
f.debuffs[i].expirationTime = nil
|
||||
f.debuffs[i].effectName = nil
|
||||
f.debuffs[i].cdText:SetText("")
|
||||
f.debuffs[i]:SetBackdropBorderColor(0, 0, 0, 1)
|
||||
f.debuffs[i]:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Pet Happiness Warning
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local WARNING_REMIND_INTERVAL_YELLOW = 60
|
||||
local WARNING_REMIND_INTERVAL_RED = 30
|
||||
|
||||
function SFrames.Pet:CreateHappinessWarning()
|
||||
local f = self.frame
|
||||
local fontPath = SFrames:GetFont()
|
||||
local outline = (SFrames.Media and SFrames.Media.fontOutline) or "OUTLINE"
|
||||
|
||||
local warnFrame = CreateFrame("Frame", "SFramesPetHappinessWarn", f)
|
||||
warnFrame:SetWidth(180)
|
||||
warnFrame:SetHeight(22)
|
||||
warnFrame:SetPoint("BOTTOM", f, "TOP", 0, 2)
|
||||
warnFrame:SetFrameStrata("HIGH")
|
||||
|
||||
local warnBg = warnFrame:CreateTexture(nil, "BACKGROUND")
|
||||
warnBg:SetAllPoints()
|
||||
warnBg:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||||
warnBg:SetVertexColor(0, 0, 0, 0.55)
|
||||
warnFrame.bg = warnBg
|
||||
|
||||
local warnText = warnFrame:CreateFontString(nil, "OVERLAY")
|
||||
warnText:SetFont(fontPath, 11, outline)
|
||||
warnText:SetPoint("CENTER", warnFrame, "CENTER", 0, 0)
|
||||
warnText:SetShadowColor(0, 0, 0, 1)
|
||||
warnText:SetShadowOffset(1, -1)
|
||||
warnFrame.text = warnText
|
||||
|
||||
warnFrame:Hide()
|
||||
self.warnFrame = warnFrame
|
||||
self.lastHappiness = nil
|
||||
self.lastWarnTime = 0
|
||||
self.warnFlashAlpha = 1
|
||||
self.warnFlashDir = -1
|
||||
|
||||
warnFrame:SetScript("OnUpdate", function()
|
||||
SFrames.Pet:WarningFlashUpdate()
|
||||
end)
|
||||
end
|
||||
|
||||
function SFrames.Pet:WarningFlashUpdate()
|
||||
if not self.warnFrame or not self.warnFrame:IsShown() then return end
|
||||
if not self.warnSeverity or self.warnSeverity ~= "red" then return end
|
||||
|
||||
local speed = 2.5
|
||||
local dt = arg1 or 0.016
|
||||
self.warnFlashAlpha = self.warnFlashAlpha + self.warnFlashDir * speed * dt
|
||||
|
||||
if self.warnFlashAlpha <= 0.25 then
|
||||
self.warnFlashAlpha = 0.25
|
||||
self.warnFlashDir = 1
|
||||
elseif self.warnFlashAlpha >= 1 then
|
||||
self.warnFlashAlpha = 1
|
||||
self.warnFlashDir = -1
|
||||
end
|
||||
|
||||
self.warnFrame.text:SetAlpha(self.warnFlashAlpha)
|
||||
self.warnFrame.bg:SetVertexColor(0.4, 0, 0, 0.55 * self.warnFlashAlpha)
|
||||
end
|
||||
|
||||
function SFrames.Pet:ShowHappinessWarning(happiness)
|
||||
if not self.warnFrame then return end
|
||||
|
||||
if happiness == 3 then
|
||||
self:HideHappinessWarning()
|
||||
return
|
||||
end
|
||||
|
||||
local now = GetTime()
|
||||
local isNewState = (self.lastHappiness ~= happiness)
|
||||
|
||||
if happiness == 2 then
|
||||
self.warnFrame.text:SetText("宠物心情一般,攻击力受影响!")
|
||||
self.warnFrame.text:SetTextColor(1, 0.82, 0.2)
|
||||
self.warnFrame.bg:SetVertexColor(0.3, 0.25, 0, 0.55)
|
||||
self.warnFrame.text:SetAlpha(1)
|
||||
self.warnSeverity = "yellow"
|
||||
self.warnFrame:Show()
|
||||
|
||||
if isNewState or (now - self.lastWarnTime >= WARNING_REMIND_INTERVAL_YELLOW) then
|
||||
SFrames:Print("|cffffff00宠物心情一般|r - 攻击力下降,请及时喂食!")
|
||||
self.lastWarnTime = now
|
||||
end
|
||||
elseif happiness == 1 then
|
||||
self.warnFrame.text:SetText("宠物很不开心,快要跑了!")
|
||||
self.warnFrame.text:SetTextColor(1, 0.2, 0.2)
|
||||
self.warnFrame.bg:SetVertexColor(0.4, 0, 0, 0.55)
|
||||
self.warnFlashAlpha = 1
|
||||
self.warnFlashDir = -1
|
||||
self.warnSeverity = "red"
|
||||
self.warnFrame:Show()
|
||||
|
||||
if isNewState or (now - self.lastWarnTime >= WARNING_REMIND_INTERVAL_RED) then
|
||||
SFrames:Print("|cffff3333宠物非常不开心,即将离你而去!|r 请立即喂食!")
|
||||
UIErrorsFrame:AddMessage("宠物快要跑了!请立即喂食!", 1, 0.2, 0.2, 1, 3)
|
||||
self.lastWarnTime = now
|
||||
end
|
||||
end
|
||||
|
||||
self.lastHappiness = happiness
|
||||
end
|
||||
|
||||
function SFrames.Pet:HideHappinessWarning()
|
||||
if self.warnFrame then
|
||||
self.warnFrame:Hide()
|
||||
end
|
||||
self.warnSeverity = nil
|
||||
self.lastHappiness = nil
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Pet Castbar
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -1613,13 +1613,24 @@ function SFrames.Player:CastbarStart(spellName, duration)
|
||||
cb:SetMinMaxValues(0, cb.maxValue)
|
||||
cb:SetValue(0)
|
||||
cb.text:SetText(spellName)
|
||||
|
||||
|
||||
local texture
|
||||
local _UnitCastingInfo = UnitCastingInfo or (ShaguTweaks and ShaguTweaks.UnitCastingInfo)
|
||||
if _UnitCastingInfo then
|
||||
local _, _, _, tex = _UnitCastingInfo("player")
|
||||
texture = tex
|
||||
end
|
||||
if not texture and SFrames.castdb and UnitGUID then
|
||||
local guid = UnitGUID("player")
|
||||
if guid and SFrames.castdb[guid] and SFrames.castdb[guid].icon then
|
||||
texture = SFrames.castdb[guid].icon
|
||||
end
|
||||
end
|
||||
if (not texture or texture == "Interface\\Icons\\INV_Misc_QuestionMark")
|
||||
and SFrames.GetSpellIcon then
|
||||
texture = SFrames.GetSpellIcon(spellName) or texture
|
||||
end
|
||||
|
||||
if texture then
|
||||
cb.icon:SetTexture(texture)
|
||||
cb.icon:Show()
|
||||
@@ -1650,13 +1661,24 @@ function SFrames.Player:CastbarChannelStart(duration, spellName)
|
||||
cb:SetMinMaxValues(0, cb.maxValue)
|
||||
cb:SetValue(cb.maxValue)
|
||||
cb.text:SetText(spellName)
|
||||
|
||||
|
||||
local texture
|
||||
local _UnitChannelInfo = UnitChannelInfo or (ShaguTweaks and ShaguTweaks.UnitChannelInfo)
|
||||
if _UnitChannelInfo then
|
||||
local _, _, _, tex = _UnitChannelInfo("player")
|
||||
texture = tex
|
||||
end
|
||||
if not texture and SFrames.castdb and UnitGUID then
|
||||
local guid = UnitGUID("player")
|
||||
if guid and SFrames.castdb[guid] and SFrames.castdb[guid].icon then
|
||||
texture = SFrames.castdb[guid].icon
|
||||
end
|
||||
end
|
||||
if (not texture or texture == "Interface\\Icons\\INV_Misc_QuestionMark")
|
||||
and SFrames.GetSpellIcon then
|
||||
texture = SFrames.GetSpellIcon(spellName) or texture
|
||||
end
|
||||
|
||||
if texture then
|
||||
cb.icon:SetTexture(texture)
|
||||
cb.icon:Show()
|
||||
@@ -1714,6 +1736,9 @@ function SFrames.Player:CastbarOnUpdate()
|
||||
end
|
||||
cb:SetValue(elapsed)
|
||||
cb.time:SetText(string.format("%.1f", math.max(cb.maxValue - elapsed, 0)))
|
||||
if not cb.icon:IsShown() then
|
||||
self:CastbarTryResolveIcon()
|
||||
end
|
||||
elseif cb.channeling then
|
||||
local timeRemaining = cb.endTime - GetTime()
|
||||
if timeRemaining <= 0 then
|
||||
@@ -1724,6 +1749,9 @@ function SFrames.Player:CastbarOnUpdate()
|
||||
end
|
||||
cb:SetValue(timeRemaining)
|
||||
cb.time:SetText(string.format("%.1f", timeRemaining))
|
||||
if not cb.icon:IsShown() then
|
||||
self:CastbarTryResolveIcon()
|
||||
end
|
||||
elseif cb.fadeOut then
|
||||
local alpha = cb:GetAlpha() - 0.05
|
||||
if alpha > 0 then
|
||||
@@ -1740,3 +1768,41 @@ function SFrames.Player:CastbarOnUpdate()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SFrames.Player:CastbarTryResolveIcon()
|
||||
local cb = self.frame.castbar
|
||||
local spellName = cb.text:GetText()
|
||||
local texture
|
||||
|
||||
if SFrames.castdb and UnitGUID then
|
||||
local guid = UnitGUID("player")
|
||||
if guid and SFrames.castdb[guid] then
|
||||
local entry = SFrames.castdb[guid]
|
||||
if entry.icon and entry.icon ~= "Interface\\Icons\\INV_Misc_QuestionMark" then
|
||||
texture = entry.icon
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not texture and NanamiPlates and NanamiPlates.castDB and UnitGUID then
|
||||
local guid = UnitGUID("player")
|
||||
if guid and NanamiPlates.castDB[guid] then
|
||||
local entry = NanamiPlates.castDB[guid]
|
||||
if entry.icon and entry.icon ~= "Interface\\Icons\\INV_Misc_QuestionMark" then
|
||||
texture = entry.icon
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not texture and SFrames.GetSpellIcon then
|
||||
texture = SFrames.GetSpellIcon(spellName)
|
||||
end
|
||||
|
||||
if texture then
|
||||
cb.icon:SetTexture(texture)
|
||||
cb.icon:SetAlpha(1)
|
||||
cb.ibg:SetAlpha(1)
|
||||
cb.icon:Show()
|
||||
cb.ibg:Show()
|
||||
end
|
||||
end
|
||||
|
||||
493
Units/Target.lua
493
Units/Target.lua
@@ -1,6 +1,177 @@
|
||||
SFrames.Target = {}
|
||||
local _A = SFrames.ActiveTheme
|
||||
|
||||
local targetCLCast = nil
|
||||
local spellIconCache = {}
|
||||
|
||||
local SPELL_ICONS = {
|
||||
-- Mage
|
||||
["Fireball"] = "Spell_Fire_FlameBolt",
|
||||
["火球术"] = "Spell_Fire_FlameBolt",
|
||||
["Frostbolt"] = "Spell_Frost_FrostBolt02",
|
||||
["寒冰箭"] = "Spell_Frost_FrostBolt02",
|
||||
["Polymorph"] = "Spell_Nature_Polymorph",
|
||||
["变形术"] = "Spell_Nature_Polymorph",
|
||||
["Arcane Missiles"] = "Spell_Nature_StarFall",
|
||||
["奥术飞弹"] = "Spell_Nature_StarFall",
|
||||
["Pyroblast"] = "Spell_Fire_Fireball02",
|
||||
["炎爆术"] = "Spell_Fire_Fireball02",
|
||||
["Scorch"] = "Spell_Fire_SoulBurn",
|
||||
["灼烧"] = "Spell_Fire_SoulBurn",
|
||||
["Flamestrike"] = "Spell_Fire_SelfDestruct",
|
||||
["烈焰风暴"] = "Spell_Fire_SelfDestruct",
|
||||
["Blizzard"] = "Spell_Frost_IceStorm",
|
||||
["暴风雪"] = "Spell_Frost_IceStorm",
|
||||
-- Warlock
|
||||
["Shadow Bolt"] = "Spell_Shadow_ShadowBolt",
|
||||
["暗影箭"] = "Spell_Shadow_ShadowBolt",
|
||||
["Fear"] = "Spell_Shadow_Possession",
|
||||
["恐惧术"] = "Spell_Shadow_Possession",
|
||||
["Immolate"] = "Spell_Fire_Immolation",
|
||||
["献祭"] = "Spell_Fire_Immolation",
|
||||
["Soul Fire"] = "Spell_Fire_Fireball02",
|
||||
["灵魂之火"] = "Spell_Fire_Fireball02",
|
||||
["Drain Life"] = "Spell_Shadow_LifeDrain02",
|
||||
["吸取生命"] = "Spell_Shadow_LifeDrain02",
|
||||
["Drain Mana"] = "Spell_Shadow_SiphonMana",
|
||||
["吸取法力"] = "Spell_Shadow_SiphonMana",
|
||||
["Rain of Fire"] = "Spell_Shadow_RainOfFire",
|
||||
["火焰之雨"] = "Spell_Shadow_RainOfFire",
|
||||
["Hellfire"] = "Spell_Fire_Incinerate",
|
||||
["地狱烈焰"] = "Spell_Fire_Incinerate",
|
||||
-- Priest
|
||||
["Greater Heal"] = "Spell_Holy_GreaterHeal",
|
||||
["强效治疗术"] = "Spell_Holy_GreaterHeal",
|
||||
["Flash Heal"] = "Spell_Holy_FlashHeal",
|
||||
["快速治疗"] = "Spell_Holy_FlashHeal",
|
||||
["Heal"] = "Spell_Holy_Heal",
|
||||
["治疗术"] = "Spell_Holy_Heal",
|
||||
["Smite"] = "Spell_Holy_HolySmite",
|
||||
["惩击"] = "Spell_Holy_HolySmite",
|
||||
["Mind Blast"] = "Spell_Shadow_UnholyFrenzy",
|
||||
["心灵震爆"] = "Spell_Shadow_UnholyFrenzy",
|
||||
["Mind Flay"] = "Spell_Shadow_SiphonMana",
|
||||
["精神鞭笞"] = "Spell_Shadow_SiphonMana",
|
||||
["Mind Control"] = "Spell_Shadow_ShadowWordDominate",
|
||||
["精神控制"] = "Spell_Shadow_ShadowWordDominate",
|
||||
["Holy Fire"] = "Spell_Holy_SearingLight",
|
||||
["神圣之火"] = "Spell_Holy_SearingLight",
|
||||
["Resurrection"] = "Spell_Holy_Resurrection",
|
||||
["复活术"] = "Spell_Holy_Resurrection",
|
||||
-- Shaman
|
||||
["Lightning Bolt"] = "Spell_Nature_Lightning",
|
||||
["闪电箭"] = "Spell_Nature_Lightning",
|
||||
["Chain Lightning"] = "Spell_Nature_ChainLightning",
|
||||
["闪电链"] = "Spell_Nature_ChainLightning",
|
||||
["Healing Wave"] = "Spell_Nature_MagicImmunity",
|
||||
["治疗波"] = "Spell_Nature_MagicImmunity",
|
||||
["Lesser Healing Wave"] = "Spell_Nature_HealingWaveLesser",
|
||||
["次级治疗波"] = "Spell_Nature_HealingWaveLesser",
|
||||
["Chain Heal"] = "Spell_Nature_HealingWaveGreater",
|
||||
["治疗链"] = "Spell_Nature_HealingWaveGreater",
|
||||
["Ancestral Spirit"] = "Spell_Nature_Regenerate",
|
||||
["先祖之魂"] = "Spell_Nature_Regenerate",
|
||||
-- Druid
|
||||
["Wrath"] = "Spell_Nature_AbolishMagic",
|
||||
["愤怒"] = "Spell_Nature_AbolishMagic",
|
||||
["Starfire"] = "Spell_Arcane_StarFire",
|
||||
["星火术"] = "Spell_Arcane_StarFire",
|
||||
["Regrowth"] = "Spell_Nature_ResistNature",
|
||||
["愈合"] = "Spell_Nature_ResistNature",
|
||||
["Healing Touch"] = "Spell_Nature_HealingTouch",
|
||||
["治疗之触"] = "Spell_Nature_HealingTouch",
|
||||
["Entangling Roots"] = "Spell_Nature_StrangleVines",
|
||||
["纠缠根须"] = "Spell_Nature_StrangleVines",
|
||||
["Hibernate"] = "Spell_Nature_Sleep",
|
||||
["休眠"] = "Spell_Nature_Sleep",
|
||||
["Rebirth"] = "Spell_Nature_Reincarnation",
|
||||
["复生"] = "Spell_Nature_Reincarnation",
|
||||
["Tranquility"] = "Spell_Nature_Tranquility",
|
||||
["宁静"] = "Spell_Nature_Tranquility",
|
||||
["Moonfire"] = "Spell_Nature_StarFall",
|
||||
["月火术"] = "Spell_Nature_StarFall",
|
||||
-- Paladin
|
||||
["Holy Light"] = "Spell_Holy_HolyBolt",
|
||||
["圣光术"] = "Spell_Holy_HolyBolt",
|
||||
["Flash of Light"] = "Spell_Holy_FlashHeal",
|
||||
["圣光闪现"] = "Spell_Holy_FlashHeal",
|
||||
["Hammer of Wrath"] = "Spell_Holy_SealOfMight",
|
||||
["愤怒之锤"] = "Spell_Holy_SealOfMight",
|
||||
["Exorcism"] = "Spell_Holy_Excorcism_02",
|
||||
["驱邪术"] = "Spell_Holy_Excorcism_02",
|
||||
["Redemption"] = "Spell_Holy_Resurrection",
|
||||
["救赎"] = "Spell_Holy_Resurrection",
|
||||
-- Hunter
|
||||
["Aimed Shot"] = "INV_Spear_07",
|
||||
["瞄准射击"] = "INV_Spear_07",
|
||||
["Multi-Shot"] = "Ability_UpgradeMoonGlaive",
|
||||
["多重射击"] = "Ability_UpgradeMoonGlaive",
|
||||
["Volley"] = "Ability_Marksmanship",
|
||||
["乱射"] = "Ability_Marksmanship",
|
||||
["Revive Pet"] = "Ability_Hunter_BeastSoothe",
|
||||
["复活宠物"] = "Ability_Hunter_BeastSoothe",
|
||||
-- Common NPC / generic
|
||||
["Shoot"] = "Ability_Marksmanship",
|
||||
["射击"] = "Ability_Marksmanship",
|
||||
["Mend"] = "Spell_Holy_Heal",
|
||||
["修补"] = "Spell_Holy_Heal",
|
||||
["Rejuvenation"] = "Spell_Nature_Rejuvenation",
|
||||
["回春术"] = "Spell_Nature_Rejuvenation",
|
||||
}
|
||||
for k, v in pairs(SPELL_ICONS) do
|
||||
SPELL_ICONS[k] = "Interface\\Icons\\" .. v
|
||||
end
|
||||
|
||||
local function BuildSpellIconCache()
|
||||
if not GetSpellName or not GetSpellTexture then return end
|
||||
local i = 1
|
||||
while true do
|
||||
local name = GetSpellName(i, "spell")
|
||||
if not name then break end
|
||||
local tex = GetSpellTexture(i, "spell")
|
||||
if tex then spellIconCache[name] = tex end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function GetSpellIcon(spellName)
|
||||
if not spellName then return nil end
|
||||
local tex = spellIconCache[spellName]
|
||||
or SPELL_ICONS[spellName]
|
||||
or (NanamiPlates_CombatLog and NanamiPlates_CombatLog.castIcons
|
||||
and NanamiPlates_CombatLog.castIcons[spellName])
|
||||
if tex then return tex end
|
||||
if GetSpellName and GetSpellTexture then
|
||||
local i = 1
|
||||
while true do
|
||||
local name = GetSpellName(i, "spell")
|
||||
if not name then break end
|
||||
if name == spellName then
|
||||
tex = GetSpellTexture(i, "spell")
|
||||
if tex then
|
||||
spellIconCache[spellName] = tex
|
||||
return tex
|
||||
end
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
SFrames.GetSpellIcon = GetSpellIcon
|
||||
SFrames.BuildSpellIconCache = BuildSpellIconCache
|
||||
|
||||
local function CLMatch(str, pattern)
|
||||
if not str or not pattern then return nil end
|
||||
local pat = string.gsub(pattern, "%%%d?%$?s", "(.+)")
|
||||
pat = string.gsub(pat, "%%%d?%$?d", "(%%d+)")
|
||||
for a, b, c, d in string.gfind(str, pat) do
|
||||
return a, b, c, d
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function Clamp(value, minValue, maxValue)
|
||||
if value < minValue then
|
||||
return minValue
|
||||
@@ -467,7 +638,11 @@ function SFrames.Target:Initialize()
|
||||
self:CreateAuras()
|
||||
self:CreateCastbar()
|
||||
self:InitializeDistanceFrame()
|
||||
|
||||
self:InitCastDetection()
|
||||
|
||||
BuildSpellIconCache()
|
||||
SFrames:RegisterEvent("SPELLS_CHANGED", BuildSpellIconCache)
|
||||
|
||||
f.unit = "target"
|
||||
f:SetScript("OnEnter", function()
|
||||
GameTooltip_SetDefaultAnchor(GameTooltip, this)
|
||||
@@ -492,11 +667,181 @@ function SFrames.Target:Initialize()
|
||||
end
|
||||
end
|
||||
|
||||
function SFrames.Target:InitCastDetection()
|
||||
local castFrame = CreateFrame("Frame", nil, UIParent)
|
||||
|
||||
castFrame:RegisterEvent("UNIT_CASTEVENT")
|
||||
castFrame:RegisterEvent("SPELLCAST_START")
|
||||
castFrame:RegisterEvent("SPELLCAST_STOP")
|
||||
castFrame:RegisterEvent("SPELLCAST_FAILED")
|
||||
castFrame:RegisterEvent("SPELLCAST_INTERRUPTED")
|
||||
castFrame:RegisterEvent("SPELLCAST_CHANNEL_START")
|
||||
castFrame:RegisterEvent("SPELLCAST_CHANNEL_STOP")
|
||||
|
||||
local CL_EVENTS = {
|
||||
"CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE",
|
||||
"CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE",
|
||||
"CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE",
|
||||
"CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF",
|
||||
"CHAT_MSG_SPELL_CREATURE_VS_PARTY_BUFF",
|
||||
"CHAT_MSG_SPELL_CREATURE_VS_SELF_BUFF",
|
||||
"CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE",
|
||||
"CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF",
|
||||
"CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE",
|
||||
"CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF",
|
||||
"CHAT_MSG_SPELL_PARTY_DAMAGE",
|
||||
"CHAT_MSG_SPELL_PARTY_BUFF",
|
||||
"CHAT_MSG_SPELL_SELF_DAMAGE",
|
||||
"CHAT_MSG_SPELL_SELF_BUFF",
|
||||
}
|
||||
for _, ev in ipairs(CL_EVENTS) do
|
||||
castFrame:RegisterEvent(ev)
|
||||
end
|
||||
|
||||
local function ResolveSelfIcon(spellName)
|
||||
local texture
|
||||
local _UCI = UnitCastingInfo or (ShaguTweaks and ShaguTweaks.UnitCastingInfo)
|
||||
if _UCI then
|
||||
local _, _, _, tex = _UCI("player")
|
||||
texture = tex
|
||||
end
|
||||
if not texture then
|
||||
local _UCH = UnitChannelInfo or (ShaguTweaks and ShaguTweaks.UnitChannelInfo)
|
||||
if _UCH then
|
||||
local _, _, _, tex = _UCH("player")
|
||||
texture = tex
|
||||
end
|
||||
end
|
||||
if not texture and SFrames.castdb and UnitGUID then
|
||||
local guid = UnitGUID("player")
|
||||
if guid and SFrames.castdb[guid] and SFrames.castdb[guid].icon then
|
||||
texture = SFrames.castdb[guid].icon
|
||||
end
|
||||
end
|
||||
if not texture or texture == "Interface\\Icons\\INV_Misc_QuestionMark" then
|
||||
texture = GetSpellIcon(spellName) or texture
|
||||
end
|
||||
return texture or "Interface\\Icons\\INV_Misc_QuestionMark"
|
||||
end
|
||||
|
||||
castFrame:SetScript("OnEvent", function()
|
||||
-- Player's own cast events (for self-target and friendly-target-is-self)
|
||||
if event == "SPELLCAST_START" then
|
||||
if UnitExists("target") and UnitIsUnit("target", "player") then
|
||||
local spellName = arg1
|
||||
local duration = arg2
|
||||
targetCLCast = {
|
||||
spell = spellName,
|
||||
startTime = GetTime(),
|
||||
duration = (duration or 2000) / 1000,
|
||||
icon = ResolveSelfIcon(spellName),
|
||||
channel = false,
|
||||
}
|
||||
end
|
||||
return
|
||||
end
|
||||
if event == "SPELLCAST_CHANNEL_START" then
|
||||
if UnitExists("target") and UnitIsUnit("target", "player") then
|
||||
local duration = arg1
|
||||
local spellName = arg2
|
||||
targetCLCast = {
|
||||
spell = spellName,
|
||||
startTime = GetTime(),
|
||||
duration = (duration or 2000) / 1000,
|
||||
icon = ResolveSelfIcon(spellName),
|
||||
channel = true,
|
||||
}
|
||||
end
|
||||
return
|
||||
end
|
||||
if event == "SPELLCAST_STOP" or event == "SPELLCAST_FAILED"
|
||||
or event == "SPELLCAST_INTERRUPTED" or event == "SPELLCAST_CHANNEL_STOP" then
|
||||
if UnitExists("target") and UnitIsUnit("target", "player") then
|
||||
targetCLCast = nil
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- UNIT_CASTEVENT (SuperWoW / TurtleWoW): works for all units
|
||||
if event == "UNIT_CASTEVENT" then
|
||||
if not UnitGUID or not UnitExists("target") then return end
|
||||
local targetGUID = UnitGUID("target")
|
||||
if not targetGUID or arg1 ~= targetGUID then return end
|
||||
|
||||
if arg3 == "START" or arg3 == "CAST" or arg3 == "CHANNEL" then
|
||||
local spell, icon
|
||||
if SpellInfo and arg4 then
|
||||
spell, _, icon = SpellInfo(arg4)
|
||||
end
|
||||
spell = spell or "Casting"
|
||||
if not icon or icon == "" or icon == "Interface\\Icons\\INV_Misc_QuestionMark" then
|
||||
icon = GetSpellIcon(spell) or icon
|
||||
end
|
||||
icon = icon or "Interface\\Icons\\INV_Misc_QuestionMark"
|
||||
targetCLCast = {
|
||||
spell = spell,
|
||||
startTime = GetTime(),
|
||||
duration = (arg5 or 2000) / 1000,
|
||||
icon = icon,
|
||||
channel = (arg3 == "CHANNEL"),
|
||||
}
|
||||
elseif arg3 == "FAIL" then
|
||||
targetCLCast = nil
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Combat log parsing: "X begins to cast Y" (third-person, all other units)
|
||||
if not arg1 or not UnitExists("target") then return end
|
||||
local targetName = UnitName("target")
|
||||
if not targetName then return end
|
||||
|
||||
local msg = arg1
|
||||
local caster, spell
|
||||
|
||||
local castStart = SPELLCASTOTHERSTART or "%s begins to cast %s."
|
||||
caster, spell = CLMatch(msg, castStart)
|
||||
if not caster then
|
||||
local perfStart = SPELLPERFORMOTHERSTART or "%s begins to perform %s."
|
||||
caster, spell = CLMatch(msg, perfStart)
|
||||
end
|
||||
|
||||
if caster and caster == targetName and spell then
|
||||
local icon = GetSpellIcon(spell) or "Interface\\Icons\\INV_Misc_QuestionMark"
|
||||
targetCLCast = {
|
||||
spell = spell,
|
||||
startTime = GetTime(),
|
||||
duration = 2.0,
|
||||
icon = icon,
|
||||
channel = false,
|
||||
}
|
||||
return
|
||||
end
|
||||
|
||||
if targetCLCast then
|
||||
local isFail = false
|
||||
for u in string.gfind(msg, "(.+)'s .+ is interrupted%.") do
|
||||
if u == targetName then isFail = true end
|
||||
end
|
||||
if not isFail then
|
||||
for u in string.gfind(msg, "(.+)'s .+ fails%.") do
|
||||
if u == targetName then isFail = true end
|
||||
end
|
||||
end
|
||||
if not isFail and SPELLINTERRUPTOTHEROTHER then
|
||||
local a = CLMatch(msg, SPELLINTERRUPTOTHEROTHER)
|
||||
if a == targetName then isFail = true end
|
||||
end
|
||||
if isFail then targetCLCast = nil end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function SFrames.Target:OnTargetChanged()
|
||||
targetCLCast = nil
|
||||
if UnitExists("target") then
|
||||
self.frame:Show()
|
||||
self:UpdateAll()
|
||||
-- Force distance update immediately
|
||||
if SFrames.Target.distanceFrame then
|
||||
local dist = self:GetDistance("target")
|
||||
SFrames.Target.distanceFrame.text:SetText(dist or "---")
|
||||
@@ -1141,49 +1486,149 @@ function SFrames.Target:CastbarOnUpdate()
|
||||
cb.ibg:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
-- Try to read cast from Vanilla extensions (SuperWoW or TurtleWoW modern API, or ShaguTweaks)
|
||||
local cast, nameSubtext, text, texture, startTime, endTime
|
||||
|
||||
local cast, texture, startTime, endTime, channel
|
||||
|
||||
-- 1) UnitCastingInfo / UnitChannelInfo (TurtleWoW / ShaguTweaks)
|
||||
local _UnitCastingInfo = UnitCastingInfo or (ShaguTweaks and ShaguTweaks.UnitCastingInfo)
|
||||
if _UnitCastingInfo then
|
||||
cast, nameSubtext, text, texture, startTime, endTime = _UnitCastingInfo("target")
|
||||
local c, _, _, tex, st, et = _UnitCastingInfo("target")
|
||||
if c then
|
||||
cast, texture, startTime, endTime = c, tex, st, et
|
||||
end
|
||||
end
|
||||
|
||||
local channel
|
||||
local _UnitChannelInfo = UnitChannelInfo or (ShaguTweaks and ShaguTweaks.UnitChannelInfo)
|
||||
if not cast and _UnitChannelInfo then
|
||||
channel, nameSubtext, text, texture, startTime, endTime = _UnitChannelInfo("target")
|
||||
cast = channel
|
||||
|
||||
if not cast then
|
||||
local _UnitChannelInfo = UnitChannelInfo or (ShaguTweaks and ShaguTweaks.UnitChannelInfo)
|
||||
if _UnitChannelInfo then
|
||||
local c, _, _, tex, st, et = _UnitChannelInfo("target")
|
||||
if c then
|
||||
cast, texture, startTime, endTime = c, tex, st, et
|
||||
channel = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 2) SFrames.castdb (UNIT_CASTEVENT via Tweaks.lua, has SpellInfo icon)
|
||||
if SFrames.castdb and UnitGUID then
|
||||
local guid = UnitGUID("target")
|
||||
if guid then
|
||||
local entry = SFrames.castdb[guid]
|
||||
if entry and entry.cast and entry.start and entry.casttime then
|
||||
local elapsed = GetTime() - entry.start
|
||||
local duration = entry.casttime / 1000
|
||||
if elapsed < duration + 0.5 then
|
||||
if not cast then
|
||||
cast = entry.cast
|
||||
startTime = entry.start * 1000
|
||||
endTime = (entry.start + duration) * 1000
|
||||
channel = entry.channel
|
||||
end
|
||||
if not texture or texture == "Interface\\Icons\\INV_Misc_QuestionMark" then
|
||||
texture = entry.icon
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 3) NanamiPlates castDB (GUID-based, UNIT_CASTEVENT with SpellInfo icon)
|
||||
if NanamiPlates and NanamiPlates.castDB and UnitGUID then
|
||||
local guid = UnitGUID("target")
|
||||
if guid then
|
||||
local entry = NanamiPlates.castDB[guid]
|
||||
if entry and entry.spell and entry.startTime and entry.duration then
|
||||
local elapsed = GetTime() - entry.startTime
|
||||
local duration = entry.duration / 1000
|
||||
if elapsed < duration + 0.5 then
|
||||
if not cast then
|
||||
cast = entry.spell
|
||||
startTime = entry.startTime * 1000
|
||||
endTime = (entry.startTime + duration) * 1000
|
||||
channel = entry.channel
|
||||
end
|
||||
if not texture or texture == "Interface\\Icons\\INV_Misc_QuestionMark" then
|
||||
texture = entry.icon
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 4) NanamiPlates castTracker (name-based, combat log)
|
||||
if not cast and NanamiPlates and NanamiPlates.castTracker then
|
||||
local targetName = UnitName("target")
|
||||
if targetName and NanamiPlates.castTracker[targetName] then
|
||||
local entries = NanamiPlates.castTracker[targetName]
|
||||
if entries and entries[1] then
|
||||
local entry = entries[1]
|
||||
if entry.spell and entry.startTime then
|
||||
local duration = (entry.duration or 2000) / 1000
|
||||
local elapsed = GetTime() - entry.startTime
|
||||
if elapsed < duration + 0.5 then
|
||||
cast = entry.spell
|
||||
texture = entry.icon
|
||||
startTime = entry.startTime * 1000
|
||||
endTime = (entry.startTime + duration) * 1000
|
||||
channel = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 5) Local UNIT_CASTEVENT / SPELLCAST_* tracker
|
||||
if targetCLCast then
|
||||
local elapsed = GetTime() - targetCLCast.startTime
|
||||
if elapsed < targetCLCast.duration + 0.5 then
|
||||
if not cast then
|
||||
cast = targetCLCast.spell
|
||||
startTime = targetCLCast.startTime * 1000
|
||||
endTime = (targetCLCast.startTime + targetCLCast.duration) * 1000
|
||||
channel = targetCLCast.channel
|
||||
end
|
||||
if not texture or texture == "Interface\\Icons\\INV_Misc_QuestionMark" then
|
||||
texture = targetCLCast.icon
|
||||
end
|
||||
else
|
||||
targetCLCast = nil
|
||||
end
|
||||
end
|
||||
|
||||
if cast and startTime and endTime then
|
||||
local duration = (endTime - startTime) / 1000
|
||||
local cur = GetTime() - (startTime / 1000)
|
||||
|
||||
|
||||
if channel then
|
||||
cur = duration + (startTime / 1000) - GetTime()
|
||||
end
|
||||
|
||||
|
||||
if cur > duration then cur = duration end
|
||||
if cur < 0 then cur = 0 end
|
||||
|
||||
|
||||
cb:SetMinMaxValues(0, duration)
|
||||
cb:SetValue(cur)
|
||||
cb.text:SetText(cast)
|
||||
|
||||
if texture then
|
||||
cb.icon:SetTexture(texture)
|
||||
|
||||
if not texture or texture == "Interface\\Icons\\INV_Misc_QuestionMark" then
|
||||
texture = GetSpellIcon(cast) or texture
|
||||
end
|
||||
|
||||
|
||||
cb:SetAlpha(1)
|
||||
cb.cbbg:SetAlpha(1)
|
||||
cb.icon:SetAlpha(1)
|
||||
cb.ibg:SetAlpha(1)
|
||||
|
||||
cb:Show()
|
||||
cb.cbbg:Show()
|
||||
cb.icon:Show()
|
||||
cb.ibg:Show()
|
||||
|
||||
if texture then
|
||||
cb.icon:SetTexture(texture)
|
||||
cb.icon:SetAlpha(1)
|
||||
cb.ibg:SetAlpha(1)
|
||||
cb.icon:Show()
|
||||
cb.ibg:Show()
|
||||
else
|
||||
cb.icon:Hide()
|
||||
cb.ibg:Hide()
|
||||
end
|
||||
else
|
||||
cb:Hide()
|
||||
cb.cbbg:Hide()
|
||||
|
||||
Reference in New Issue
Block a user