mirror of
https://github.com/Bluewhale1337/HealBotBlue.git
synced 2026-11-10 03:57:37 +00:00
323 lines
14 KiB
Lua
323 lines
14 KiB
Lua
-- HealBot_View_HoT.lua
|
|
-- HoT overlays, duration timers, and side list rendering
|
|
|
|
local HealBot_PlayerHoTsListFrame = nil
|
|
local HealBot_PlayerHoTFrames = {}
|
|
local HealBot_PlayerHoTs_ListCache = {}
|
|
local HealBot_ActiveHoTUnitMap = {}
|
|
|
|
local function HealBot_PlayerHoTs_SortComparator(a, b)
|
|
return (a.expires or 0) < (b.expires or 0)
|
|
end
|
|
|
|
-- Reposition the HoT timer list frame based on config
|
|
local function HealBot_HoTTimerList_Reanchor()
|
|
if not HealBot_PlayerHoTsListFrame then return end
|
|
local pos = HealBot_Config.HealBot_Integrations_HoTTimerPosition or "BELOW"
|
|
HealBot_PlayerHoTsListFrame:ClearAllPoints()
|
|
if pos == "ABOVE" then
|
|
HealBot_PlayerHoTsListFrame:SetPoint("BOTTOMLEFT", HealBot_Action, "TOPLEFT", 0, 2)
|
|
elseif pos == "RIGHT" then
|
|
HealBot_PlayerHoTsListFrame:SetPoint("TOPLEFT", HealBot_Action, "TOPRIGHT", 2, 0)
|
|
elseif pos == "LEFT" then
|
|
HealBot_PlayerHoTsListFrame:SetPoint("TOPRIGHT", HealBot_Action, "TOPLEFT", -2, 0)
|
|
else -- BELOW (default)
|
|
HealBot_PlayerHoTsListFrame:SetPoint("TOPLEFT", HealBot_Action, "BOTTOMLEFT", 0, -2)
|
|
end
|
|
end
|
|
|
|
-- Reposition child HoT frames for stacking direction
|
|
local function HealBot_HoTTimerList_StackChild(frame, index)
|
|
local pos = HealBot_Config.HealBot_Integrations_HoTTimerPosition or "BELOW"
|
|
frame:ClearAllPoints()
|
|
if pos == "ABOVE" then
|
|
if index == 1 then
|
|
frame:SetPoint("BOTTOMLEFT", HealBot_PlayerHoTsListFrame, "BOTTOMLEFT", 0, 0)
|
|
else
|
|
frame:SetPoint("BOTTOMLEFT", HealBot_PlayerHoTFrames[index-1], "TOPLEFT", 0, 2)
|
|
end
|
|
else
|
|
if index == 1 then
|
|
frame:SetPoint("TOPLEFT", HealBot_PlayerHoTsListFrame, "TOPLEFT", 0, 0)
|
|
else
|
|
frame:SetPoint("TOPLEFT", HealBot_PlayerHoTFrames[index-1], "BOTTOMLEFT", 0, -2)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Clear all icon overlay timer texts
|
|
function HealBot_ClearHoTOverlays()
|
|
if not HealBot_Action_UnitButtons then return end
|
|
for unit, btnList in pairs(HealBot_Action_UnitButtons) do
|
|
for _, button in pairs(btnList) do
|
|
local bar = button.bar or getglobal(button:GetName() .. "Bar")
|
|
if bar then
|
|
for i = 1, 10 do
|
|
local iconText = bar["iconText"..i]
|
|
if iconText and iconText:IsVisible() then
|
|
iconText:SetText("")
|
|
iconText:Hide()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Render countdown numbers directly on unit bar icons
|
|
function HealBot_RenderHoTOverlays()
|
|
if not HealBot_Action_UnitButtons then return end
|
|
local iconSize = HealBot_Config.biconsize[HealBot_Config.Current_Skin] or 12
|
|
local fontSize = math.min(11, math.max(8, iconSize - 2))
|
|
|
|
for unit, btnList in pairs(HealBot_Action_UnitButtons) do
|
|
local unitMap = HealBot_ActiveHoTUnitMap[unit]
|
|
for _, button in pairs(btnList) do
|
|
local bar = HealBot_Action_HealthBar(button)
|
|
if bar and bar:IsVisible() then
|
|
for i = 1, 10 do
|
|
local icon = button["icon"..i] or getglobal(button:GetName() .. "BarIcon" .. i)
|
|
local iconText = bar["iconText"..i]
|
|
if icon and icon:IsVisible() then
|
|
local tex = icon:GetTexture()
|
|
local cleanTex = tex and string.lower(string.gsub(tex, "/", "\\"))
|
|
local shortTex = cleanTex and string.match(cleanTex, "([^\\]+)$")
|
|
local timeLeft = unitMap and (unitMap[tex] or (cleanTex and unitMap[cleanTex]) or (shortTex and unitMap[shortTex]))
|
|
if timeLeft then
|
|
if not iconText then
|
|
local overlayFrame = bar.overlayFrame
|
|
if not overlayFrame then
|
|
overlayFrame = CreateFrame("Frame", nil, bar)
|
|
overlayFrame:SetAllPoints(bar)
|
|
overlayFrame:SetFrameLevel(bar:GetFrameLevel() + 5)
|
|
bar.overlayFrame = overlayFrame
|
|
end
|
|
iconText = overlayFrame:CreateFontString(nil, "OVERLAY")
|
|
iconText:SetFont("Fonts\\ARIALN.TTF", fontSize, "OUTLINE")
|
|
iconText:SetPoint("CENTER", icon, "CENTER", 0, 0)
|
|
iconText:SetTextColor(1, 1, 1, 1)
|
|
bar["iconText"..i] = iconText
|
|
end
|
|
if bar.overlayFrame then bar.overlayFrame:Show() end
|
|
iconText:SetText(timeLeft)
|
|
iconText:Show()
|
|
else
|
|
if iconText and iconText:IsVisible() then
|
|
iconText:SetText("")
|
|
iconText:Hide()
|
|
end
|
|
end
|
|
else
|
|
if iconText and iconText:IsVisible() then
|
|
iconText:Hide()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Render HoT timer list
|
|
local function HealBot_RenderHoTList(numHoTs, currentTime)
|
|
if not HealBot_PlayerHoTsListFrame then
|
|
HealBot_PlayerHoTsListFrame = CreateFrame("Frame", "HealBot_PlayerHoTsListFrame", HealBot_Action)
|
|
HealBot_PlayerHoTsListFrame:SetWidth(128)
|
|
HealBot_PlayerHoTsListFrame:SetHeight(1)
|
|
end
|
|
|
|
HealBot_HoTTimerList_Reanchor()
|
|
HealBot_PlayerHoTsListFrame:Show()
|
|
|
|
-- Sort active HoTs by expiration
|
|
table.sort(HealBot_PlayerHoTs_ListCache, HealBot_PlayerHoTs_SortComparator)
|
|
|
|
for i = 1, math.max(numHoTs, table.getn(HealBot_PlayerHoTFrames)) do
|
|
local frame = HealBot_PlayerHoTFrames[i]
|
|
if i <= numHoTs then
|
|
if not frame then
|
|
frame = CreateFrame("Frame", "HealBot_PlayerHoT" .. i, HealBot_PlayerHoTsListFrame)
|
|
frame:SetWidth(128)
|
|
frame:SetHeight(16)
|
|
|
|
local icon = frame:CreateTexture(nil, "ARTWORK")
|
|
icon:SetWidth(14)
|
|
icon:SetHeight(14)
|
|
icon:SetPoint("LEFT", frame, "LEFT", 2, 0)
|
|
frame.icon = icon
|
|
|
|
local text = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
text:SetPoint("LEFT", icon, "RIGHT", 4, 0)
|
|
text:SetJustifyH("LEFT")
|
|
frame.text = text
|
|
|
|
HealBot_PlayerHoTFrames[i] = frame
|
|
end
|
|
|
|
HealBot_HoTTimerList_StackChild(frame, i)
|
|
|
|
local hot = HealBot_PlayerHoTs_ListCache[i]
|
|
local timeLeft = hot.timeLeft or math.floor(hot.expires - currentTime)
|
|
|
|
frame.icon:SetTexture(hot.texture)
|
|
frame.text:SetText(hot.name .. ": " .. timeLeft .. "s")
|
|
frame.text:SetTextColor(0.8, 1, 0.8)
|
|
frame:Show()
|
|
else
|
|
if frame then
|
|
frame:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
HealBot_PlayerHoTsListFrame:SetHeight(math.max(1, numHoTs * 18))
|
|
end
|
|
|
|
-- Unified HoT Timer Pipeline
|
|
function HealBot_UpdateActiveHoTTimers()
|
|
if HealBot_Config.HealBot_Integrations_ShowHoTTimers ~= 1 then
|
|
if HealBot_PlayerHoTsListFrame and HealBot_PlayerHoTsListFrame:IsVisible() then
|
|
HealBot_PlayerHoTsListFrame:Hide()
|
|
end
|
|
HealBot_ClearHoTOverlays()
|
|
return
|
|
end
|
|
|
|
local currentTime = GetTime()
|
|
local numHoTs = 0
|
|
|
|
-- Clear unit map (recycle)
|
|
for _, sub in pairs(HealBot_ActiveHoTUnitMap) do
|
|
for k in pairs(sub) do sub[k] = nil end
|
|
end
|
|
|
|
if HealBot_Integrations_Nampower_Active and HealBot_Nampower_Auras then
|
|
for targetKey, auras in pairs(HealBot_Nampower_Auras) do
|
|
local lowerKey = string.lower(targetKey)
|
|
local unitID = HealBot_Model and (HealBot_Model:GetUnitByGUID(targetKey) or HealBot_Model:GetUnitByGUID(lowerKey))
|
|
|
|
if not unitID then
|
|
local isPlayer = (HealBot_PlayerGUID and (targetKey == HealBot_PlayerGUID or lowerKey == string.lower(HealBot_PlayerGUID)))
|
|
or (UnitName("player") and (targetKey == UnitName("player") or lowerKey == string.lower(UnitName("player"))))
|
|
or (HealBot_GetUnitGUID and (targetKey == HealBot_GetUnitGUID("player") or lowerKey == string.lower(HealBot_GetUnitGUID("player") or "")))
|
|
if isPlayer then
|
|
unitID = "player"
|
|
end
|
|
end
|
|
|
|
if not unitID and HealBot_Model and HealBot_Model.GetUnitIDByName then
|
|
unitID = HealBot_Model:GetUnitIDByName(targetKey)
|
|
end
|
|
|
|
-- Multi-tier player name resolution
|
|
local displayName = nil
|
|
if unitID and unitID ~= "target" then
|
|
if HealBot_Model and HealBot_Model.units[unitID] and HealBot_Model.units[unitID].name then
|
|
displayName = HealBot_Model.units[unitID].name
|
|
end
|
|
if not displayName then
|
|
displayName = UnitName(unitID)
|
|
end
|
|
end
|
|
if not displayName and HealBot_Nampower_NameCache then
|
|
displayName = HealBot_Nampower_NameCache[targetKey] or HealBot_Nampower_NameCache[lowerKey]
|
|
end
|
|
if not displayName and UnitExists("target") and HealBot_GetUnitGUID and (targetKey == HealBot_GetUnitGUID("target") or lowerKey == string.lower(HealBot_GetUnitGUID("target") or "")) then
|
|
displayName = UnitName("target")
|
|
end
|
|
if not displayName and UnitExists("mouseover") and HealBot_GetUnitGUID and (targetKey == HealBot_GetUnitGUID("mouseover") or lowerKey == string.lower(HealBot_GetUnitGUID("mouseover") or "")) then
|
|
displayName = UnitName("mouseover")
|
|
end
|
|
if not displayName then
|
|
local uName = UnitName(targetKey)
|
|
if uName and uName ~= targetKey and uName ~= "Unknown" then
|
|
displayName = uName
|
|
end
|
|
end
|
|
if displayName and HealBot_Nampower_NameCache then
|
|
HealBot_Nampower_NameCache[targetKey] = displayName
|
|
HealBot_Nampower_NameCache[lowerKey] = displayName
|
|
end
|
|
|
|
-- Exclude pets
|
|
if not (unitID and string.find(unitID, "pet")) then
|
|
for spellName, expiration in pairs(auras) do
|
|
local auraInfo = HealBot_TrackedAura_Spells and HealBot_TrackedAura_Spells[spellName]
|
|
if not auraInfo and HealBot_TrackedAuras and HealBot_TrackedAuras[spellName] then
|
|
auraInfo = HealBot_TrackedAuras[spellName]
|
|
end
|
|
if auraInfo and auraInfo.showTimer and expiration > currentTime then
|
|
local timeLeft = math.floor(expiration - currentTime)
|
|
local tex = auraInfo.texture or "Interface\\Icons\\INV_Misc_QuestionMark"
|
|
|
|
numHoTs = numHoTs + 1
|
|
if not HealBot_PlayerHoTs_ListCache[numHoTs] then
|
|
HealBot_PlayerHoTs_ListCache[numHoTs] = {}
|
|
end
|
|
local hot = HealBot_PlayerHoTs_ListCache[numHoTs]
|
|
hot.unit = unitID
|
|
hot.name = displayName or "Unknown"
|
|
hot.spell = spellName
|
|
hot.texture = tex
|
|
hot.expires = expiration
|
|
hot.timeLeft = timeLeft
|
|
|
|
if unitID then
|
|
if not HealBot_ActiveHoTUnitMap[unitID] then
|
|
HealBot_ActiveHoTUnitMap[unitID] = {}
|
|
end
|
|
local cleanTex = string.lower(string.gsub(tex, "/", "\\"))
|
|
local shortTex = string.match(cleanTex, "([^\\]+)$")
|
|
HealBot_ActiveHoTUnitMap[unitID][tex] = timeLeft
|
|
HealBot_ActiveHoTUnitMap[unitID][cleanTex] = timeLeft
|
|
if shortTex then
|
|
HealBot_ActiveHoTUnitMap[unitID][shortTex] = timeLeft
|
|
end
|
|
|
|
-- If player in raid, map under raid token button as well
|
|
if unitID == "player" and HealBot_Action_UnitButtons then
|
|
for btnUnit in pairs(HealBot_Action_UnitButtons) do
|
|
if btnUnit ~= "player" and not string.find(btnUnit, "^Test") and UnitIsUnit(btnUnit, "player") then
|
|
if not HealBot_ActiveHoTUnitMap[btnUnit] then
|
|
HealBot_ActiveHoTUnitMap[btnUnit] = {}
|
|
end
|
|
HealBot_ActiveHoTUnitMap[btnUnit][tex] = timeLeft
|
|
HealBot_ActiveHoTUnitMap[btnUnit][cleanTex] = timeLeft
|
|
if shortTex then
|
|
HealBot_ActiveHoTUnitMap[btnUnit][shortTex] = timeLeft
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Blank out remaining cache entries so sort doesn't read them
|
|
for i = numHoTs + 1, table.getn(HealBot_PlayerHoTs_ListCache) do
|
|
HealBot_PlayerHoTs_ListCache[i].expires = 9999999999
|
|
end
|
|
|
|
local displayMode = HealBot_Config.HealBot_Integrations_HoTTimerDisplayMode or 0
|
|
if displayMode == 0 then
|
|
-- List Mode
|
|
HealBot_ClearHoTOverlays()
|
|
HealBot_RenderHoTList(numHoTs, currentTime)
|
|
elseif displayMode == 1 then
|
|
-- Overlay Mode
|
|
if HealBot_PlayerHoTsListFrame and HealBot_PlayerHoTsListFrame:IsVisible() then
|
|
HealBot_PlayerHoTsListFrame:Hide()
|
|
end
|
|
HealBot_RenderHoTOverlays()
|
|
else
|
|
-- Both Mode (2)
|
|
HealBot_RenderHoTList(numHoTs, currentTime)
|
|
HealBot_RenderHoTOverlays()
|
|
end
|
|
end
|
|
|
|
HealBot_Action_UpdatePlayerHoTs = HealBot_UpdateActiveHoTTimers
|