local _G = ShaguTweaks.GetGlobalEnv() local T = ShaguTweaks.T local GetExpansion = ShaguTweaks.GetExpansion local API = ShaguTweaks.API local LegacyCastingInfo = ShaguTweaks.UnitCastingInfo local LegacyChannelInfo = ShaguTweaks.UnitChannelInfo local module = ShaguTweaks:register({ title = T["Enemy Castbars"], description = T["Shows an enemy castbar on target unit frame."], expansions = { ["vanilla"] = true }, category = T["Unit Frames"], enabled = true, }) local castbar = CreateFrame("StatusBar", "ShaguTargetCastbar", TargetFrame) castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -4) castbar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar") castbar:SetStatusBarColor(1, .8, 0, 1) castbar:SetWidth(140) castbar:SetHeight(10) castbar:Hide() castbar.texture = CreateFrame("Frame", nil, castbar) castbar.texture:SetPoint("RIGHT", castbar, "LEFT", -2, 0) castbar.texture:SetHeight(20) castbar.texture:SetWidth(20) castbar.texture.icon = castbar.texture:CreateTexture(nil, "BACKGROUND") castbar.texture.icon:SetPoint("CENTER", 0, 0) castbar.texture.icon:SetWidth(16) castbar.texture.icon:SetHeight(16) castbar.texture:SetBackdrop({ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = true, tileSize = 8, edgeSize = 12, insets = { left = 3, right = 3, top = 3, bottom = 3 } }) castbar.bg = castbar:CreateTexture(nil, "BACKGROUND") castbar.bg:SetTexture("Interface\\TARGETINGFRAME\\UI-StatusBar") castbar.bg:SetVertexColor(.1, .1, 0, .8) castbar.bg:SetAllPoints(true) castbar.spark = castbar:CreateTexture(nil, "OVERLAY") castbar.spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark") castbar.spark:SetWidth(20) castbar.spark:SetHeight(20) castbar.spark:SetBlendMode("ADD") castbar.backdrop = CreateFrame("Frame", nil, castbar) castbar.backdrop:SetFrameStrata("BACKGROUND") castbar.backdrop:SetPoint("TOPLEFT", castbar, "TOPLEFT", -3, 3) castbar.backdrop:SetPoint("BOTTOMRIGHT", castbar, "BOTTOMRIGHT", 3, -3) castbar.backdrop:SetBackdrop({ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = true, tileSize = 8, edgeSize = 12, insets = { left = 3, right = 3, top = 3, bottom = 3 } }) castbar.text = castbar:CreateFontString(nil, "HIGH", "GameFontWhite") castbar.text:SetPoint("CENTER", castbar, "CENTER", 0, 0) local font, size, opts = castbar.text:GetFont() castbar.text:SetFont(font, size - 2, "THINOUTLINE") local function QueryLegacy(query) if not query then return end local cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill = LegacyCastingInfo(query) if cast then return cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill, false end local channel channel, nameSubtext, text, texture, startTime, endTime, isTradeSkill = LegacyChannelInfo(query) if channel then return channel, nameSubtext, text, texture, startTime, endTime, isTradeSkill, true end end local function QueryCast(unit) if not unit then return end -- ClassicAPI is authoritative for real unit tokens and provides exact -- engine/server timing. Keep the old parser only as a compatibility layer. local cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill = API.GetCastInfo(unit) if cast then return cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill, false end local channel channel, nameSubtext, text, texture, startTime, endTime, isTradeSkill = API.GetChannelInfo(unit) if channel then return channel, nameSubtext, text, texture, startTime, endTime, isTradeSkill, true end -- SuperWoW remains a second source for GUID-keyed casts when available. if ShaguTweaks.superwow_active and not UnitIsUnit(unit, "player") then local _, guid = UnitExists(unit) if guid then local a, b, c, d, e, f, g, h = QueryLegacy(guid) if a then return a, b, c, d, e, f, g, h end end end return QueryLegacy(unit) end module.enable = function(self) local oldUpdate = TargetFrame:GetScript("OnUpdate") TargetFrame:SetScript("OnUpdate", function(arg) if oldUpdate then oldUpdate(arg) end local unit = this.unit or "target" local cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill, isChannel = QueryCast(unit) if cast and startTime and endTime and endTime > startTime then local duration = endTime - startTime local max = duration / 1000 local cur = GetTime() - startTime / 1000 if isChannel then cur = max + startTime/1000 - GetTime() end cur = cur > max and max or cur cur = cur < 0 and 0 or cur castbar:Show() castbar:SetMinMaxValues(0, max) castbar:SetValue(cur) local percent = cur / max local x = castbar:GetWidth()*percent castbar.spark:SetPoint("CENTER", castbar, "LEFT", x, 0) castbar.text:SetText(cast) if texture then castbar.texture.icon:SetTexture(texture) castbar.texture.icon:Show() else castbar.texture.icon:Hide() end castbar:ClearAllPoints() castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -4) local targetOfTarget = TargetofTargetFrame and TargetofTargetFrame:IsShown() local debuff11 = TargetFrameDebuff11 and TargetFrameDebuff11:IsShown() local debuff7 = TargetFrameDebuff7 and TargetFrameDebuff7:IsShown() local buff1 = TargetFrameBuff1 and TargetFrameBuff1:IsShown() if targetOfTarget then castbar:ClearAllPoints() castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -24) if debuff11 then castbar:ClearAllPoints() castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -45) if buff1 then castbar:ClearAllPoints() castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -65) end end else if debuff7 then castbar:ClearAllPoints() castbar:SetPoint("BOTTOM", TargetFrame, "BOTTOM", -12, -24) end end else castbar:Hide() end end) end