mirror of
https://github.com/OldManAlpha/Puppeteer.git
synced 2025-11-28 23:48:35 +00:00
836 lines
28 KiB
Lua
836 lines
28 KiB
Lua
Puppeteer = {}
|
|
PTUtil.SetEnvironment(Puppeteer)
|
|
local _G = getfenv(0)
|
|
_G.PuppeteerLib = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0")
|
|
|
|
VERSION = GetAddOnMetadata("Puppeteer", "version")
|
|
|
|
TestUI = false
|
|
|
|
Banzai = AceLibrary("Banzai-1.0")
|
|
HealComm = AceLibrary("HealComm-1.0")
|
|
GuidRoster = nil -- Will be nil if SuperWoW isn't present
|
|
|
|
local compost = AceLibrary("Compost-2.0")
|
|
local util = PTUtil
|
|
local colorize = util.Colorize
|
|
local GetKeyModifier = util.GetKeyModifier
|
|
local GetClass = util.GetClass
|
|
local GetPowerType = util.GetPowerType
|
|
local UseItem = util.UseItem
|
|
local GetItemCount = util.GetItemCount
|
|
|
|
PartyUnits = util.PartyUnits
|
|
PetUnits = util.PetUnits
|
|
TargetUnits = util.TargetUnits
|
|
RaidUnits = util.RaidUnits
|
|
RaidPetUnits = util.RaidPetUnits
|
|
AllUnits = util.AllUnits
|
|
AllUnitsSet = util.AllUnitsSet
|
|
AllCustomUnits = util.CustomUnits
|
|
AllCustomUnitsSet = util.CustomUnitsSet
|
|
|
|
ReadableButtonMap = {
|
|
["LeftButton"] = "Left",
|
|
["MiddleButton"] = "Middle",
|
|
["RightButton"] = "Right",
|
|
["Button4"] = "Button 4",
|
|
["Button5"] = "Button 5"
|
|
}
|
|
|
|
ResurrectionSpells = {
|
|
["PRIEST"] = "Resurrection",
|
|
["PALADIN"] = "Redemption",
|
|
["SHAMAN"] = "Ancestral Spirit",
|
|
["DRUID"] = "Rebirth"
|
|
}
|
|
|
|
local ptBarsPath = util.GetAssetsPath().."textures\\bars\\"
|
|
BarStyles = {
|
|
["Blizzard"] = "Interface\\TargetingFrame\\UI-StatusBar",
|
|
["Blizzard Smooth"] = ptBarsPath.."Blizzard-Smooth",
|
|
["Blizzard Raid"] = ptBarsPath.."Blizzard-Raid",
|
|
["Blizzard Raid Sideless"] = ptBarsPath.."Blizzard-Raid-Sideless",
|
|
["Puppeteer"] = ptBarsPath.."Puppeteer",
|
|
["Puppeteer Borderless"] = ptBarsPath.."Puppeteer-Borderless",
|
|
["Puppeteer Shineless"] = ptBarsPath.."Puppeteer-Shineless",
|
|
["Puppeteer Shineless Borderless"] = ptBarsPath.."Puppeteer-Shineless-Borderless"
|
|
}
|
|
|
|
GameTooltip = CreateFrame("GameTooltip", "PTGameTooltip", UIParent, "GameTooltipTemplate")
|
|
|
|
CurrentlyHeldButton = nil
|
|
|
|
-- An unmapped array of all unit frames
|
|
AllUnitFrames = {}
|
|
-- A map of units to an array of unit frames associated with the unit
|
|
PTUnitFrames = {}
|
|
|
|
-- Key: Unit frame group name | Value: The group
|
|
UnitFrameGroups = {}
|
|
|
|
CustomUnitGUIDMap = PTUnitProxy and PTUnitProxy.CustomUnitGUIDMap or {}
|
|
GUIDCustomUnitMap = PTUnitProxy and PTUnitProxy.GUIDCustomUnitMap or {}
|
|
|
|
|
|
CurrentlyInRaid = false
|
|
|
|
Mouseover = nil
|
|
|
|
-- Returns the array of unit frames of the unit
|
|
function GetUnitFrames(unit)
|
|
return PTUnitFrames[unit]
|
|
end
|
|
|
|
-- A temporary dummy function while the addon initializes. See below for the real iterator.
|
|
function UnitFrames(unit)
|
|
return function() end
|
|
end
|
|
|
|
local function OpenUnitFramesIterator()
|
|
-- UnitFrames function definition.
|
|
-- Returns an iterator for the unit frames of the unit.
|
|
-- These iterators have a serious problem in that they do not support concurrent iteration.
|
|
if util.IsSuperWowPresent() then
|
|
local EMPTY_UIS = {}
|
|
local PTUnitFrames = PTUnitFrames
|
|
local GuidUnitMap = PTGuidRoster.GuidUnitMap
|
|
local iterTable = {} -- The table reused for iteration over GUID units
|
|
local uis
|
|
local i = 0
|
|
local len = 0
|
|
local iterFunc = function()
|
|
i = i + 1
|
|
if i <= len then
|
|
return uis[i]
|
|
end
|
|
end
|
|
function UnitFrames(unit)
|
|
if i < len then
|
|
print("Collision: "..i.."/"..len)
|
|
end
|
|
if GuidUnitMap[unit] then -- If a GUID is provided, ALL UIs associated with that GUID will be iterated
|
|
uis = iterTable
|
|
for i = 1, table.getn(uis) do
|
|
uis[i] = nil
|
|
end
|
|
table.setn(uis, 0)
|
|
for _, unit in pairs(GuidUnitMap[unit]) do
|
|
for _, frame in ipairs(PTUnitFrames[unit]) do
|
|
table.insert(uis, frame)
|
|
end
|
|
end
|
|
else
|
|
uis = PTUnitFrames[unit] or EMPTY_UIS
|
|
end
|
|
len = table.getn(uis)
|
|
i = 0
|
|
return iterFunc
|
|
end
|
|
else -- Optimized version for vanilla
|
|
local PTUnitFrames = PTUnitFrames
|
|
local uis
|
|
local i = 0
|
|
local len = 0
|
|
local iterFunc = function()
|
|
i = i + 1
|
|
if i <= len then
|
|
return uis[i]
|
|
end
|
|
end
|
|
function UnitFrames(unit)
|
|
i = 0
|
|
uis = PTUnitFrames[unit]
|
|
len = table.getn(uis)
|
|
return iterFunc
|
|
end
|
|
end
|
|
end
|
|
|
|
function Debug(msg)
|
|
DEFAULT_CHAT_FRAME:AddMessage(msg)
|
|
end
|
|
|
|
function UpdateUnitFrameGroups()
|
|
for _, group in pairs(UnitFrameGroups) do
|
|
group:UpdateUIPositions()
|
|
end
|
|
end
|
|
|
|
function UpdateAllIncomingHealing()
|
|
if PTHealPredict then
|
|
for _, ui in ipairs(AllUnitFrames) do
|
|
if PTOptions.UseHealPredictions then
|
|
local _, guid = UnitExists(ui:GetUnit())
|
|
ui:SetIncomingHealing(PTHealPredict.GetIncomingHealing(guid))
|
|
else
|
|
ui:SetIncomingHealing(0)
|
|
end
|
|
end
|
|
else
|
|
for _, ui in ipairs(AllUnitFrames) do
|
|
if PTOptions.UseHealPredictions then
|
|
ui:UpdateIncomingHealing()
|
|
else
|
|
ui:SetIncomingHealing(0)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function UpdateAllOutlines()
|
|
for _, ui in ipairs(AllUnitFrames) do
|
|
ui:UpdateOutline()
|
|
end
|
|
end
|
|
|
|
function CreateUnitFrameGroup(groupName, environment, units, petGroup, profile, sortByRole)
|
|
if UnitFrameGroups[groupName] then
|
|
error("[Puppeteer] Tried to create a unit frame group using existing name! \""..groupName.."\"")
|
|
return
|
|
end
|
|
local uiGroup = PTUnitFrameGroup:New(groupName, environment, units, petGroup, profile, sortByRole)
|
|
for _, unit in ipairs(units) do
|
|
local ui = PTUnitFrame:New(unit, AllCustomUnitsSet[unit] ~= nil)
|
|
if not PTUnitFrames[unit] then
|
|
PTUnitFrames[unit] = {}
|
|
end
|
|
table.insert(PTUnitFrames[unit], ui)
|
|
table.insert(AllUnitFrames, ui)
|
|
uiGroup:AddUI(ui)
|
|
if unit ~= "target" then
|
|
ui:Hide()
|
|
end
|
|
end
|
|
UnitFrameGroups[groupName] = uiGroup
|
|
return uiGroup
|
|
end
|
|
|
|
local function initUnitFrames()
|
|
local getSelectedProfile = PuppeteerSettings.GetSelectedProfile
|
|
CreateUnitFrameGroup("Party", "party", PartyUnits, false, getSelectedProfile("Party"))
|
|
CreateUnitFrameGroup("Pets", "party", PetUnits, true, getSelectedProfile("Pets"))
|
|
CreateUnitFrameGroup("Raid", "raid", RaidUnits, false, getSelectedProfile("Raid"))
|
|
CreateUnitFrameGroup("Raid Pets", "raid", RaidPetUnits, true, getSelectedProfile("Raid Pets"))
|
|
CreateUnitFrameGroup("Target", "all", TargetUnits, false, getSelectedProfile("Target"), false)
|
|
if util.IsSuperWowPresent() then
|
|
CreateUnitFrameGroup("Focus", "all", PTUnitProxy.CustomUnitsMap["focus"], false, getSelectedProfile("Focus"), false)
|
|
end
|
|
|
|
local baseCondition = UnitFrameGroups["Target"].ShowCondition
|
|
UnitFrameGroups["Target"].ShowCondition = function(self)
|
|
local friendly = not UnitCanAttack("player", "target")
|
|
return (PTOptions.AlwaysShowTargetFrame or (UnitExists("target") and
|
|
(friendly and PTOptions.ShowTargets.Friendly) or (not friendly and PTOptions.ShowTargets.Hostile)))
|
|
and baseCondition(self)
|
|
end
|
|
|
|
OpenUnitFramesIterator()
|
|
end
|
|
|
|
function OnAddonLoaded()
|
|
StartTiming("OnLoad")
|
|
|
|
if PTBindings == nil then
|
|
-- Create default bindings
|
|
_G.PTBindings = {}
|
|
PTBindings["SelectedLoadout"] = "Default"
|
|
local loadouts = {}
|
|
PTBindings["Loadouts"] = loadouts
|
|
loadouts["Default"] = CreateEmptyBindingsLoadout()
|
|
|
|
local friendlyOrHostile = "Friendly"
|
|
local modifier
|
|
local function setContext(a, b)
|
|
friendlyOrHostile = a
|
|
modifier = b
|
|
end
|
|
local function setBinding(button, binding)
|
|
local bindings = GetBindings()
|
|
local l1 = bindings.Bindings[friendlyOrHostile]
|
|
if not l1 then
|
|
l1 = {}
|
|
bindings.Bindings[friendlyOrHostile] = l1
|
|
end
|
|
local l2 = l1[modifier]
|
|
if not l2 then
|
|
l2 = {}
|
|
l1[modifier] = l2
|
|
end
|
|
l2[button] = binding
|
|
end
|
|
local function setSpell(button, spell)
|
|
setBinding(button, {Type = "SPELL", Data = spell})
|
|
end
|
|
local function setBestSpell(button, spells)
|
|
local selected
|
|
for _, spell in ipairs(spells) do
|
|
if util.GetSpellID(spell) then
|
|
selected = spell
|
|
break
|
|
end
|
|
end
|
|
if not selected then
|
|
return
|
|
end
|
|
setSpell(button, selected)
|
|
end
|
|
local function setMulti(button, tooltip, spells)
|
|
local bindings = {}
|
|
for i, spell in ipairs(spells) do
|
|
bindings[i] = {Type = "SPELL", Data = spell}
|
|
end
|
|
setBinding(button, {
|
|
Type = "MULTI",
|
|
Tooltip = {
|
|
Type = "CUSTOM",
|
|
Data = tooltip
|
|
},
|
|
Data = {
|
|
Bindings = bindings
|
|
}
|
|
})
|
|
end
|
|
local function setAction(button, action)
|
|
setBinding(button, {Type = "ACTION", Data = action})
|
|
end
|
|
local function addHealerControls()
|
|
setContext("Friendly", "Shift")
|
|
setAction("LeftButton", "Target")
|
|
setAction("MiddleButton", "Role")
|
|
setAction("RightButton", "Menu")
|
|
end
|
|
|
|
local class = GetClass("player")
|
|
if class == "PRIEST" then
|
|
setContext("Friendly", "None")
|
|
setSpell("LeftButton", "Power Word: Shield")
|
|
setSpell("MiddleButton", "Renew")
|
|
setBestSpell("RightButton", {"Greater Heal", "Heal", "Lesser Heal"})
|
|
|
|
addHealerControls()
|
|
|
|
setContext("Friendly", "Control")
|
|
setMulti("LeftButton", "Buffs", {"Power Word: Fortitude", "Divine Spirit", "Shadow Protection"})
|
|
setBinding("RightButton", "Dispel Magic")
|
|
|
|
setContext("Hostile", "None")
|
|
setSpell("RightButton", "Dispel Magic")
|
|
|
|
setContext("Hostile", "Control")
|
|
setSpell("RightButton", "Dispel Magic")
|
|
elseif class == "DRUID" then
|
|
setContext("Friendly", "None")
|
|
setSpell("LeftButton", "Rejuvenation")
|
|
setSpell("RightButton", "Healing Touch")
|
|
|
|
addHealerControls()
|
|
|
|
setContext("Friendly", "Control")
|
|
setSpell("RightButton", "Remove Curse")
|
|
elseif class == "PALADIN" then
|
|
setContext("Friendly", "None")
|
|
setSpell("LeftButton", "Flash of Light")
|
|
setSpell("RightButton", "Holy Light")
|
|
|
|
addHealerControls()
|
|
|
|
setContext("Friendly", "Control")
|
|
setMulti("LeftButton", "Blessings", {"Blessing of Might", "Blessing of Wisdom", "Blessing of Salvation", "Blessing of Kings"})
|
|
setBestSpell("RightButton", {"Cleanse", "Purify"})
|
|
elseif class == "SHAMAN" then
|
|
setContext("Friendly", "None")
|
|
setBestSpell("LeftButton", {"Healing Wave", "Lesser Healing Wave"})
|
|
setSpell("RightButton", "Chain Heal")
|
|
|
|
addHealerControls()
|
|
|
|
setContext("Friendly", "Control")
|
|
setSpell("RightButton", "Cure Disease")
|
|
else
|
|
-- Non-healer classes can use this addon like traditional raid frames
|
|
setContext("Friendly", "None")
|
|
setAction("LeftButton", "Target")
|
|
setAction("MiddleButton", "Role")
|
|
setAction("RightButton", "Menu")
|
|
|
|
setContext("Hostile", "None")
|
|
setAction("LeftButton", "Target")
|
|
setAction("RightButton", "Menu")
|
|
end
|
|
end
|
|
|
|
PuppeteerSettings.SetDefaults()
|
|
|
|
InitOverrideBindingsMapping()
|
|
InitBindingDisplayCache()
|
|
|
|
if util.IsSuperWowPresent() then
|
|
-- In case other addons override unit functions, we want to make sure we're using their functions
|
|
PTUnitProxy.CreateUnitProxies()
|
|
|
|
-- Do it again after all addons have loaded
|
|
local frame = CreateFrame("Frame")
|
|
local reapply = GetTime() + 0.1
|
|
frame:SetScript("OnUpdate", function()
|
|
if GetTime() > reapply then
|
|
PTUnitProxy.CreateUnitProxies()
|
|
frame:SetScript("OnUpdate", nil)
|
|
end
|
|
end)
|
|
end
|
|
|
|
if not _G.PTRoleCache then
|
|
_G.PTRoleCache = {}
|
|
end
|
|
if not _G.PTRoleCache[GetRealmName()] then
|
|
_G.PTRoleCache[GetRealmName()] = {}
|
|
end
|
|
AssignedRoles = _G.PTRoleCache[GetRealmName()]
|
|
PruneAssignedRoles()
|
|
|
|
if util.IsSuperWowPresent() then
|
|
PTUnit.UpdateGuidCaches()
|
|
|
|
local customUnitUpdater = CreateFrame("Frame", "PTCustomUnitUpdater")
|
|
local nextUpdate = GetTime() + 0.25
|
|
-- Older versions of SuperWoW had an issue where units that aren't part of normal units wouldn't receive events,
|
|
-- so updates are done manually
|
|
local needsManualUpdates = util.SuperWoWFeatureLevel < util.SuperWoW_v1_4
|
|
customUnitUpdater:SetScript("OnUpdate", function()
|
|
if GetTime() > nextUpdate then
|
|
nextUpdate = GetTime() + 0.25
|
|
|
|
for unit, guid in pairs(CustomUnitGUIDMap) do
|
|
if needsManualUpdates or not UnitExists(guid) then
|
|
PTUnit.Get(unit):UpdateAuras()
|
|
for ui in UnitFrames(unit) do
|
|
ui:UpdateHealth()
|
|
ui:UpdatePower()
|
|
ui:UpdateAuras()
|
|
ui:UpdateIncomingHealing()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
else
|
|
PTUnit.CreateCaches()
|
|
end
|
|
PuppeteerSettings.UpdateTrackedDebuffTypes()
|
|
PTProfileManager.InitializeDefaultProfiles()
|
|
|
|
do
|
|
if PTOptions.Scripts.OnLoad then
|
|
local scriptString = "local GetProfile = PTProfileManager.GetProfile "..
|
|
"local CreateProfile = PTProfileManager.CreateProfile "..PTOptions.Scripts.OnLoad
|
|
local script, err = loadstring(scriptString)
|
|
if script then
|
|
local ok, result = pcall(script)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] ", 1, 0.4, 0.4)..colorize("ERROR: ", 1, 0.2, 0.2)
|
|
..colorize("The Load Script produced an error! If this causes Puppeteer to fail to load, "..
|
|
"you will need to manually edit the script in your game files.", 1, 0.4, 0.4))
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("OnLoad Script Error: "..tostring(result), 1, 0, 0))
|
|
end
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] ", 1, 0.4, 0.4)..colorize("ERROR: ", 1, 0.2, 0.2)
|
|
..colorize("The Load Script failed to load: "..err, 1, 0.4, 0.4))
|
|
end
|
|
end
|
|
end
|
|
PTSettingsGui.Init()
|
|
if PTHealPredict then
|
|
PTHealPredict.OnLoad()
|
|
|
|
PTHealPredict.HookUpdates(function(guid, incomingHealing, incomingDirectHealing)
|
|
if not PTOptions.UseHealPredictions then
|
|
return
|
|
end
|
|
local units = GuidRoster.GetUnits(guid)
|
|
if not units then
|
|
return
|
|
end
|
|
for _, unit in ipairs(units) do
|
|
for ui in UnitFrames(unit) do
|
|
ui:SetIncomingHealing(incomingHealing, incomingDirectHealing)
|
|
end
|
|
end
|
|
end)
|
|
else
|
|
local roster = AceLibrary("RosterLib-2.0")
|
|
PuppeteerLib:RegisterEvent("HealComm_Healupdate", function(name)
|
|
if not PTOptions.UseHealPredictions then
|
|
return
|
|
end
|
|
local unit = roster:GetUnitIDFromName(name)
|
|
if unit then
|
|
for ui in UnitFrames(unit) do
|
|
ui:UpdateIncomingHealing()
|
|
end
|
|
end
|
|
if UnitName("target") == name then
|
|
for ui in UnitFrames("target") do
|
|
ui:UpdateIncomingHealing()
|
|
end
|
|
end
|
|
end)
|
|
PuppeteerLib:RegisterEvent("HealComm_Ressupdate", function(name)
|
|
local unit = roster:GetUnitIDFromName(name)
|
|
if unit then
|
|
for ui in UnitFrames(unit) do
|
|
ui:UpdateHealth()
|
|
end
|
|
end
|
|
if UnitName("target") == name then
|
|
for ui in UnitFrames("target") do
|
|
ui:UpdateHealth()
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
SetLFTAutoRoleEnabled(PTOptions.LFTAutoRole)
|
|
|
|
TestUI = PTOptions.TestUI
|
|
|
|
if TestUI then
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] UI Testing is enabled. Use /pt testui to disable.", 1, 0.6, 0.6))
|
|
end
|
|
|
|
initUnitFrames()
|
|
StartDistanceScanner()
|
|
|
|
PuppeteerLib:RegisterEvent("Banzai_UnitGainedAggro", function(unit)
|
|
if PTGuidRoster then
|
|
unit = PTGuidRoster.GetUnitGuid(unit)
|
|
end
|
|
for ui in UnitFrames(unit) do
|
|
ui:UpdateOutline()
|
|
end
|
|
end)
|
|
PuppeteerLib:RegisterEvent("Banzai_UnitLostAggro", function(unit)
|
|
if PTGuidRoster then
|
|
unit = PTGuidRoster.GetUnitGuid(unit)
|
|
end
|
|
for ui in UnitFrames(unit) do
|
|
ui:UpdateOutline()
|
|
end
|
|
end)
|
|
|
|
if PTOnLoadInfoDisabled == nil then
|
|
PTOnLoadInfoDisabled = false
|
|
end
|
|
|
|
do
|
|
local INFO_SEND_TIME = GetTime() + 0.5
|
|
local infoFrame = CreateFrame("Frame")
|
|
infoFrame:SetScript("OnUpdate", function()
|
|
if GetTime() < INFO_SEND_TIME then
|
|
return
|
|
end
|
|
infoFrame:SetScript("OnUpdate", nil)
|
|
if not PTOnLoadInfoDisabled then
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] Use ", 0.5, 1, 0.5)..colorize("/pt help", 0, 1, 0)
|
|
..colorize(" to see commands.", 0.5, 1, 0.5))
|
|
end
|
|
|
|
if not util.IsSuperWowPresent() and util.IsNampowerPresent() then
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] ", 1, 0.4, 0.4)..colorize("WARNING: ", 1, 0.2, 0.2)
|
|
..colorize("You are using Nampower without SuperWoW, which will cause heal predictions to be wildly inaccurate "..
|
|
"for you and your raid members! It is highly recommended to install SuperWoW.", 1, 0.4, 0.4))
|
|
end
|
|
|
|
if util.IsSuperWowPresent() and not HealComm:IsEventRegistered("UNIT_CASTEVENT") then
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] ", 1, 0.4, 0.4)..colorize("WARNING: ", 1, 0.2, 0.2)
|
|
..colorize("You have another addon that uses a HealComm version that is incompatible with SuperWoW! "..
|
|
"This will cause wildly inaccurate heal predictions to be shown to your raid members. It is "..
|
|
"recommended to either unload the offending addon or copy Puppeteer's HealComm "..
|
|
"into the other addon.", 1, 0.4, 0.4))
|
|
end
|
|
end)
|
|
end
|
|
|
|
do
|
|
if PTOptions.Scripts.OnPostLoad then
|
|
local scriptString = PTOptions.Scripts.OnPostLoad
|
|
local script, err = loadstring(scriptString)
|
|
if script then
|
|
local ok, result = pcall(script)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] ", 1, 0.4, 0.4)..colorize("ERROR: ", 1, 0.2, 0.2)
|
|
..colorize("The Postload Script produced an error! If this causes Puppeteer to fail to operate, "..
|
|
"you may need to manually edit the script in your game files.", 1, 0.4, 0.4))
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("OnPostLoad Script Error: "..tostring(result), 1, 0, 0))
|
|
end
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] ", 1, 0.4, 0.4)..colorize("ERROR: ", 1, 0.2, 0.2)
|
|
..colorize("The Postload Script failed to load: "..err, 1, 0.4, 0.4))
|
|
end
|
|
end
|
|
end
|
|
|
|
EndTiming("OnLoad")
|
|
end
|
|
|
|
function CheckPartyFramesEnabled()
|
|
local shouldBeDisabled = (CurrentlyInRaid and PTOptions.DisablePartyFrames.InRaid) or
|
|
(not CurrentlyInRaid and PTOptions.DisablePartyFrames.InParty)
|
|
SetPartyFramesEnabled(not shouldBeDisabled)
|
|
end
|
|
|
|
function SetPartyFramesEnabled(enabled)
|
|
if enabled then
|
|
for i = 1, MAX_PARTY_MEMBERS do
|
|
local frame = getglobal("PartyMemberFrame"..i)
|
|
if frame and frame.PTRealShow then
|
|
frame.Show = frame.PTRealShow
|
|
frame.PTRealShow = nil
|
|
|
|
if UnitExists("party"..i) then
|
|
frame:Show()
|
|
end
|
|
local prevThis = _G.this
|
|
_G.this = frame
|
|
PartyMemberFrame_OnLoad()
|
|
_G.this = prevThis
|
|
end
|
|
end
|
|
else
|
|
for i = 1, MAX_PARTY_MEMBERS do
|
|
local frame = getglobal("PartyMemberFrame"..i)
|
|
if frame and not frame.PTRealShow then
|
|
frame:UnregisterAllEvents()
|
|
frame.PTRealShow = frame.Show
|
|
frame.Show = function() end
|
|
frame:Hide()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function _G.PT_ToggleFocusUnit(unit)
|
|
if PTUnitProxy.IsUnitUnitType(unit, "focus") then
|
|
if not PTUnitProxy.CustomUnitsSetMap["focus"][unit] then
|
|
return -- Do not toggle focus if user is clicking on a UI that isn't the focus UI
|
|
end
|
|
PT_UnfocusUnit(unit)
|
|
else
|
|
PT_FocusUnit(unit)
|
|
end
|
|
end
|
|
|
|
function _G.PT_FocusUnit(unit)
|
|
local guid = PTGuidRoster.ResolveUnitGuid(unit)
|
|
if not guid or PTUnitProxy.IsGuidUnitType(guid, "focus") then
|
|
return
|
|
end
|
|
|
|
PTUnitProxy.SetGuidUnitType(guid, "focus")
|
|
PlaySound("GAMETARGETHOSTILEUNIT")
|
|
end
|
|
|
|
function _G.PT_UnfocusUnit(unit)
|
|
local guid = PTGuidRoster.ResolveUnitGuid(unit)
|
|
if not guid then
|
|
return
|
|
end
|
|
local focusUnit = PTUnitProxy.GetCurrentUnitOfType(guid, "focus")
|
|
if not focusUnit then
|
|
return
|
|
end
|
|
PTUnitProxy.SetCustomUnitGuid(focusUnit, nil)
|
|
PlaySound("INTERFACESOUND_LOSTTARGETUNIT")
|
|
end
|
|
|
|
function _G.PT_PromoteFocus(unit)
|
|
local guid = PTGuidRoster.ResolveUnitGuid(unit)
|
|
if not guid then
|
|
return
|
|
end
|
|
PTUnitProxy.PromoteGuidUnitType(guid, "focus")
|
|
end
|
|
|
|
function CycleFocus(onlyAttackable)
|
|
PTUnitProxy.CycleUnitType("focus", onlyAttackable)
|
|
end
|
|
|
|
local emptySpell = {}
|
|
function UnitFrame_OnClick(button, unit, unitFrame)
|
|
if not UnitExists(unit) then
|
|
return
|
|
end
|
|
local binding = GetBindingFor(unit, GetKeyModifier(), button)
|
|
local targetCastable = UnitIsConnected(unit) and UnitIsVisible(unit)
|
|
local wantToRes = PTOptions.AutoResurrect and util.IsDeadFriend(unit) and ResurrectionSpells[GetClass("player")]
|
|
if not binding then
|
|
if targetCastable and wantToRes then
|
|
RunBinding_Spell(emptySpell, unit)
|
|
end
|
|
return
|
|
end
|
|
|
|
RunBinding(binding, unit, unitFrame)
|
|
end
|
|
|
|
local CheckGroupThrottler = CreateFrame("Frame", "PTCheckGroupThrottler")
|
|
local MAX_GROUP_UPDATE_TOKENS = 2
|
|
local GROUP_UPDATE_RECOVERY = 0.1
|
|
local groupUpdateTokens = 2
|
|
local nextGroupUpdateToken = 0
|
|
local groupUpdateWaiting = false
|
|
local CheckGroupThrottler_OnUpdate = function()
|
|
if nextGroupUpdateToken <= GetTime() then
|
|
groupUpdateTokens = groupUpdateTokens + 1
|
|
nextGroupUpdateToken = GetTime() + GROUP_UPDATE_RECOVERY
|
|
if groupUpdateWaiting then
|
|
groupUpdateWaiting = false
|
|
print("Delayed Group Update")
|
|
CheckGroupThrottled()
|
|
end
|
|
if groupUpdateTokens == MAX_GROUP_UPDATE_TOKENS then
|
|
CheckGroupThrottler:SetScript("OnUpdate", nil)
|
|
end
|
|
end
|
|
end
|
|
function UseGroupUpdateToken()
|
|
if groupUpdateTokens > 0 then
|
|
groupUpdateTokens = groupUpdateTokens - 1
|
|
if CheckGroupThrottler:GetScript("OnUpdate") == nil then
|
|
nextGroupUpdateToken = GetTime() + GROUP_UPDATE_RECOVERY
|
|
CheckGroupThrottler:SetScript("OnUpdate", CheckGroupThrottler_OnUpdate)
|
|
end
|
|
return true
|
|
end
|
|
groupUpdateWaiting = true
|
|
return false
|
|
end
|
|
|
|
-- Same as CheckGroup, but may delay and consolidate checks if there's been many calls
|
|
function CheckGroupThrottled()
|
|
if UseGroupUpdateToken() then
|
|
CheckGroup()
|
|
print("Group Update "..groupUpdateTokens)
|
|
else
|
|
print("GROUP UPDATE THROTTLED")
|
|
end
|
|
end
|
|
|
|
-- Reevaluates what UI frames should be shown and updates the roster if using SuperWoW
|
|
function CheckGroup()
|
|
StartTiming("CheckGroup")
|
|
if GetNumRaidMembers() > 0 then
|
|
if not CurrentlyInRaid then
|
|
CurrentlyInRaid = true
|
|
SetPartyFramesEnabled(not PTOptions.DisablePartyFrames.InRaid)
|
|
end
|
|
else
|
|
if CurrentlyInRaid then
|
|
CurrentlyInRaid = false
|
|
SetPartyFramesEnabled(not PTOptions.DisablePartyFrames.InParty)
|
|
end
|
|
end
|
|
local superwow = util.IsSuperWowPresent()
|
|
if superwow then
|
|
GuidRoster.ResetRoster()
|
|
GuidRoster.PopulateRoster()
|
|
PTUnit.UpdateGuidCaches()
|
|
end
|
|
for _, unit in ipairs(util.AllRealUnits) do
|
|
local exists, guid = UnitExists(unit)
|
|
if unit ~= "target" then
|
|
if exists then
|
|
for ui in UnitFrames(unit) do
|
|
ui:Show()
|
|
end
|
|
else
|
|
for ui in UnitFrames(unit) do
|
|
ui:Hide()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for _, group in pairs(UnitFrameGroups) do
|
|
group:EvaluateShown()
|
|
end
|
|
if not superwow then -- If SuperWoW isn't present, the units may have shifted and thus require a full scan
|
|
PTUnit.UpdateAllUnits()
|
|
end
|
|
for _, ui in pairs(AllUnitFrames) do
|
|
if ui:IsShown() then
|
|
ui:UpdateRange()
|
|
ui:UpdateAuras()
|
|
ui:UpdateIncomingHealing()
|
|
ui:UpdateOutline()
|
|
end
|
|
end
|
|
if superwow then
|
|
PTHealPredict.SetRelevantGUIDs(GuidRoster.GetTrackedGuids())
|
|
end
|
|
RunTrackingScan()
|
|
EndTiming("CheckGroup")
|
|
end
|
|
|
|
function CheckTarget()
|
|
local exists, guid = UnitExists("target")
|
|
if exists then
|
|
local friendly = not UnitCanAttack("player", "target")
|
|
if (friendly and PTOptions.ShowTargets.Friendly) or (not friendly and PTOptions.ShowTargets.Hostile) then
|
|
for ui in UnitFrames("target") do
|
|
ui.lastHealthPercent = (ui:GetCurrentHealth() / ui:GetMaxHealth()) * 100
|
|
ui:UpdateRange()
|
|
ui:UpdateSight()
|
|
ui:UpdateRole()
|
|
ui:UpdateIncomingHealing()
|
|
end
|
|
end
|
|
else
|
|
for ui in UnitFrames("target") do
|
|
ui.lastHealthPercent = (ui:GetCurrentHealth() / ui:GetMaxHealth()) * 100
|
|
ui:UpdateAll()
|
|
ui:UpdateRole()
|
|
ui:UpdateIncomingHealing()
|
|
end
|
|
end
|
|
UnitFrameGroups["Target"]:EvaluateShown()
|
|
end
|
|
|
|
function IsRelevantUnit(unit)
|
|
return AllUnitsSet[unit] ~= nil or GUIDCustomUnitMap[unit]
|
|
end
|
|
|
|
function print(msg)
|
|
if not PTOptions or not PTOptions["Debug"] then
|
|
return
|
|
end
|
|
local window
|
|
local i = 1
|
|
while not window do
|
|
local name = GetChatWindowInfo(i)
|
|
if not name then
|
|
break
|
|
end
|
|
if name == "Debug" then
|
|
window = getglobal("ChatFrame"..i)
|
|
break
|
|
end
|
|
i = i + 1
|
|
end
|
|
if window then
|
|
window:AddMessage(tostring(msg))
|
|
end
|
|
end
|
|
|
|
function StartTiming(name)
|
|
if not pfDebug_StartTiming then
|
|
return
|
|
end
|
|
pfDebug_StartTiming(name)
|
|
end
|
|
|
|
function EndTiming(name)
|
|
if not pfDebug_EndTiming then
|
|
return
|
|
end
|
|
pfDebug_EndTiming(name)
|
|
end |