Greatly reduce garbage generation

This commit is contained in:
OldManAlpha 2025-01-07 22:55:08 -08:00
parent d0d51b1571
commit 5c7e9e443e
8 changed files with 292 additions and 181 deletions

View File

@ -59,6 +59,8 @@ end
local HM
local util = HMUtil
local compost = AceLibrary("Compost-2.0")
function HMUnitFrame:New(unit, isCustomUnit)
HM = HealersMate -- Need to do this in the constructor or else it doesn't exist yet
local obj = {unit = unit, isCustomUnit = isCustomUnit, auraIconPool = {},
@ -294,16 +296,27 @@ function HMUnitFrame:Flash()
frame:Show()
frame:SetAlpha(START_OPACITY)
if not frame:GetScript("OnUpdate") then
frame:SetScript("OnUpdate", function()
self.flashTime = self.flashTime - arg1
frame:SetAlpha(START_OPACITY - (((FLASH_TIME - self.flashTime) / FLASH_TIME) * START_OPACITY))
frame.flashTime = FLASH_TIME
frame.startOpacity = START_OPACITY
if self.flashTime <= 0 then
frame:Hide()
frame:SetScript("OnUpdate", nil)
end
end)
if not frame:GetScript("OnUpdate") then
frame:SetScript("OnUpdate", HMUnitFrame.Flash_OnUpdate)
end
end
do
function HMUnitFrame.Flash_OnUpdate()
local frame = this
local self = frame.unitFrame
local FLASH_TIME = frame.flashTime
local START_OPACITY = frame.startOpacity
self.flashTime = self.flashTime - arg1
frame:SetAlpha(START_OPACITY - (((FLASH_TIME - self.flashTime) / FLASH_TIME) * START_OPACITY))
if self.flashTime <= 0 then
frame:Hide()
frame:SetScript("OnUpdate", nil)
end
end
end
@ -530,6 +543,7 @@ function HMUnitFrame:UpdatePower()
if not UnitExists(self.unit) and not fake then
powerBar:SetValue(0)
self.powerText:SetText("")
return
end
local powerColor = fake and util.PowerColors[util.ClassPowerTypes[class or "WARRIOR"]] or util.GetPowerColor(unit)
@ -551,7 +565,7 @@ function HMUnitFrame:UpdatePower()
end
local AURA_DURATION_TEXT_FLASH_THRESHOLD = 5
local AURA_DURATION_TEXT_LOW_THRESHOLD = 10
local AURA_DURATION_TEXT_LOW_THRESHOLD = 30
-- A map of all seconds below the flash threshold to an array of colors to interpolate
local durationTextFlashColorsRange
if util.IsSuperWowPresent() then
@ -570,12 +584,19 @@ if util.IsSuperWowPresent() then
end
function HMUnitFrame:AllocateAura()
local frame = CreateFrame("Button", nil, self.auraPanel, "UIPanelButtonTemplate")
frame.unitFrame = self
frame:SetNormalTexture(nil)
frame:SetHighlightTexture(nil)
frame:SetPushedTexture(nil)
local buttons = HMOptions.CastWhen == "Mouse Up" and util.GetUpButtons() or util.GetDownButtons()
frame:RegisterForClicks(unpack(buttons))
frame:EnableMouse(true)
frame:SetScript("OnEnter", HMUnitFrame.Aura_OnEnter)
frame:SetScript("OnLeave", HMUnitFrame.Aura_OnLeave)
frame:SetScript("OnClick", HMUnitFrame.Aura_OnClick)
frame:SetScript("OnMouseUp", HMUnitFrame.Aura_OnMouseUp)
frame:SetScript("OnMouseDown", HMUnitFrame.Aura_OnMouseDown)
local icon = frame:CreateTexture(nil, "OVERLAY")
local stackText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
@ -599,8 +620,24 @@ function HMUnitFrame:AllocateAura()
self:SetFont("Fonts\\FRIZQT__.TTF", math.ceil(frame:GetHeight() *
(seconds < 540 and (seconds < 10 and 0.6 or 0.45) or 0.35)), "OUTLINE")
end
duration.UpdateText = function()
local seconds = duration.seconds
local secondsPrecise = duration.secondsPrecise
durationText:SetSeconds(seconds)
if seconds <= AURA_DURATION_TEXT_FLASH_THRESHOLD then
durationText:SetTextColor(
util.InterpolateColorsNoTable(durationTextFlashColorsRange[seconds],
secondsPrecise - seconds))
elseif seconds <= AURA_DURATION_TEXT_LOW_THRESHOLD then
durationText:SetTextColor(1, 1, 0.25)
else
durationText:SetTextColor(1, 1, 1)
end
duration:SetScript("OnUpdate", nil)
end
duration:SetScript("OnUpdateModel", function()
if this.stopping == 0 then
this:SetAlpha(0.8)
local time = GetTime()
local progress = (time - this.start) / this.duration
if progress < 1.0 then
@ -611,19 +648,9 @@ function HMUnitFrame:AllocateAura()
if durationText.seconds ~= seconds or seconds <= AURA_DURATION_TEXT_FLASH_THRESHOLD then
-- You don't want to know why it's gotta be done like this..
-- (If you're insane and you do, it's because otherwise the text will disappear for one frame otherwise)
duration:SetScript("OnUpdate", function()
durationText:SetSeconds(seconds)
if seconds <= AURA_DURATION_TEXT_FLASH_THRESHOLD then
durationText:SetTextColor(
util.InterpolateColorsNoTable(durationTextFlashColorsRange[seconds],
secondsPrecise - seconds))
elseif seconds <= AURA_DURATION_TEXT_LOW_THRESHOLD then
durationText:SetTextColor(1, 1, 0.25)
else
durationText:SetTextColor(1, 1, 1)
end
duration:SetScript("OnUpdate", nil)
end)
duration.seconds = seconds
duration.secondsPrecise = secondsPrecise
duration:SetScript("OnUpdate", duration.UpdateText)
end
elseif durationText.seconds ~= nil then
durationText:SetSeconds(nil)
@ -660,11 +687,6 @@ function HMUnitFrame:ReleaseAuras()
-- Release all icons back to the icon pool
for _, aura in ipairs(self.auraIcons) do
local frame = aura.frame
frame:SetScript("OnEnter", nil)
frame:SetScript("OnLeave", nil)
frame:SetScript("OnClick", nil)
frame:SetScript("OnMouseUp", nil)
frame:SetScript("OnMouseDown", nil)
frame:Hide()
frame:ClearAllPoints()
@ -682,7 +704,21 @@ function HMUnitFrame:ReleaseAuras()
table.insert(self.auraIconPool, aura)
end
self.auraIcons = {} -- Allocating new table instead of clearing, might be a mistake?
self.auraIcons = compost:Erase(self.auraIcons)
end
do
local trackedBuffs = HealersMateSettings.TrackedBuffs
function HMUnitFrame.BuffSorter(a, b)
return trackedBuffs[a.name] < trackedBuffs[b.name]
end
end
do
local trackedDebuffs = HealersMateSettings.TrackedDebuffs
function HMUnitFrame.DebuffSorter(a, b)
return trackedDebuffs[a.name] < trackedDebuffs[b.name]
end
end
function HMUnitFrame:UpdateAuras()
@ -704,9 +740,7 @@ function HMUnitFrame:UpdateAuras()
end
if not enemy then
table.sort(buffs, function(a, b)
return trackedBuffs[a.name] < trackedBuffs[b.name]
end)
table.sort(buffs, self.BuffSorter)
end
@ -729,9 +763,7 @@ function HMUnitFrame:UpdateAuras()
end
if not enemy then
table.sort(debuffs, function(a, b)
return trackedDebuffs[a.name] < trackedDebuffs[b.name]
end)
table.sort(debuffs, self.DebuffSorter)
util.AppendArrayElements(debuffs, typedDebuffs)
end
@ -770,12 +802,78 @@ function HMUnitFrame:UpdateAuras()
end
end
function HMUnitFrame.Aura_OnEnter()
local self = this.unitFrame
local aura = this.aura
local index = this.auraIndex
local type = this.auraType
local tooltip = HM.GameTooltip
local cache = self:GetCache()
tooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
tooltip.OwningFrame = this
tooltip.OwningIcon = aura.icon
local unit = self:GetResolvedUnit()
if type == "Buff" then
tooltip.IconTexture = cache.Buffs[index].texture
tooltip:SetUnitBuff(unit, index)
else
tooltip.IconTexture = cache.Debuffs[index].texture
tooltip:SetUnitDebuff(unit, index)
end
local auraTime = cache.AuraTimes[(type == "Buff" and cache.Buffs[index] or cache.Debuffs[index]).name]
if auraTime then
local seconds = math.floor(auraTime.startTime - GetTime() + auraTime.duration)
if seconds < 60 then
tooltip:AddLine(seconds.." second"..(seconds ~= 1 and "s" or "").." remaining")
else
tooltip:AddLine(math.ceil(seconds / 60).." minutes remaining")
end
end
tooltip:Show()
if MouseIsOver(self.button) then
self.button:GetScript("OnEnter")()
end
end
function HMUnitFrame.Aura_OnLeave()
HM.GameTooltip:Hide()
HM.GameTooltip.OwningFrame = nil
HM.GameTooltip.OwningIcon = nil
HM.GameTooltip.IconTexture = nil
-- Don't check mouse position for leaving, because it could cause the tooltip to stay if the icon is on the edge
this.unitFrame.button:GetScript("OnLeave")()
end
do
local wrapButtonScript = function(scriptName)
return function()
local self = this.unitFrame
if MouseIsOver(self.button) then
self.button:GetScript(scriptName)()
end
end
end
HMUnitFrame.Aura_OnClick = wrapButtonScript("OnClick")
HMUnitFrame.Aura_OnMouseUp = wrapButtonScript("OnMouseUp")
HMUnitFrame.Aura_OnMouseDown = wrapButtonScript("OnMouseDown")
end
function HMUnitFrame:CreateAura(aura, name, index, texturePath, stacks, xOffset, yOffset, type, size)
local frame = aura.frame
frame:SetWidth(size)
frame:SetHeight(size)
frame:SetPoint(type == "Buff" and "TOPLEFT" or "TOPRIGHT", xOffset, yOffset)
frame:Show()
frame.unitFrame = self
frame.aura = aura
frame.auraIndex = index
frame.auraType = type
local icon = aura.icon
icon:SetAllPoints(frame)
@ -790,58 +888,6 @@ function HMUnitFrame:CreateAura(aura, name, index, texturePath, stacks, xOffset,
duration:SetAllPoints()
duration:SetScale(size * 0.0275)
end
-- Creates a function that checks if the mouse is over the UI's button and calls the script if so
local wrapScript = function(scriptName)
return function()
if MouseIsOver(self.button) then
self.button:GetScript(scriptName)()
end
end
end
frame:SetScript("OnEnter", function()
local tooltip = HM.GameTooltip
local cache = self:GetCache()
tooltip:SetOwner(frame, "ANCHOR_BOTTOMLEFT")
tooltip.OwningFrame = frame
tooltip.OwningIcon = icon
local unit = self:GetResolvedUnit()
if type == "Buff" then
tooltip.IconTexture = cache.Buffs[index].texture
tooltip:SetUnitBuff(unit, index)
else
tooltip.IconTexture = cache.Debuffs[index].texture
tooltip:SetUnitDebuff(unit, index)
end
local auraTime = cache.AuraTimes[(type == "Buff" and cache.Buffs[index] or cache.Debuffs[index]).name]
if auraTime then
local seconds = math.floor(auraTime.startTime - GetTime() + auraTime.duration)
if seconds < 60 then
tooltip:AddLine(seconds.." second"..(seconds ~= 1 and "s" or "").." remaining")
else
tooltip:AddLine(math.ceil(seconds / 60).." minutes remaining")
end
end
tooltip:Show()
wrapScript("OnEnter")()
end)
frame:SetScript("OnLeave", function()
HM.GameTooltip:Hide()
HM.GameTooltip.OwningFrame = nil
HM.GameTooltip.OwningIcon = nil
HM.GameTooltip.IconTexture = nil
-- Don't check mouse position for leaving, because it could cause the tooltip to stay if the icon is on the edge
self.button:GetScript("OnLeave")()
end)
frame:SetScript("OnClick", wrapScript("OnClick"))
frame:SetScript("OnMouseUp", wrapScript("OnMouseUp"))
frame:SetScript("OnMouseDown", wrapScript("OnMouseDown"))
if stacks > 1 then
local stackText = aura.stackText
@ -1002,13 +1048,14 @@ function HMUnitFrame:Initialize()
end
incomingHealthBar:SetAlpha(0.35)
incomingDirectHealthBar:SetAlpha(0.4)
local rgb
local r, g, b
local enemy = self:IsEnemy()
if not enemy then -- Do not display debuff colors for enemies
for _, trackedDebuffType in ipairs(HealersMateSettings.TrackedDebuffTypes) do
if self:GetAfflictedDebuffTypes()[trackedDebuffType] then
rgb = HealersMateSettings.DebuffTypeColors[trackedDebuffType]
local debuffTypeColor = HealersMateSettings.DebuffTypeColors[trackedDebuffType]
r, g, b = debuffTypeColor[1], debuffTypeColor[2], debuffTypeColor[3]
break
end
end
@ -1016,34 +1063,32 @@ function HMUnitFrame:Initialize()
local fake = self:IsFake()
if fake and self.fakeStats.debuffType then
rgb = HealersMateSettings.DebuffTypeColors[self.fakeStats.debuffType]
local debuffTypeColor = HealersMateSettings.DebuffTypeColors[self.fakeStats.debuffType]
r, g, b = debuffTypeColor[1], debuffTypeColor[2], debuffTypeColor[3]
end
if rgb == nil then -- If there's no debuff color, proceed to normal colors
if r == nil then -- If there's no debuff color, proceed to normal colors
local hbc = enemy and profile.EnemyHealthBarColor or profile.HealthBarColor
if hbc == "Class" then
local class = util.GetClass(unit)
if class == nil then
class = self.fakeStats.class
end
local r, g, b = util.GetClassColor(class)
rgb = {r, g, b}
r, g, b = util.GetClassColor(class)
elseif hbc == "Green" then
rgb = {0, 0.8, 0}
r, g, b = 0, 0.8, 0
elseif hbc == "Green To Red" then
rgb = util.InterpolateColors(greenToRedColors, value)
r, g, b = util.InterpolateColorsNoTable(greenToRedColors, value)
end
if healthIncMaxRatio > 1 then
local prevRgb = rgb
rgb = {}
local brightenFactor = math.min(((healthIncMaxRatio - 1) / 4) + 1, 1.25)
for i = 1, 3 do
rgb[i] = math.min(prevRgb[i] * brightenFactor, 1)
end
r = math.min(r * brightenFactor, 1)
g = math.min(g * brightenFactor, 1)
b = math.min(b * brightenFactor, 1)
end
end
healthBar:SetStatusBarColor(rgb[1], rgb[2], rgb[3])
healthBar:SetStatusBarColor(r, g, b)
incomingHealthBar:SetStatusBarColor(0, 0.8, 0)
incomingDirectHealthBar:SetStatusBarColor(0, 0.8, 0)
@ -1146,6 +1191,7 @@ function HMUnitFrame:Initialize()
local flashFrame = CreateFrame("Frame", "$parentFlash", container)
flashFrame:SetFrameLevel(container:GetFrameLevel() + 9)
flashFrame.unitFrame = self
local flashTexture = flashFrame:CreateTexture(nil, "OVERLAY")
self.flashTexture = {frame = flashFrame, texture = flashTexture}
flashTexture:SetTexture(1, 1, 1)

View File

@ -361,18 +361,23 @@ function GetRaidPartyMembers(partyNumberOrUnit)
partyNumberOrUnit = FindUnitRaidGroup(partyNumberOrUnit)
end
local members = {}
for frameNumber, raidNumber in pairs(RAID_SUBGROUP_LISTS[partyNumberOrUnit]) do
table.insert(members, "raid"..raidNumber)
if RAID_SUBGROUP_LISTS[partyNumberOrUnit] then
for frameNumber, raidNumber in pairs(RAID_SUBGROUP_LISTS[partyNumberOrUnit]) do
table.insert(members, RaidUnits[raidNumber])
end
end
return members
end
-- Returns the raid unit that this unit is, or nil if the unit is not in the raid
function FindRaidUnit(unit)
if not RAID_SUBGROUP_LISTS then
return {}
end
for party = 1, 8 do
if RAID_SUBGROUP_LISTS[party] then
for frameNumber, raidNumber in pairs(RAID_SUBGROUP_LISTS[party]) do
local raidUnit = "raid"..raidNumber
local raidUnit = RaidUnits[raidNumber]
if UnitIsUnit(unit, raidUnit) then
return raidUnit
end
@ -386,7 +391,7 @@ function FindUnitRaidGroup(unit)
for party = 1, 8 do
if RAID_SUBGROUP_LISTS[party] then
for frameNumber, raidNumber in pairs(RAID_SUBGROUP_LISTS[party]) do
local raidUnit = "raid"..raidNumber
local raidUnit = RaidUnits[raidNumber]
if UnitIsUnit(unit, raidUnit) then
return party
end
@ -496,25 +501,33 @@ function GetKeyModifiers()
return keyModifiers
end
-- L1: Shift
-- L2: Control
-- L3: Alt
local keyModifierMap = {
[true] = {
[true] = {
[true] = "Shift+Control+Alt",
[false] = "Shift+Control"
},
[false] = {
[true] = "Shift+Alt",
[false] = "Shift"
}
},
[false] = {
[true] = {
[true] = "Control+Alt",
[false] = "Control"
},
[false] = {
[true] = "Alt",
[false] = "None"
}
}
}
function GetKeyModifier()
local modifier = IsShiftKeyDown() and "Shift" or ""
if IsControlKeyDown() then
if modifier ~= "" then
modifier = modifier.."+"
end
modifier = modifier.."Control"
end
if IsAltKeyDown() then
if modifier ~= "" then
modifier = modifier.."+"
end
modifier = modifier.."Alt"
end
if modifier == "" then
return "None"
end
return modifier
return keyModifierMap[IsShiftKeyDown() == 1][IsControlKeyDown() == 1][IsAltKeyDown() == 1]
end
local buttons = {"LeftButton", "MiddleButton", "RightButton", "Button4", "Button5"}

View File

@ -22,11 +22,11 @@ libs\ace\Banzai-1.0\Banzai-1.0.lua
libs\UnitProxy.lua
HMUtil.lua
Settings.lua
HMUnitFrame.lua
HMUnitFrameGroup.lua
Profile.lua
ProfileManager.lua
Settings.lua
libs\GuidRoster.lua
libs\AuraTracker.lua

View File

@ -104,7 +104,7 @@ function HealersMateSettings.SetDefaults()
["Raid"] = "Compact (Small)",
["Raid Pets"] = "Compact (Small)",
["Target"] = "Long",
["Focus"] = "Long"
["Focus"] = "Compact"
},
["OptionsVersion"] = 1
}

View File

@ -10,6 +10,8 @@ local _G = getfenv(0)
setmetatable(HMGuidRoster, {__index = getfenv(1)})
setfenv(1, HMGuidRoster)
local compost = AceLibrary("Compost-2.0")
HMUnitProxy.ImportFunctions(HMGuidRoster)
local util = HMUtil
@ -19,7 +21,8 @@ GuidFrameMap = {}
function ResetRoster()
local roster = GuidUnitMap
for k, _ in pairs(roster) do
for k, v in pairs(roster) do
compost:Reclaim(v)
roster[k] = nil
end
end
@ -38,7 +41,7 @@ end
function AddUnit(guid, unit)
if not GuidUnitMap[guid] then
GuidUnitMap[guid] = {}
GuidUnitMap[guid] = compost:GetTable()
end
table.insert(GuidUnitMap[guid], unit)
end
@ -48,6 +51,7 @@ function SetUnitGuid(unit, guid)
if util.ArrayContains(units, unit) then
util.RemoveElement(units, unit)
if table.getn(units) == 0 then
compost:Reclaim(units)
GuidUnitMap[guidInMap] = nil
end
break
@ -59,7 +63,7 @@ function SetUnitGuid(unit, guid)
end
if not GuidUnitMap[guid] then
GuidUnitMap[guid] = {}
GuidUnitMap[guid] = compost:GetTable()
end
table.insert(GuidUnitMap[guid], unit)
end

View File

@ -6,6 +6,8 @@ local AllUnits = HMUtil.AllUnits
local AllUnitsSet = HMUtil.AllUnitsSet
local util = HMUtil
local compost = AceLibrary("Compost-2.0")
HMUnit = {}
-- Non-instance variable
@ -100,6 +102,7 @@ function HMUnit:New(unit)
setmetatable(obj, self)
self.__index = self
HMUnit.Cached[unit] = obj
obj:AllocateAuras()
obj.AurasPopulated = true -- To force aura fields to generate
obj.IsNew = true
if USE_GUIDS then
@ -150,16 +153,31 @@ function HMUnit:IsInSight()
return self.InSight
end
function HMUnit:AllocateAuras()
self.Buffs = compost:GetTable()
self.BuffsMap = compost:GetTable()
self.Debuffs = compost:GetTable()
self.DebuffsMap = compost:GetTable()
self.TypedDebuffs = compost:GetTable()
self.AfflictedDebuffTypes = compost:GetTable()
end
function HMUnit:ClearAuras()
if not self.AurasPopulated then
if not self.AurasPopulated or self.Buffs == HMUnit.Buffs then
return
end
self.Buffs = {}
self.BuffsMap = {}
self.Debuffs = {}
self.DebuffsMap = {}
self.TypedDebuffs = {}
self.AfflictedDebuffTypes = {}
compost:Reclaim(self.Buffs, 1)
compost:Reclaim(self.BuffsMap, 1)
compost:Reclaim(self.Debuffs, 1)
compost:Reclaim(self.DebuffsMap, 1)
compost:Reclaim(self.TypedDebuffs)
compost:Reclaim(self.AfflictedDebuffTypes)
self.Buffs = compost:GetTable()
self.BuffsMap = compost:GetTable()
self.Debuffs = compost:GetTable()
self.DebuffsMap = compost:GetTable()
self.TypedDebuffs = compost:GetTable()
self.AfflictedDebuffTypes = compost:GetTable()
self.HasHealingModifier = false
self.AurasPopulated = false
end
@ -187,9 +205,9 @@ function HMUnit:UpdateAuras()
if HealersMateSettings.TrackedHealingBuffs[name] then
self.HasHealingModifier = true
end
local buff = {name = name, index = index, texture = texture, stacks = stacks, type = type, id = id}
local buff = compost:AcquireHash("name", name, "index", index, "texture", texture, "stacks", stacks, "type", type, "id", id)
if not buffsMap[name] then
buffsMap[name] = {}
buffsMap[name] = compost:GetTable()
end
table.insert(buffsMap[name], buff)
table.insert(buffs, buff)
@ -210,15 +228,16 @@ function HMUnit:UpdateAuras()
if HealersMateSettings.TrackedHealingDebuffs[name] then
self.HasHealingModifier = true
end
local debuff = {name = name, index = index, texture = texture, stacks = stacks, type = type, id = id}
local debuff = compost:AcquireHash("name", name, "index", index, "texture", texture, "stacks", stacks, "type", type, "id", id)
--local debuff = {name = name, index = index, texture = texture, stacks = stacks, type = type, id = id}
if not debuffsMap[name] then
debuffsMap[name] = {}
debuffsMap[name] = compost:GetTable()
end
table.insert(debuffsMap[name], debuff)
if type ~= "" then
afflictedDebuffTypes[type] = 1
if not typedDebuffs[type] then
typedDebuffs[type] = {}
typedDebuffs[type] = compost:GetTable()
end
table.insert(typedDebuffs[type], debuff)
end

View File

@ -11,6 +11,8 @@ local _G = getfenv(0)
setmetatable(HMHealPredict, {__index = getfenv(1)})
setfenv(1, HMHealPredict)
local compost = AceLibrary("Compost-2.0")
RelevantGUIDs = {} -- A set of GUIDs to listen to
IncomingHeals = {} -- Key: Receiver | Value: List of incoming casts
@ -125,10 +127,10 @@ end
-- Used for Prayer of Healing to add incoming healing to multiple players
function AddIncomingMultiCast(targets, caster, spellID, healAmount, castTime)
Casts[caster] = {
["targets"] = targets,
["spellID"] = spellID
}
Casts[caster] = compost:AcquireHash(
"targets", targets,
"spellID", spellID
)
for _, target in ipairs(targets) do
AddIncomingCast(target, caster, spellID, healAmount, castTime, true)
end
@ -136,22 +138,22 @@ end
function AddIncomingCast(target, caster, spellID, healAmount, castTime, multi)
if not multi then
Casts[caster] = {
["targets"] = {target},
["spellID"] = spellID
}
Casts[caster] = compost:AcquireHash(
"targets", compost:Acquire(target),
"spellID", spellID
)
end
local targetTable = IncomingHeals[target]
if not targetTable then
targetTable = {}
IncomingHeals[target] = targetTable
end
targetTable[caster] = {
["spellID"] = spellID,
["heal"] = healAmount,
["castTime"] = castTime,
["startTime"] = GetTime()
}
targetTable[caster] = compost:AcquireHash(
"spellID", spellID,
"heal", healAmount,
"castTime", castTime,
"startTime", GetTime()
)
UpdateTarget(target)
end
@ -161,9 +163,11 @@ function RemoveIncomingCast(caster)
if cast then
for _, target in ipairs(cast["targets"]) do
local incomingHeals = IncomingHeals[target]
compost:Reclaim(incomingHeals[caster])
incomingHeals[caster] = nil
UpdateTarget(target)
end
compost:Reclaim(cast)
Casts[caster] = nil
end
end
@ -176,12 +180,12 @@ function GetCurrentCast(caster)
end
function AddHot(target, caster, spellID, spellName, healAmount)
local hot = {
["caster"] = caster,
["id"] = spellID,
["heal"] = healAmount,
["startTime"] = GetTime()
}
local hot = compost:AcquireHash(
"caster", caster,
"id", spellID,
"heal", healAmount,
"startTime", GetTime()
)
local targetTable = IncomingHots[target]
if not targetTable then
targetTable = {}
@ -297,6 +301,7 @@ function RemoveHoT(spellName, targetGuid)
if hot["startTime"] + 0.5 > GetTime() and not hot["swiftmend"] then
return
end
compost:Reclaim(hot)
IncomingHots[targetGuid][spellName] = nil
UpdateTarget(targetGuid)
end
@ -373,7 +378,7 @@ eventFrame:SetScript("OnEvent", function()
end
if TRACKED_HOTS[spellName] then
if spellName == "Mend Pet" then -- Mend pet doesn't "target" the pet, so we have to aquire the pet
if spellName == "Mend Pet" then -- Mend pet doesn't "target" the pet, so we have to acquire the pet
local units = HMGuidRoster.GetUnits(caster)
if not units then
return
@ -430,6 +435,7 @@ eventFrame:SetScript("OnUpdate", function()
for caster, cast in pairs(casts) do
if cast["startTime"] + 15 < time then
hmprint(colorize("Removed "..caster.."'s heal on "..receiver.." for taking too long", 1, 0, 0))
compost:Reclaim(cast)
casts[caster] = nil
UpdateTarget(receiver)
end
@ -441,6 +447,7 @@ eventFrame:SetScript("OnUpdate", function()
if hot["startTime"] + 25 < time then
hmprint(colorize("Removed "..hot["caster"].."'s "..name.." (HoT) on "..
receiver.." for taking too long", 1, 0, 0))
compost:Reclaim(hot)
hots[name] = nil
UpdateTarget(receiver)
end

View File

@ -11,6 +11,8 @@ local _G = getfenv(0)
setmetatable(HMUnitProxy, {__index = getfenv(1)})
setfenv(1, HMUnitProxy)
local compost = AceLibrary("Compost-2.0")
-- Unit data
CustomUnitTypes = {} -- Array of custom unit types(ex: "focus")
@ -74,7 +76,7 @@ UnitFunctions = {}
function UpdateUnitTypeFrames(unitType)
local groups = {}
local groups = compost:GetTable()
for _, unit in ipairs(CustomUnitsMap[unitType]) do
local guid = CustomUnitGUIDMap[unit]
for ui in HealersMate.UnitFrames(unit) do
@ -94,10 +96,11 @@ function UpdateUnitTypeFrames(unitType)
for group, _ in pairs(groups) do
group:EvaluateShown()
end
compost:Reclaim(groups)
end
function UpdateUnitFrames(unit)
local groups = {}
local groups = compost:GetTable()
local guid = CustomUnitGUIDMap[unit]
for ui in HealersMate.UnitFrames(unit) do
if guid then
@ -114,6 +117,7 @@ function UpdateUnitFrames(unit)
for group, _ in pairs(groups) do
group:EvaluateShown()
end
compost:Reclaim(groups)
end
function GetCurrentUnitOfType(guid, unitType)
@ -140,7 +144,7 @@ function SetCustomUnitGuid(unit, guid, skipUpdate)
CustomUnitGUIDMap[unit] = guid
local unitArray = GUIDCustomUnitMap[guid]
if not unitArray then
unitArray = {}
unitArray = compost:GetTable()
GUIDCustomUnitMap[guid] = unitArray
end
table.insert(unitArray, unit)
@ -156,6 +160,7 @@ function SetCustomUnitGuid(unit, guid, skipUpdate)
CustomUnitGUIDMap[unit] = nil
local unitArray = GUIDCustomUnitMap[guid]
if table.getn(unitArray) == 1 then
compost:Reclaim(unitArray)
GUIDCustomUnitMap[guid] = nil
else
HMUtil.RemoveElement(unitArray, unit)
@ -213,21 +218,22 @@ function PromoteGuidUnitType(guid, unitType)
SetCustomUnitGuid(unit, nil)
-- Remove all units before this unit
local reaquire = {}
local reacquire = compost:GetTable()
for i = 1, index do
local moveUnit = units[i]
if CustomUnitGUIDMap[moveUnit] then
local moveGuid = CustomUnitGUIDMap[moveUnit]
SetCustomUnitGuid(moveUnit, nil, true)
table.insert(reaquire, moveGuid)
table.insert(reacquire, moveGuid)
end
end
-- Set the promotion first so they get the first spot
SetGuidUnitType(guid, unitType, true)
-- Reaquire the removed units
for _, reaquireGuid in ipairs(reaquire) do
SetGuidUnitType(reaquireGuid, unitType, true)
-- Reacquire the removed units
for _, reacquireGuid in ipairs(reacquire) do
SetGuidUnitType(reacquireGuid, unitType, true)
end
compost:Reclaim(reacquire)
UpdateUnitTypeFrames(unitType)
end
@ -420,21 +426,37 @@ function CreateUnitProxies()
-- UnitXP SP3 compatibility
CustomProxy("UnitXP", function()
local UnitXP = _G.UnitXP
return function(...)
local args = arg
for i = 1, table.getn(args) do
local arg = args[i]
if AllCustomUnitsSet[arg] then
args[i] = CustomUnitGUIDMap[arg]
if not args[i] then
return 0
end
end
local function ScanArg(arg)
if AllCustomUnitsSet[arg] then
return CustomUnitGUIDMap[arg]
end
return UnitXP(unpack(args))
return arg
end
return function(a1, a2, a3, a4, a5)
if a1 then
a1 = ScanArg(a1)
if not a1 then return 0 end
end
if a2 then
a2 = ScanArg(a2)
if not a2 then return 0 end
end
if a3 then
a3 = ScanArg(a3)
if not a3 then return 0 end
end
if a4 then
a4 = ScanArg(a4)
if not a4 then return 0 end
end
if a5 then
a5 = ScanArg(a5)
if not a5 then return 0 end
end
return UnitXP(a1, a2, a3, a4, a5)
end
end)
UpdateImports()
end