Merge pull request #13 from OldManAlpha/dev

Version 1.0.3
This commit is contained in:
OldManAlpha 2025-08-29 16:10:47 -07:00 committed by GitHub
commit da225c898e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 305 additions and 72 deletions

View File

@ -1191,9 +1191,9 @@ function PTUnitFrame:Initialize()
self.nameText = name
name:SetAlpha(profile.NameText:GetAlpha())
local bg = healthBar:CreateTexture(nil, "BACKGROUND")
local bg = container:CreateTexture(nil, "BACKGROUND")
healthBar.background = bg
bg:SetAllPoints(true)
bg:SetAllPoints(healthBar)
bg:SetTexture(0.5, 0.5, 0.5, 0.25)
-- Incoming Text
@ -1460,7 +1460,7 @@ function PTUnitFrame:UpdateComponent(component, props, xOffset, yOffset)
end
function PTUnitFrame:GetCache()
return PTUnit.Get(self.unit) or PTUnit
return PTUnit.Get(self.unit)
end
function PTUnitFrame:GetAfflictedDebuffTypes()

View File

@ -354,6 +354,8 @@ function OnAddonLoaded()
end
end)
end
InitRoleDropdown()
SetLFTAutoRoleEnabled(PTOptions.LFTAutoRole)

View File

@ -1,5 +1,5 @@
## Interface: 11200
## Version: 1.0.2
## Version: 1.0.3
## Title: Puppeteer
## Notes: Unit frames addon tailored for healers
## Author: OldManAlpha, Richard Truax(i2ichardt)

View File

@ -133,6 +133,9 @@ function SetDefaults()
["Medium"] = 10, -- <=2 min
["Long"] = 60 * 2 -- >2 min
},
["Experiments"] = {
["AutoRole"] = false
},
["CastWhen"] = "Mouse Up", -- Mouse Up, Mouse Down
["CastWhenKey"] = "Key Up", -- Key Up, Key Down
["AutoResurrect"] = Puppeteer.ResurrectionSpells[util.GetClass("player")] ~= nil,

View File

@ -81,6 +81,7 @@ RegisterActionBind({
return
end
RoleAssignInfo.Name = UnitName(unit)
RoleAssignInfo.Class = util.GetClass(unit)
RoleAssignInfo.ClassColor = util.GetClassColor(util.GetClass(unit), true)
RoleAssignInfo.FrameGroup = unitFrame.owningGroup
local frame = unitFrame:GetRootContainer()

View File

@ -347,6 +347,20 @@ function RunTargetedAction(binding, unit, actionFunc, mustTempTarget)
end
end
local targetedSpell
local targetedSpellUnit
local function targetedCastFunc()
if util.IsSuperWowPresent() then
CastSpellByName(targetedSpell, targetedSpellUnit)
else
CastSpellByName(targetedSpell)
end
end
local function setupTargetedCast(spell, unit)
targetedSpell = spell
targetedSpellUnit = unit
return targetedCastFunc
end
function RunBinding_Spell(binding, unit)
local spell = binding.Data
@ -359,13 +373,7 @@ function RunBinding_Spell(binding, unit)
end
end
RunTargetedAction(binding, unit, function()
if util.IsSuperWowPresent() then
CastSpellByName(spell, unit)
else
CastSpellByName(spell)
end
end, not util.IsSuperWowPresent())
RunTargetedAction(binding, unit, setupTargetedCast(spell, unit), not util.IsSuperWowPresent())
end
function RunBinding_Action(binding, unit, unitFrame)
@ -410,6 +418,18 @@ local preScript = "local unit = PTScriptUnit;"..
"local unitFrame = PTScriptUnitFrame;"
BindingScriptCache = {}
BindingEnvironment = setmetatable({_G = _G, api = BindingScriptAPI}, {__index = PTUnitProxy or _G})
local targetedScript
local function targetedScriptFunc()
local ok, result = pcall(targetedScript)
if not ok then
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] Error occurred while running custom script binding:", 1, 0.5, 0.5))
DEFAULT_CHAT_FRAME:AddMessage(colorize(result, 1, 0.5, 0.5))
end
end
local function setupTargetedScript(script)
targetedScript = script
return targetedScriptFunc
end
function RunBinding_Script(binding, unit, unitFrame)
local scriptString = binding.Data
if not BindingScriptCache[scriptString] then
@ -425,13 +445,7 @@ function RunBinding_Script(binding, unit, unitFrame)
BindingEnvironment.PTScriptUnit = PTUnitProxy and PTUnitProxy.CustomUnitGUIDMap[unit] or unit
BindingEnvironment.PTScriptUnitUnresolved = unit
BindingEnvironment.PTScriptUnitFrame = unitFrame
RunTargetedAction(binding, unit, function()
local ok, result = pcall(BindingScriptCache[scriptString])
if not ok then
DEFAULT_CHAT_FRAME:AddMessage(colorize("[Puppeteer] Error occurred while running custom script binding:", 1, 0.5, 0.5))
DEFAULT_CHAT_FRAME:AddMessage(colorize(result, 1, 0.5, 0.5))
end
end)
RunTargetedAction(binding, unit, setupTargetedScript(BindingScriptCache[scriptString]))
end
MultiMenu = PTGuiLib.Get("dropdown", UIParent)

View File

@ -9,17 +9,10 @@ local TRACKING_MIN_DIST = 20
local TRACKING_MAX_DIST = 60
local SIGHT_MAX_DIST = 80
local almostAllUnits = util.CloneTable(util.AllUnits) -- Everything except the player
table.remove(almostAllUnits, util.IndexOf(almostAllUnits, "player"))
if PTUnitProxy then
PTUnitProxy.RegisterUpdateListener(function()
almostAllUnits = util.CloneTable(util.AllUnits) -- Everything except the player
table.remove(almostAllUnits, util.IndexOf(almostAllUnits, "player"))
end)
end
local AllUnits = util.AllUnits
local distanceTrackedUnits = util.CloneTable(almostAllUnits) -- Initially scan all units
local sightTrackedUnits = util.CloneTable(almostAllUnits)
local distanceTrackedUnits = util.CloneTable(AllUnits) -- Initially scan all units
local sightTrackedUnits = util.CloneTable(AllUnits)
local preciseDistance = util.CanClientGetPreciseDistance()
local sightTrackingEnabled = util.CanClientSightCheck()
local nextTrackingUpdate = GetTime() + 0.5
@ -46,7 +39,7 @@ function RunTrackingScan()
EvaluateTracking(guid)
end
else
for _, unit in ipairs(almostAllUnits) do
for _, unit in ipairs(AllUnits) do
EvaluateTracking(unit)
end
end

View File

@ -65,6 +65,9 @@ RegisterEventHandler("UNIT_AURA", function()
if not IsRelevantUnit(unit) then
return
end
if unit == "player" then
util.MarkSpellCostCacheDirty()
end
PTUnit.Get(unit):UpdateAuras()
for ui in UnitFrames(unit) do
ui:UpdateAuras()
@ -107,6 +110,10 @@ RegisterEventHandler("PLAYER_TARGET_CHANGED", function()
end)
RegisterEventHandler("SPELLS_CHANGED", function()
PuppeteerSettings.UpdateTrackedDebuffTypes()
util.MarkSpellCostCacheDirty()
end)
RegisterEventHandler("CHARACTER_POINTS_CHANGED", function()
util.MarkSpellCostCacheDirty()
end)
RegisterEventHandler("RAID_TARGET_UPDATE", function()
for _, ui in ipairs(AllUnitFrames) do

View File

@ -3,12 +3,13 @@ local _G = getfenv(0)
local util = PTUtil
local colorize = util.Colorize
local GetColoredRoleText = util.GetColoredRoleText
local SplitString = util.SplitString
AssignedRoles = nil
LFTAutoRoleFrame = CreateFrame("Frame", "PT_LFTAutoRoleFrame")
function SetLFTAutoRoleEnabled(enabled)
if not LFT_ADDON_PREFIX then -- Must not be Turtle WoW, or LFT has changed
if not util.IsTurtleWow() then
return
end
@ -48,11 +49,11 @@ function SetLFTAutoRoleEnabled(enabled)
end
LFTAutoRoleFrame:RegisterEvent("CHAT_MSG_ADDON")
LFTAutoRoleFrame:SetScript("OnEvent", function()
if arg1 == LFT_ADDON_PREFIX then
if arg1 == (LFT_ADDON_PREFIX or "TW_LFG") then
-- After an offer is complete, it is immediately followed by rolecheck info for the tank and healer
if strfind(arg2, "S2C_ROLECHECK_INFO") then
if GetNumPartyMembers() == 4 then
local params = util.SplitString(arg2, LFT_ADDON_FIELD_DELIMITER)
local params = util.SplitString(arg2, ";")
local member = params[2]
params = util.SplitString(params[3], ":") -- get confirmed roles
if offerCompleteTime + 0.5 > GetTime() and table.getn(params) == 1 then
@ -120,15 +121,117 @@ function PruneAssignedRoles()
end
end
function SetRoleAndUpdate(name, role)
SetAssignedRole(name, role)
UpdateUnitFrameGroups()
end
function SetUnitRoleAndUpdate(unit, role)
if not SetUnitAssignedRole(unit, role) then
UpdateUnitFrameGroups()
end
end
-- Players will be considered as the role in the index if they have the highest talent points in said index.
-- Clases not listed have only DPS specs and are not bothered to be scanned.
TalentCountRoleMap = {
PRIEST = {
"Healer", "Healer", "Damage"
},
PALADIN = {
"Healer", "Tank", "Damage"
},
WARRIOR = {
"Damage", "Damage", "Tank"
},
SHAMAN = {
"Damage", "Damage", "Healer"
},
DRUID = { -- Spec #2(Feral) will be swapped to Tank if Thick Hide talent is found
"Damage", "Damage", "Healer"
}
}
local PlayerTalentData = {}
local talentScanner = CreateFrame("Frame", "PTTalentScanner")
talentScanner:RegisterEvent("CHAT_MSG_ADDON")
talentScanner:SetScript("OnEvent", function()
if arg1 == "TW_CHAT_MSG_WHISPER" then
local message = arg2
local sender = arg4
if not PlayerTalentData[sender] then
return
end
if string.find(message, "INSTalentTabInfo;", 1, true) then
-- This is sent right before receiving info for individual talents in the tree
local split = SplitString(message, ';')
local index = tonumber(split[2])
local pointsSpent = tonumber(split[4])
PlayerTalentData[sender].trees[index] = {points = pointsSpent, talents = {}}
elseif string.find(message, "INSTalentInfo;", 1, true) then
local split = SplitString(message, ';')
local tree = tonumber(split[2])
local tier = tonumber(split[5])
local column = tonumber(split[6])
local currRank = tonumber(split[7])
local cache = PlayerTalentData[sender]
local talents = cache.trees[tree].talents
talents[tier.."-"..column] = currRank
elseif string.find(message, "INSTalentEND;", 1, true) then
local data = PlayerTalentData[sender]
local trees = data.trees
local mostPoints = 0
local mostIndex = 1
for i = 1, 3 do
if trees[i].points > mostPoints then
mostPoints = trees[i].points
mostIndex = i
end
end
local class = data.class
-- Check for Druid Thick Hide talent, set as tank if they have it
if class == "DRUID" and (trees[2].talents["2-3"] or 0) > 0 then
SetRoleAndUpdate(sender, "Tank")
else
SetRoleAndUpdate(sender, mostPoints > 0 and TalentCountRoleMap[class][mostIndex] or "Damage")
end
PlayerTalentData[sender] = nil
end
end
end)
local function requestTalents(name)
SendAddonMessage("TW_CHAT_MSG_WHISPER<"..name..">", "INSShowTalents", "GUILD")
end
function AutoRole(unit)
local class = util.GetClass(unit)
if not TalentCountRoleMap[class] then
SetUnitRoleAndUpdate(unit, "Damage")
return
end
if not UnitIsConnected(unit) then -- Can't request offline player's talents
return
end
PlayerTalentData[UnitName(unit)] = {class = class, trees = {}}
requestTalents(UnitName(unit))
end
function AutoRoleByNameClass(name, class)
PlayerTalentData[name] = {class = class, trees = {}}
requestTalents(name)
end
RoleAssignInfo = {}
do
RoleDropdown = PTGuiLib.Get("dropdown", UIParent)
function InitRoleDropdown()
local initFunc = function(self)
self.checked = (GetAssignedRole(RoleAssignInfo.Name) or "No Role") == self.role
end
@ -165,7 +268,6 @@ do
}
end
RoleDropdown = PTGuiLib.Get("dropdown", UIParent)
local options = {
{
initFunc = function(self)
@ -178,7 +280,7 @@ do
genRole("Tank"),
genRole("Healer"),
genRole("Damage"),
genRole("No Role"),
genRole("No Role"),
{
notCheckable = true,
disabled = true
@ -202,5 +304,39 @@ do
func = massRoleFunc
}
}
if PTOptions.Experiments.AutoRole then
table.insert(options, 6, {
text = colorize("Auto Detect", 1, 0.6, 0),
func = function()
if not RoleAssignInfo.FrameGroup then
return
end
AutoRoleByNameClass(RoleAssignInfo.Name, RoleAssignInfo.Class)
end
})
local lastMassRole = 0
table.insert(options, 9, {
text = "Auto Detect Unassigned",
tooltipTitle = "Auto Detect Unassigned",
tooltipText = "Automatically detect the roles of unassigned players. Only applies to players contained in this UI group.",
notCheckable = true,
textHeight = 11,
func = function()
if not RoleAssignInfo.FrameGroup then
return
end
if lastMassRole + 6 > GetTime() then
DEFAULT_CHAT_FRAME:AddMessage("Please wait a moment before requesting roles again")
return
end
lastMassRole = GetTime()
for _, ui in pairs(RoleAssignInfo.FrameGroup.uis) do
if UnitIsPlayer(ui:GetUnit()) and not GetUnitAssignedRole(ui:GetUnit()) then
AutoRole(ui:GetUnit())
end
end
end
})
end
RoleDropdown:SetOptions(options)
end

View File

@ -228,8 +228,8 @@ function CreateTab_Bindings()
end)
UniversalBindingsCheckbox = universalBindingsCheckbox
local keyLabel = CreateLabel(container, "Key")
:SetPoint("TOPLEFT", container, "TOPLEFT", 120, -125)
local keyLabel = CreateLabel(container, "Key Modifier")
:SetPoint("TOPLEFT", container, "TOPLEFT", 95, -125)
local keyDropdown = CreateDropdown(container, 150)
:SetPoint("LEFT", keyLabel, "RIGHT", 5, 0)
@ -259,8 +259,8 @@ function CreateTab_Bindings()
local addButton = PTGuiLib.Get("button", container)
:SetPoint("TOP", container, "TOP", 0, -440)
:SetSize(200, 25)
:SetText("Edit Buttons")
:ApplyTooltip("Edit what buttons you use and their names")
:SetText("Add or Remove Buttons")
:ApplyTooltip("Edit what buttons you can bind spells to")
:OnClick(function()
local editor = PTGuiLib.Get("puppeteer_button_editor", TabFrame)
:SetPoint("CENTER", TabFrame, "CENTER")
@ -436,7 +436,7 @@ function CreateTab_Options_SpellsTooltip(panel)
layout:offset(0, 10)
factory:dropdown("Anchor", "Where the tooltip should be anchored", "SpellsTooltip.Anchor",
{"Top Left", "Top Right", "Bottom Left", "Bottom Right"})
factory:checkbox("Show Item Count", {"Show the amount of your bound items", colorize("Warning: This causes lag!", 1, 0.2, 0.2)},
factory:checkbox("Show Item Count", {"Show the amount of your bound items", colorize("Warning: This causes lag!", 1, 0.4, 0.4)},
"SpellsTooltip.ShowItemCount")
end
@ -477,22 +477,26 @@ function CreateTab_Options_Other(panel)
"UseHealPredictions", function() Puppeteer.UpdateAllIncomingHealing() end)
factory:checkbox("(TWoW) LFT Auto Role", {"Automatically assign roles when joining LFT groups",
"This functionality was created for 1.17.2 and may break in future updates"}, "LFTAutoRole",
"This functionality was tested for 1.18.0 and may break in future updates"}, "LFTAutoRole",
function() Puppeteer.SetLFTAutoRoleEnabled(PTOptions.LFTAutoRole) end)
end
function CreateTab_Options_Advanced(panel)
local container = panel:CreateTab("Advanced")
local layout = NewLabeledColumnLayout(container, {150, 220, 300}, -20, 10)
local layout = NewLabeledColumnLayout(container, {150, 220, 300}, 0, 10)
local factory = NewComponentFactory(container, layout)
container.factory = factory
local TEXT_WIDTH = 370
local scriptsLabel = CreateLabel(container, "Load & Postload Scripts")
:SetPoint("TOP", container, "TOP", 0, -10)
:SetFontSize(14)
local loadScriptInfo = CreateLabel(container, "The Load Script runs after profiles are initialized, but before UIs are created, "..
"making it good for editing profile attributes. GetProfile and CreateProfile are defined locals.")
:SetWidth(TEXT_WIDTH)
:SetPoint("TOP", container, "TOP", 0, -10)
:SetPoint("TOP", scriptsLabel, "BOTTOM", 0, -10)
local loadScriptButton = PTGuiLib.Get("button", container)
:SetPoint("TOP", loadScriptInfo, "BOTTOM", 0, -5)
:SetSize(150, 20)
@ -547,6 +551,14 @@ function CreateTab_Options_Advanced(panel)
:OnClick(function()
ReloadUI()
end)
local experimentsLabel = CreateLabel(container, "Experiments")
:SetPoint("TOP", reloadButton, "BOTTOM", 0, -20)
:SetFontSize(14)
layout:offset(0, -260)
factory:checkbox("(TWoW) Auto Role", {"If enabled, the Role Action menu shows auto role detection options",
colorize("Using this functionality WILL cause errors and other unexpected behavior", 1, 0.4, 0.4)}, "Experiments.AutoRole",
Puppeteer.InitRoleDropdown)
end
function CreateTab_Options_Mods(panel)

View File

@ -95,6 +95,7 @@ function PTButtonEditor:New()
end
if not obj:ContainsButton(arg1) then
obj:AddButtonLine(arg1, arg1)
PlaySound("igSpellBookOpen")
end
obj:SetAddMode(false)
local onClick = addButton:GetScript("OnClick")
@ -114,6 +115,7 @@ function PTButtonEditor:New()
if not obj:ContainsButton(arg1) then
if not obj:AreBindingsFull() then
obj:AddButtonLine(arg1, arg1)
PlaySound("igSpellBookOpen")
else
DEFAULT_CHAT_FRAME:AddMessage("You cannot add any more non-mouse buttons!")
end
@ -128,6 +130,7 @@ function PTButtonEditor:New()
if not obj:ContainsButton("MOUSEWHEELUP") then
if not obj:AreBindingsFull() then
obj:AddButtonLine("MOUSEWHEELUP", "MOUSEWHEELUP")
PlaySound("igSpellBookOpen")
else
DEFAULT_CHAT_FRAME:AddMessage("You cannot add any more non-mouse buttons!")
end
@ -136,6 +139,7 @@ function PTButtonEditor:New()
if not obj:ContainsButton("MOUSEWHEELDOWN") then
if not obj:AreBindingsFull() then
obj:AddButtonLine("MOUSEWHEELDOWN", "MOUSEWHEELDOWN")
PlaySound("igSpellBookOpen")
else
DEFAULT_CHAT_FRAME:AddMessage("You cannot add any more non-mouse buttons!")
end

View File

@ -23,8 +23,7 @@ function PTNewLoadout:New()
:SetDynamicOptions(function(addOption, level, args)
addOption("text", "<Blank>",
"dropdownText", "<Blank>",
"initFunc", args.initFunc,
"func", args.func)
"initFunc", args.initFunc)
for _, name in ipairs(Puppeteer.GetBindingLoadoutNames()) do
addOption("text", name,
"dropdownText", name,
@ -94,7 +93,6 @@ end
function PTNewLoadout:OnDispose()
self.super.OnDispose(self)
end
PTNewLoadout:CreateGetter("InheritDropdown")

View File

@ -303,6 +303,7 @@ function UpdateCacheHot(spellName, heal, targetGuid, targetName, casterGuid, cas
if not hots[spellName] then
return
end
heal = tonumber(heal) or 0
local hot = hots[spellName]
if hot["heal"] ~= heal then
local prevHeal = hot["heal"]

View File

@ -10,6 +10,7 @@ local GetAuraInfo = util.GetAuraInfo
local AllUnits = util.AllUnits
local AllUnitsSet = util.AllUnitsSet
local superwow = util.IsSuperWowPresent()
local canGetAuraIDs = util.CanClientGetAuraIDs()
local compost = AceLibrary("Compost-2.0")
@ -92,7 +93,7 @@ function Get(unit)
if superwow and AllUnitsSet[unit] then
return PTUnit.Cached[PTGuidRoster.GetUnitGuid(unit)] or PTUnit
end
return PTUnit.Cached[unit]
return PTUnit.Cached[unit] or PTUnit
end
function GetAllUnits()
@ -107,6 +108,7 @@ function PTUnit:New(unit)
obj:AllocateAuras()
obj.AurasPopulated = true -- To force aura fields to generate
obj.IsNew = true
obj.IsSelf = UnitIsUnit(unit, "player")
if superwow then
obj.AuraTimes = compost:GetTable()
end
@ -146,7 +148,7 @@ function PTUnit:UpdateDistance()
return
end
local prevDist = self.Distance
self.Distance = util.GetDistanceTo(self.Unit)
self.Distance = self.IsSelf and 0 or util.GetDistanceTo(self.Unit)
return self.Distance ~= prevDist
end
@ -161,7 +163,7 @@ function PTUnit:UpdateSight()
return
end
local wasInSight = self.InSight
self.InSight = util.IsInSight(self.Unit)
self.InSight = self.IsSelf or util.IsInSight(self.Unit)
return self.InSight ~= wasInSight
end
@ -202,25 +204,21 @@ function PTUnit:AllocateAuras()
end
function PTUnit:ClearAuras()
if not self.AurasPopulated or self.Buffs == PTUnit.Buffs then
if not self.AurasPopulated or self == PTUnit then
return
end
compost:Reclaim(self.Buffs, 1)
compost:Reclaim(self.BuffsMap, 1)
compost:Reclaim(self.BuffsIDSet)
compost:Erase(self.BuffsIDSet)
compost:Reclaim(self.Debuffs, 1)
compost:Reclaim(self.DebuffsMap, 1)
compost:Reclaim(self.DebuffsIDSet)
compost:Reclaim(self.TypedDebuffs)
compost:Reclaim(self.AfflictedDebuffTypes)
compost:Erase(self.DebuffsIDSet)
compost:Erase(self.TypedDebuffs)
compost:Erase(self.AfflictedDebuffTypes)
self.Buffs = compost:GetTable()
self.BuffsMap = compost:GetTable()
self.BuffsIDSet = compost:GetTable()
self.Debuffs = compost:GetTable()
self.DebuffsMap = compost:GetTable()
self.DebuffsIDSet = compost:GetTable()
self.TypedDebuffs = compost:GetTable()
self.AfflictedDebuffTypes = compost:GetTable()
self.HasHealingModifier = false
self.AurasPopulated = false
end
@ -238,9 +236,6 @@ function PTUnit:UpdateAuras()
return
end
local PT = Puppeteer
-- Track player buffs
local buffs = self.Buffs
local buffsMap = self.BuffsMap
local buffsIDSet = self.BuffsIDSet
@ -249,7 +244,7 @@ function PTUnit:UpdateAuras()
if not texture then
break
end
local name, type = GetAuraInfo(unit, "Buff", index)
local name, type = GetAuraInfo(unit, index, "Buff", id)
if PuppeteerSettings.TrackedHealingBuffs[name] then
self.HasHealingModifier = true
end
@ -265,7 +260,6 @@ function PTUnit:UpdateAuras()
end
local afflictedDebuffTypes = self.AfflictedDebuffTypes
-- Track player debuffs
local debuffs = self.Debuffs
local debuffsMap = self.DebuffsMap
local debuffsIDSet = self.DebuffsIDSet
@ -276,7 +270,7 @@ function PTUnit:UpdateAuras()
break
end
type = type or ""
local name = GetAuraInfo(unit, "Debuff", index)
local name = GetAuraInfo(unit, index, "Debuff", id)
if PuppeteerSettings.TrackedHealingDebuffs[name] then
self.HasHealingModifier = true
end
@ -311,7 +305,7 @@ end
-- Looks for ID if SuperWoW/Turtle WoW is present, otherwise searches by name
function PTUnit:HasBuffIDOrName(id, name)
if superwow then
if canGetAuraIDs then
return self:HasBuffID(id)
end
return self:HasBuff(name)
@ -328,7 +322,7 @@ end
-- Looks for ID if SuperWoW/Turtle WoW is present, otherwise searches by name
function PTUnit:HasDebuffIDOrName(id, name)
if superwow then
if canGetAuraIDs then
return self:HasDebuffID(id)
end
return self:HasDebuff(name)
@ -363,6 +357,9 @@ function PTUnit:GetDebuffs(name)
end
function PTUnit:GetAuraTimeRemaining(name)
if not superwow then
return
end
local auraTime = self.AuraTimes[name]
if not auraTime then
return

View File

@ -498,14 +498,14 @@ function ExtractSpellRank(spellname)
end
-- Thanks again ChatGPT
local tooltipResources = {"Mana", "Rage", "Energy"}
local tooltipResources = {["Mana"] = "mana", ["Rage"] = "rage", ["Energy"] = "energy"}
function ExtractResourceCost(costText)
-- First extract resource type
local resource
for _, r in ipairs(tooltipResources) do
if string.find(costText, r) then
resource = string.lower(r)
for tooltipName, lowerName in pairs(tooltipResources) do
if string.find(costText, tooltipName) then
resource = lowerName
break
end
end
@ -562,8 +562,23 @@ function GetSpellID(spellname)
return foundID
end
local costCache = {}
local costTypeCache = {}
local costCacheDirty = false
function MarkSpellCostCacheDirty()
costCacheDirty = true
end
-- Returns the numerical cost and the resource name; "unknown" if the spell is unknown; 0 if the spell is free
function GetResourceCost(spellName)
if costCacheDirty then
ClearTable(costCache)
ClearTable(costTypeCache)
costCacheDirty = false
end
if costCache[spellName] then
return costCache[spellName], costTypeCache[spellName]
end
ScanningTooltip:SetOwner(UIParent, "ANCHOR_NONE");
local spellID, bookType
@ -587,13 +602,15 @@ function GetResourceCost(spellName)
local leftText = _G["PTScanningTooltipTextLeft2"]
if leftText:GetText() then
return ExtractResourceCost(leftText:GetText())
costCache[spellName], costTypeCache[spellName] = ExtractResourceCost(leftText:GetText())
return costCache[spellName], costTypeCache[spellName]
end
costCache[spellName] = 0
return 0
end
-- Returns the aura's name and its school type
function GetAuraInfo(unit, type, index)
function ScanAuraInfo(unit, index, type)
-- Make these texts blank since they don't clear otherwise
local leftText = _G["PTScanningTooltipTextLeft1"]
leftText:SetText("")
@ -607,6 +624,33 @@ function GetAuraInfo(unit, type, index)
return leftText:GetText() or "", rightText:GetText() or ""
end
if SuperWoW or TurtleWow then
local auraNameCache = {}
local auraTypeCache = {}
function GetAuraInfo(unit, index, type, id)
if not id then
if type == "Buff" then
local _, _, i = UnitBuff(unit, index)
id = i
else
local _, _, _, i = UnitDebuff(unit, index)
id = i
end
end
if not auraNameCache[id] then
auraNameCache[id], auraTypeCache[id] = ScanAuraInfo(unit, index, type)
end
return auraNameCache[id], auraTypeCache[id]
end
function GetCachedAuraInfo(id)
return auraNameCache[id], auraTypeCache[id]
end
else
GetAuraInfo = ScanAuraInfo
end
-- Returns an array of the units in the party number or the unit's raid group
function GetRaidPartyMembers(partyNumberOrUnit)
if not RAID_SUBGROUP_LISTS then
@ -1151,6 +1195,10 @@ function CanClientSightCheck()
return UnitXPSP3
end
function CanClientGetAuraIDs()
return SuperWoW or TurtleWow
end
function IsSuperWowPresent()
return SuperWoW
end

View File

@ -23,4 +23,21 @@ function PTGuiCheckbox:OnDispose()
self:SetChecked(false)
end
function PTGuiCheckbox:SetScript(scriptName, script, noSelf)
if scriptName ~= "OnClick" then
return self.super.SetScript(self, scriptName, script, noSelf)
end
self:GetHandle():SetScript(scriptName, function()
if self:GetChecked() then
PlaySound("igMainMenuOptionCheckBoxOn")
else
PlaySound("igMainMenuOptionCheckBoxOff")
end
if script then
script(self)
end
end)
return self
end
PTGuiLib.RegisterComponent(PTGuiCheckbox)