mirror of
https://github.com/OldManAlpha/Puppeteer.git
synced 2025-11-28 23:48:35 +00:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
899408c4e9 | ||
|
|
8b67661ed9 | ||
|
|
7be8640a6f | ||
|
|
c8fceaf243 | ||
|
|
224f329d08 | ||
|
|
5e4a63d651 | ||
|
|
34f549744e | ||
|
|
e1898c1486 | ||
|
|
e3ba7e831c | ||
|
|
27bd99c7a8 | ||
|
|
0faa8b9184 | ||
|
|
30da69e21b | ||
|
|
f7563933ee | ||
|
|
ad54a21b6a | ||
|
|
93a0594410 | ||
|
|
be859b3b90 | ||
|
|
b44605879e | ||
|
|
5049852079 | ||
|
|
119a2381c6 | ||
|
|
4982c62fe0 | ||
|
|
b0e9d956a2 | ||
|
|
58fb2aeadc | ||
|
|
da225c898e | ||
|
|
6cb3f51c57 | ||
|
|
2247ba244f | ||
|
|
aaadb265a1 | ||
|
|
2ccf53fd86 | ||
|
|
c00be9fd64 | ||
|
|
87d27f4cc9 | ||
|
|
83736ac0c4 | ||
|
|
14516d62db | ||
|
|
d025a1a906 | ||
|
|
3faed3a1b7 | ||
|
|
fb2ad22973 | ||
|
|
7a2007044f | ||
|
|
406330c255 | ||
|
|
c053d7cdae | ||
|
|
58270464c0 | ||
|
|
4658a99450 | ||
|
|
305bb9eaf5 | ||
|
|
2a5ed7006b |
@ -180,6 +180,7 @@ function PTUnitFrame:UpdateAll()
|
||||
self:EvaluateTarget()
|
||||
self:UpdateOutline()
|
||||
self:UpdateRaidMark()
|
||||
self:UpdatePVP()
|
||||
end
|
||||
|
||||
function PTUnitFrame:GetShowDistanceThreshold()
|
||||
@ -322,6 +323,22 @@ function PTUnitFrame:UpdateRaidMark()
|
||||
self.raidMarkIcon.frame:Show()
|
||||
end
|
||||
|
||||
function PTUnitFrame:UpdatePVP()
|
||||
if UnitIsPVP(self.unit) and (not IsInInstance() or not UnitIsVisible(self.unit)) then
|
||||
local faction = UnitFactionGroup(self.unit)
|
||||
if faction == "Alliance" then
|
||||
self.pvpIcon.icon:SetTexture("Interface\\TargetingFrame\\UI-PVP-Alliance")
|
||||
elseif faction == "Horde" then
|
||||
self.pvpIcon.icon:SetTexture("Interface\\TargetingFrame\\UI-PVP-Horde")
|
||||
else
|
||||
self.pvpIcon.icon:SetTexture("Interface\\TargetingFrame\\UI-PVP-FFA")
|
||||
end
|
||||
self.pvpIcon.frame:Show()
|
||||
else
|
||||
self.pvpIcon.frame:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function PTUnitFrame:Flash()
|
||||
local FLASH_TIME = 0.15
|
||||
local START_OPACITY = self:GetProfile().FlashOpacity / 100
|
||||
@ -632,7 +649,7 @@ function PTUnitFrame:SetHealthBarValue(value)
|
||||
incomingHealText:SetText("")
|
||||
end
|
||||
elseif profile.IncomingHealDisplay == "Heal" then
|
||||
incomingHealText:SetText("+"..self.incomingHealing)
|
||||
incomingHealText:SetText("+"..math.ceil(incomingHealing))
|
||||
local rgb = incomingDirectHealing > 0 and profile.IncomingHealText.Color or
|
||||
profile.IncomingHealText.IndirectColor
|
||||
if incomingDirectHealing > 0 then
|
||||
@ -786,7 +803,12 @@ function PTUnitFrame:AllocateAura()
|
||||
frame:SetScript("OnMouseUp", PTUnitFrame.Aura_OnMouseUp)
|
||||
frame:SetScript("OnMouseDown", PTUnitFrame.Aura_OnMouseDown)
|
||||
|
||||
local icon = frame:CreateTexture(nil, "OVERLAY")
|
||||
local icon = frame:CreateTexture(nil, "ARTWORK")
|
||||
local border = frame:CreateTexture(nil, "OVERLAY")
|
||||
border:SetTexture("Interface\\Buttons\\UI-Debuff-Overlays")
|
||||
border:SetTexCoord(0.296875, 0.5703125, 0, 0.515625)
|
||||
border:SetPoint("TOPLEFT", icon, "TOPLEFT", -0.5, 0.5)
|
||||
border:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", 0.5, -0.5)
|
||||
local stackText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
stackText:SetTextColor(1, 1, 1)
|
||||
|
||||
@ -824,16 +846,18 @@ function PTUnitFrame:AllocateAura()
|
||||
end
|
||||
duration:SetScript("OnUpdate", nil)
|
||||
end
|
||||
local SetSequenceTime = duration.SetSequenceTime
|
||||
local GetTime = GetTime
|
||||
duration:SetScript("OnUpdateModel", function()
|
||||
if this.stopping == 0 then
|
||||
this:SetAlpha(0.8)
|
||||
if duration.stopping == 0 then
|
||||
duration:SetAlpha(0.8)
|
||||
local time = GetTime()
|
||||
local progress = (time - this.start) / this.duration
|
||||
local progress = (time - duration.start) / duration.duration
|
||||
if progress < 1.0 then
|
||||
this:SetSequenceTime(0, 1000 - (progress * 1000))
|
||||
local secondsPrecise = this.start - time + this.duration
|
||||
SetSequenceTime(duration, 0, 1000 - (progress * 1000))
|
||||
local secondsPrecise = duration.start - time + duration.duration
|
||||
local seconds = math.floor(secondsPrecise)
|
||||
if seconds <= (this.displayAt and this.displayAt or AURA_DURATION_TEXT_FLASH_THRESHOLD) then
|
||||
if seconds <= (duration.displayAt or AURA_DURATION_TEXT_FLASH_THRESHOLD) then
|
||||
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)
|
||||
@ -847,13 +871,13 @@ function PTUnitFrame:AllocateAura()
|
||||
return
|
||||
end
|
||||
durationText:SetSeconds(nil)
|
||||
this:SetSequenceTime(0, 0)
|
||||
SetSequenceTime(duration, 0, 0)
|
||||
end
|
||||
end)
|
||||
return {["frame"] = frame, ["icon"] = icon, ["stackText"] = stackText, ["overlay"] = durationOverlayFrame,
|
||||
return {["frame"] = frame, ["icon"] = icon, ["border"] = border, ["stackText"] = stackText, ["overlay"] = durationOverlayFrame,
|
||||
["durationText"] = durationText, ["duration"] = duration, ["durationEnabled"] = true}
|
||||
end
|
||||
return {["frame"] = frame, ["icon"] = icon, ["stackText"] = stackText}
|
||||
return {["frame"] = frame, ["icon"] = icon, ["border"] = border, ["stackText"] = stackText}
|
||||
end
|
||||
|
||||
-- Get an icon from the available pool. Automatically inserts into the used pool.
|
||||
@ -974,13 +998,13 @@ function PTUnitFrame:UpdateAuras()
|
||||
local yOffset = profile.TrackedAurasAlignment == "TOP" and 0 or origSize - auraSize
|
||||
for _, buff in ipairs(buffs) do
|
||||
local aura = self:GetUnusedAura()
|
||||
self:CreateAura(aura, buff.name, buff.index, buff.texture, buff.stacks, xOffset, -yOffset, "Buff", auraSize)
|
||||
self:CreateAura(aura, buff.name, buff.index, buff.texture, buff.stacks, buff.type, xOffset, -yOffset, "Buff", auraSize)
|
||||
xOffset = xOffset + auraSize + spacing
|
||||
end
|
||||
xOffset = 0
|
||||
for _, debuff in ipairs(debuffs) do
|
||||
local aura = self:GetUnusedAura()
|
||||
self:CreateAura(aura, debuff.name, debuff.index, debuff.texture, debuff.stacks, xOffset, -yOffset, "Debuff", auraSize)
|
||||
self:CreateAura(aura, debuff.name, debuff.index, debuff.texture, debuff.stacks, debuff.type, xOffset, -yOffset, "Debuff", auraSize)
|
||||
xOffset = xOffset - auraSize - spacing
|
||||
end
|
||||
compost:Reclaim(buffs)
|
||||
@ -1056,7 +1080,14 @@ do
|
||||
PTUnitFrame.Aura_OnMouseDown = wrapButtonScript("OnMouseDown")
|
||||
end
|
||||
|
||||
function PTUnitFrame:CreateAura(aura, name, index, texturePath, stacks, xOffset, yOffset, type, size)
|
||||
local debuffTypeBorderColors = {
|
||||
["Magic"] = {0.2, 0.6, 1.0},
|
||||
["Curse"] = {0.6, 0.0, 1.0},
|
||||
["Disease"] = {0.6, 0.4, 0},
|
||||
["Poison"] = {0.0, 0.6, 0},
|
||||
["Other"] = {1, 0, 0}
|
||||
}
|
||||
function PTUnitFrame:CreateAura(aura, name, index, texturePath, stacks, auraType, xOffset, yOffset, type, size)
|
||||
local frame = aura.frame
|
||||
frame:SetWidth(size)
|
||||
frame:SetHeight(size)
|
||||
@ -1070,7 +1101,6 @@ function PTUnitFrame:CreateAura(aura, name, index, texturePath, stacks, xOffset,
|
||||
local icon = aura.icon
|
||||
icon:SetAllPoints(frame)
|
||||
icon:SetTexture(texturePath)
|
||||
--icon:SetVertexColor(1, 0, 0)
|
||||
|
||||
if aura.durationEnabled then
|
||||
local overlay = aura.overlay
|
||||
@ -1088,6 +1118,15 @@ function PTUnitFrame:CreateAura(aura, name, index, texturePath, stacks, xOffset,
|
||||
stackText:SetText(stacks)
|
||||
end
|
||||
|
||||
if type == "Buff" then
|
||||
aura.border:Hide()
|
||||
else
|
||||
local border = aura.border
|
||||
border:Show()
|
||||
local color = debuffTypeBorderColors[auraType] or debuffTypeBorderColors["Other"]
|
||||
border:SetVertexColor(color[1], color[2], color[3])
|
||||
end
|
||||
|
||||
if aura.durationEnabled then
|
||||
local cache = self:GetCache()
|
||||
if cache.AuraTimes[name] then
|
||||
@ -1166,6 +1205,17 @@ function PTUnitFrame:Initialize()
|
||||
raidMarkIcon:SetTexture("Interface\\TARGETINGFRAME\\UI-RaidTargetingIcons")
|
||||
raidMarkFrame:Hide()
|
||||
|
||||
-- PVP Icon
|
||||
|
||||
local pvpFrame = CreateFrame("Frame", nil, container)
|
||||
pvpFrame:SetFrameLevel(container:GetFrameLevel() + 4)
|
||||
local pvpIcon = pvpFrame:CreateTexture(nil, "OVERLAY")
|
||||
self.pvpIcon = {frame = pvpFrame, icon = pvpIcon}
|
||||
pvpIcon:SetAlpha(profile.PVPIcon:GetAlpha())
|
||||
pvpIcon:SetTexture("Interface\\TargetingFrame\\UI-PVP-Alliance")
|
||||
pvpIcon:SetTexCoord(3 / 64, 39 / 64, 2 / 64, 38 / 64)
|
||||
pvpFrame:Hide()
|
||||
|
||||
-- Health Bar Element
|
||||
|
||||
local healthBar = CreateFrame("StatusBar", "$parentHealthBar", container)
|
||||
@ -1191,9 +1241,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
|
||||
@ -1389,6 +1439,12 @@ function PTUnitFrame:SizeElements()
|
||||
local raidMarkIcon = self.raidMarkIcon.icon
|
||||
raidMarkIcon:SetAllPoints(raidMarkFrame)
|
||||
|
||||
local pvpFrame = self.pvpIcon.frame
|
||||
self:UpdateComponent(pvpFrame, profile.PVPIcon)
|
||||
|
||||
local pvpIcon = self.pvpIcon.icon
|
||||
pvpIcon:SetAllPoints(pvpFrame)
|
||||
|
||||
local auraPanel = self.auraPanel
|
||||
self:UpdateComponent(auraPanel, profile.AuraTracker)
|
||||
|
||||
@ -1460,7 +1516,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()
|
||||
|
||||
@ -29,7 +29,6 @@ ContextMenu:SetDynamicOptions(function(addOption, level, args)
|
||||
addOption("text", "Lock Position",
|
||||
"func", function(self, gui)
|
||||
PuppeteerSettings.SetFrameLocked(gui.FrameGroup.name, not self.checked)
|
||||
gui.FrameGroup:UpdateHeaderColor()
|
||||
end,
|
||||
"initFunc", function(self, gui)
|
||||
self.checked = PuppeteerSettings.IsFrameLocked(gui.FrameGroup.name)
|
||||
@ -133,14 +132,15 @@ end
|
||||
function PTUnitFrameGroup:Initialize()
|
||||
local container = CreateFrame("Frame", "PTUnitFrameGroupContainer_"..self.name, UIParent)
|
||||
self.container = container
|
||||
self:ApplyToplevel()
|
||||
if container:GetNumPoints() == 0 then
|
||||
container:SetPoint(util.GetCenterScreenPoint(0, 0))
|
||||
end
|
||||
container:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
|
||||
container:SetBackdropColor(0, 0, 0, 0.5)
|
||||
container:EnableMouse(true)
|
||||
container:SetMovable(true)
|
||||
container:SetUserPlaced(false)
|
||||
self:ApplyToplevel()
|
||||
container:ClearAllPoints()
|
||||
local anchor, x, y = PuppeteerSettings.GetFramePosition(self.name)
|
||||
container:SetPoint(anchor or "TOPLEFT", UIParent, "TOPLEFT", x or 100, y or -100)
|
||||
container:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
|
||||
container:SetBackdropColor(0, 0, 0, 0.5)
|
||||
|
||||
container:SetScript("OnMouseDown", function()
|
||||
local button = arg1
|
||||
@ -157,6 +157,7 @@ function PTUnitFrameGroup:Initialize()
|
||||
|
||||
if (util.GetKeyModifier() == PTOptions.FrameDrag.AltMoveKey) == PTOptions.FrameDrag.MoveAll then
|
||||
container:StartMoving()
|
||||
container:SetUserPlaced(false) -- StartMoving sets this and needs to be reverted
|
||||
self:RemoveToplevel()
|
||||
return
|
||||
end
|
||||
@ -188,7 +189,7 @@ function PTUnitFrameGroup:Initialize()
|
||||
container:SetScript("OnMouseUp", function()
|
||||
local button = arg1
|
||||
|
||||
if button == "RightButton" and MouseIsOver(self.header) then
|
||||
if button == "RightButton" and MouseIsOver(self.header) and self.header:IsVisible() then
|
||||
ContextMenu.FrameGroup = self
|
||||
ContextMenu:SetToggleState(false)
|
||||
ContextMenu:SetToggleState(true, container, container:GetWidth(), container:GetHeight())
|
||||
@ -205,6 +206,7 @@ function PTUnitFrameGroup:Initialize()
|
||||
if not container.bulkMovement then
|
||||
container:StopMovingOrSizing()
|
||||
self:ApplyToplevel()
|
||||
util.ConvertAnchor(container, PuppeteerSettings.GetFramePosition(self.name))
|
||||
return
|
||||
end
|
||||
|
||||
@ -215,10 +217,7 @@ function PTUnitFrameGroup:Initialize()
|
||||
for _, group in pairs(moveContainer.groups) do
|
||||
group:ApplyToplevel()
|
||||
local gc = group:GetContainer()
|
||||
local xOffset = gc:GetLeft()
|
||||
local yOffset = gc:GetTop() - GetScreenHeight()
|
||||
gc:ClearAllPoints()
|
||||
gc:SetPoint("TOPLEFT", UIParent, "TOPLEFT", xOffset, yOffset)
|
||||
util.ConvertAnchor(gc, PuppeteerSettings.GetFramePosition(group.name))
|
||||
end
|
||||
-- Prevent container from potentially blocking mouse by setting it back to 0 size
|
||||
moveContainer:SetWidth(0)
|
||||
@ -241,15 +240,15 @@ function PTUnitFrameGroup:Initialize()
|
||||
header:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
|
||||
self:UpdateHeaderColor()
|
||||
|
||||
local borderFrame = CreateFrame("Frame", "$parentBorder", container)
|
||||
self.borderFrame = borderFrame
|
||||
borderFrame:SetPoint("CENTER", container, 0, 0)
|
||||
|
||||
local label = header:CreateFontString(header, "OVERLAY", "GameFontNormal")
|
||||
self.label = label
|
||||
label:SetPoint("CENTER", header, "CENTER", 0, 0)
|
||||
label:SetText(self.name)
|
||||
|
||||
local borderFrame = CreateFrame("Frame", "$parentBorder", container)
|
||||
self.borderFrame = borderFrame
|
||||
borderFrame:SetPoint("CENTER", container, 0, 0)
|
||||
|
||||
self:ApplyProfile()
|
||||
|
||||
self:UpdateUIPositions()
|
||||
@ -276,6 +275,8 @@ function PTUnitFrameGroup:UpdateUIPositions()
|
||||
local profileHeight = profile:GetHeight()
|
||||
local maxUnitsInAxis = profile.MaxUnitsInAxis
|
||||
local orientation = profile.Orientation
|
||||
local headerEnabled = not PuppeteerSettings.IsTitleHidden(self.name)
|
||||
local headerHeight = headerEnabled and 20 or 0
|
||||
|
||||
local sortedUIs = self:GetSortedUIs()
|
||||
local splitSortedUIs = {}
|
||||
@ -309,7 +310,7 @@ function PTUnitFrameGroup:UpdateUIPositions()
|
||||
local container = ui:GetRootContainer()
|
||||
local x = orientation == "Vertical" and ((profileWidth + xSpacing) * (columnIndex - 1)) or ((profileWidth + xSpacing) * (i - 1))
|
||||
local y = orientation == "Vertical" and ((profileHeight + ySpacing) * (i - 1)) or ((profileHeight + ySpacing) * (columnIndex - 1))
|
||||
container:SetPoint("TOPLEFT", self.container, "TOPLEFT", x, -y - 20)
|
||||
container:SetPoint("TOPLEFT", self.container, "TOPLEFT", x, -y - headerHeight)
|
||||
end
|
||||
end
|
||||
|
||||
@ -322,13 +323,18 @@ function PTUnitFrameGroup:UpdateUIPositions()
|
||||
local width = orientation == "Vertical" and (profileWidth * largestRow + (xSpacing * (largestRow - 1))) or (profileWidth * largestColumn + (xSpacing * (largestColumn - 1)))
|
||||
width = math.max(width, profileWidth) -- Prevent width from being 0
|
||||
local height = orientation == "Vertical" and (profileHeight * largestColumn + (ySpacing * (largestColumn - 1))) or (profileHeight * largestRow + (ySpacing * (largestRow - 1)))
|
||||
height = height + 20
|
||||
height = height + headerHeight
|
||||
self.container:SetWidth(width)
|
||||
self.container:SetHeight(height)
|
||||
|
||||
local header = self.header
|
||||
header:SetWidth(width)
|
||||
header:SetHeight(20)
|
||||
if headerEnabled then
|
||||
header:Show()
|
||||
header:SetWidth(width)
|
||||
header:SetHeight(headerHeight)
|
||||
else
|
||||
header:Hide()
|
||||
end
|
||||
|
||||
local borderPadding = 0
|
||||
if profile.BorderStyle == "Tooltip" then
|
||||
|
||||
13
Profile.lua
13
Profile.lua
@ -206,6 +206,19 @@ function PTUIProfile.SetDefaults()
|
||||
["Opacity"] = 100
|
||||
})
|
||||
|
||||
profile.PVPIcon = createSizedObject({
|
||||
["Width"] = 14,
|
||||
["Height"] = 14,
|
||||
["AlignmentH"] = "LEFT",
|
||||
["AlignmentV"] = "TOP",
|
||||
["PaddingH"] = 0,
|
||||
["OffsetX"] = -6,
|
||||
["PaddingV"] = 0,
|
||||
["OffsetY"] = 2,
|
||||
["Anchor"] = "Container",
|
||||
["Opacity"] = 100
|
||||
})
|
||||
|
||||
profile.TrackAuras = true
|
||||
profile.AuraTracker = createSizedObject({
|
||||
["Height"] = 20,
|
||||
|
||||
@ -75,6 +75,8 @@ function InitializeDefaultProfiles()
|
||||
profile.RoleIcon.PaddingV = 0
|
||||
profile.RoleIcon.OffsetY = 5
|
||||
profile.RoleIcon.OffsetX = -5
|
||||
|
||||
profile.PVPIcon.OffsetY = -5
|
||||
end
|
||||
|
||||
|
||||
@ -107,6 +109,8 @@ function InitializeDefaultProfiles()
|
||||
profile.RoleIcon.PaddingV = 0
|
||||
profile.RoleIcon.OffsetY = 5
|
||||
profile.RoleIcon.OffsetX = -4
|
||||
|
||||
profile.PVPIcon.OffsetY = -5
|
||||
end
|
||||
|
||||
do
|
||||
@ -136,6 +140,8 @@ function InitializeDefaultProfiles()
|
||||
profile.RoleIcon.PaddingV = 0
|
||||
profile.RoleIcon.OffsetY = 6
|
||||
profile.RoleIcon.OffsetX = -5
|
||||
|
||||
profile.PVPIcon.OffsetY = -5
|
||||
end
|
||||
|
||||
do
|
||||
@ -247,6 +253,9 @@ function InitializeDefaultProfiles()
|
||||
profile.PowerDisplay = "Hidden"
|
||||
profile.PowerText.FontSize = 8
|
||||
profile.Orientation = "Vertical"
|
||||
|
||||
profile.PVPIcon.Width = 12
|
||||
profile.PVPIcon.Height = 12
|
||||
end
|
||||
|
||||
do
|
||||
@ -400,6 +409,8 @@ function InitializeDefaultProfiles()
|
||||
profile.RaidMarkIcon.Width = 16
|
||||
profile.RaidMarkIcon.Height = 16
|
||||
|
||||
profile.PVPIcon.OffsetY = -4
|
||||
|
||||
profile.BorderStyle = "Hidden"
|
||||
end
|
||||
|
||||
|
||||
@ -262,18 +262,36 @@ function OnAddonLoaded()
|
||||
-- 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
|
||||
local existing = {}
|
||||
local nextCleanup = GetTime() + 10
|
||||
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()
|
||||
for guid, units in pairs(GUIDCustomUnitMap) do
|
||||
local exists = UnitExists(guid) == 1
|
||||
local needsUpdate = false
|
||||
if (existing[guid] ~= nil) ~= exists then
|
||||
existing[guid] = exists or nil
|
||||
needsUpdate = true
|
||||
end
|
||||
|
||||
if needsManualUpdates or needsUpdate then
|
||||
PTUnit.Get(guid):UpdateAuras()
|
||||
for _, unit in ipairs(units) do
|
||||
for ui in UnitFrames(unit) do
|
||||
ui:UpdateAll()
|
||||
ui:UpdateIncomingHealing()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if GetTime() > nextCleanup then
|
||||
nextCleanup = GetTime() + 10
|
||||
for guid in pairs(existing) do
|
||||
if not GUIDCustomUnitMap[guid] then
|
||||
existing[guid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -354,6 +372,8 @@ function OnAddonLoaded()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
InitRoleDropdown()
|
||||
|
||||
SetLFTAutoRoleEnabled(PTOptions.LFTAutoRole)
|
||||
|
||||
@ -364,7 +384,7 @@ function OnAddonLoaded()
|
||||
end
|
||||
|
||||
initUnitFrames()
|
||||
StartDistanceScanner()
|
||||
StartUnitTracker()
|
||||
|
||||
PuppeteerLib:RegisterEvent("Banzai_UnitGainedAggro", function(unit)
|
||||
if PTGuidRoster then
|
||||
@ -634,10 +654,13 @@ end
|
||||
|
||||
local emptySpell = {}
|
||||
function UnitFrame_OnClick(button, unit, unitFrame)
|
||||
local binding = GetBindingFor(unit, GetKeyModifier(), button)
|
||||
if not UnitExists(unit) then
|
||||
if binding and binding.Type == "ACTION" then
|
||||
RunBinding(binding, unit, unitFrame)
|
||||
end
|
||||
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
|
||||
@ -733,7 +756,7 @@ function CheckGroup()
|
||||
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
|
||||
for _, ui in ipairs(AllUnitFrames) do
|
||||
if ui:IsShown() then
|
||||
ui:UpdateRange()
|
||||
ui:UpdateAuras()
|
||||
@ -810,4 +833,8 @@ function EndTiming(name)
|
||||
return
|
||||
end
|
||||
pfDebug_EndTiming(name)
|
||||
end
|
||||
|
||||
function PrintStack()
|
||||
print(debugstack(2))
|
||||
end
|
||||
@ -1,5 +1,5 @@
|
||||
## Interface: 11200
|
||||
## Version: 1.0.0
|
||||
## Version: 1.0.5
|
||||
## Title: Puppeteer
|
||||
## Notes: Unit frames addon tailored for healers
|
||||
## Author: OldManAlpha, Richard Truax(i2ichardt)
|
||||
@ -51,7 +51,7 @@ libs\gui\frame\SimpleDialog.lua
|
||||
Puppeteer.lua
|
||||
core\SpellsTooltip.lua
|
||||
core\EventHandler.lua
|
||||
core\DistanceScanner.lua
|
||||
core\UnitTracker.lua
|
||||
core\Command.lua
|
||||
core\OverrideBindings.lua
|
||||
core\Bindings.lua
|
||||
|
||||
@ -133,10 +133,19 @@ function SetDefaults()
|
||||
["Medium"] = 10, -- <=2 min
|
||||
["Long"] = 60 * 2 -- >2 min
|
||||
},
|
||||
["Tracking"] = {
|
||||
["EvaluateInterval"] = 1.25, -- How often everyone is fully scanned to determine if they should be closely tracked
|
||||
["DistanceUpdateInterval"] = 0.1, -- How often distance tracked units are updated
|
||||
["SightUpdateInterval"] = 0.1, -- How often sight tracked units are updated
|
||||
["MinDistanceTracking"] = 20, -- The minimum distance to start closely tracking distance
|
||||
["MaxDistanceTracking"] = 60, -- The maxmimum distance to start closely tracking distance
|
||||
["MaxSightTracking"] = 80 -- The maximum distance to closely track sight
|
||||
},
|
||||
["CastWhen"] = "Mouse Up", -- Mouse Up, Mouse Down
|
||||
["CastWhenKey"] = "Key Up", -- Key Up, Key Down
|
||||
["AutoResurrect"] = Puppeteer.ResurrectionSpells[util.GetClass("player")] ~= nil,
|
||||
["UseHealPredictions"] = true,
|
||||
["PVPFlagProtection"] = true,
|
||||
["SetMouseover"] = true,
|
||||
["LFTAutoRole"] = true, -- Turtle WoW
|
||||
["TestUI"] = false,
|
||||
@ -284,6 +293,9 @@ function SetDefaults()
|
||||
do
|
||||
local defaults = {
|
||||
["ShowLoadMessage"] = true,
|
||||
["Experiments"] = {
|
||||
["AutoRole"] = false
|
||||
},
|
||||
["OptionsVersion"] = OPTIONS_VERSION
|
||||
}
|
||||
ApplyDefaults(PTGlobalOptions, defaults)
|
||||
@ -304,6 +316,10 @@ end
|
||||
function TraverseOptions(location)
|
||||
local path = util.SplitString(location, ".")
|
||||
local currentTable = PTOptions
|
||||
if path[1] == "Global" then
|
||||
currentTable = PTGlobalOptions
|
||||
table.remove(path, 1)
|
||||
end
|
||||
for i = 1, table.getn(path) - 1 do
|
||||
currentTable = currentTable[path[i]]
|
||||
end
|
||||
@ -348,7 +364,7 @@ DefaultClassTrackedBuffs = {
|
||||
"Greater Blessing of Light", "Daybreak", "Blessing of Freedom", "Hand of Freedom", "Redoubt", "Holy Shield"},
|
||||
["PRIEST"] = {"Prayer of Fortitude", "Power Word: Fortitude", "Prayer of Spirit", "Divine Spirit",
|
||||
"Prayer of Shadow Protection", "Shadow Protection", "Holy Champion", "Champion's Grace", "Empower Champion",
|
||||
"Fear Ward", "Inner Fire", "Renew", "Greater Heal", "Lightwell Renew", "Inspiration",
|
||||
"Champion's Bond", "Fear Ward", "Inner Fire", "Renew", "Greater Heal", "Lightwell Renew", "Inspiration",
|
||||
"Fade", "Spirit Tap", "Enlighten", "Enlightened"},
|
||||
["WARRIOR"] = {"Battle Shout"},
|
||||
["DRUID"] = {"Gift of the Wild", "Mark of the Wild", "Thorns", "Rejuvenation", "Regrowth"},
|
||||
@ -456,15 +472,20 @@ function GetSelectedProfile(frame)
|
||||
return PTProfileManager.GetProfile(GetSelectedProfileName(frame))
|
||||
end
|
||||
|
||||
local function validateFrameOptionsExistence(frameName)
|
||||
if not PTOptions.FrameOptions[frameName] then
|
||||
PTOptions.FrameOptions[frameName] = {}
|
||||
end
|
||||
end
|
||||
|
||||
function IsFrameHidden(frameName)
|
||||
return PTOptions.FrameOptions[frameName] and PTOptions.FrameOptions[frameName].Hidden
|
||||
end
|
||||
|
||||
function SetFrameHidden(frameName, hidden)
|
||||
if not PTOptions.FrameOptions[frameName] then
|
||||
PTOptions.FrameOptions[frameName] = {}
|
||||
end
|
||||
validateFrameOptionsExistence(frameName)
|
||||
PTOptions.FrameOptions[frameName].Hidden = hidden
|
||||
PTSettingsGui.UpdateFrameOptions()
|
||||
end
|
||||
|
||||
function IsFrameLocked(frameName)
|
||||
@ -472,8 +493,42 @@ function IsFrameLocked(frameName)
|
||||
end
|
||||
|
||||
function SetFrameLocked(frameName, locked)
|
||||
if not PTOptions.FrameOptions[frameName] then
|
||||
PTOptions.FrameOptions[frameName] = {}
|
||||
end
|
||||
validateFrameOptionsExistence(frameName)
|
||||
PTOptions.FrameOptions[frameName].Locked = locked
|
||||
local group = Puppeteer.UnitFrameGroups[frameName]
|
||||
if group then
|
||||
group:UpdateHeaderColor()
|
||||
end
|
||||
PTSettingsGui.UpdateFrameOptions()
|
||||
end
|
||||
|
||||
function IsTitleHidden(frameName)
|
||||
return PTOptions.FrameOptions[frameName] and PTOptions.FrameOptions[frameName].TitleHidden
|
||||
end
|
||||
|
||||
function SetTitleHidden(frameName, hidden)
|
||||
validateFrameOptionsExistence(frameName)
|
||||
PTOptions.FrameOptions[frameName].TitleHidden = hidden
|
||||
local group = Puppeteer.UnitFrameGroups[frameName]
|
||||
if group then
|
||||
group:UpdateUIPositions()
|
||||
end
|
||||
PTSettingsGui.UpdateFrameOptions()
|
||||
end
|
||||
|
||||
function GetFramePosition(frameName)
|
||||
if not (PTOptions.FrameOptions[frameName] and PTOptions.FrameOptions[frameName].Position) then
|
||||
return "TOPLEFT", (GetScreenWidth() / 2), -(GetScreenHeight() / 2)
|
||||
end
|
||||
return unpack(PTOptions.FrameOptions[frameName].Position)
|
||||
end
|
||||
|
||||
function SaveFramePositions()
|
||||
for frameName, group in pairs(Puppeteer.UnitFrameGroups) do
|
||||
if not PTOptions.FrameOptions[frameName] then
|
||||
PTOptions.FrameOptions[frameName] = {}
|
||||
end
|
||||
local anchor, _, _, x, y = group:GetContainer():GetPoint(1)
|
||||
PTOptions.FrameOptions[frameName].Position = {anchor, x, y}
|
||||
end
|
||||
end
|
||||
21
README.md
21
README.md
@ -4,7 +4,7 @@
|
||||
Puppeteer, formerly HealersMate, is a unit frames addon for World of Warcraft Vanilla 1.12 that strives to be an alternative to modern WoW's VuhDo, Cell, or Healbot. Its features are tailored for healers, but can be a viable unit frames addon for any class and spec.
|
||||
|
||||
### Features
|
||||
- See health, power, marks, incoming healing, mob aggro, and relevant buffs & debuffs of your party, raid, pets, and targets
|
||||
- See health, power, marks, incoming healing, mob aggro, PvP status, and relevant buffs & debuffs of your party, raid, pets, and targets
|
||||
- Bind mouse clicks, the mouse wheel, and keys to spells
|
||||
- See your bound spells, their cost, and available mana while hovering over frames
|
||||
- Assign roles to players
|
||||
@ -23,7 +23,7 @@ Puppeteer, formerly HealersMate, is a unit frames addon for World of Warcraft Va
|
||||
### Simple, Yet Advanced Bindings
|
||||
<img align="right" width="36%" src="https://i.imgur.com/KoFygXv.png">
|
||||
|
||||
Puppeteer boasts the ability to bind mouse clicks, the mouse wheel, and keys to any combination of Ctrl/Shift/Alt modifiers. You can bind spells, macros, items, custom Lua scripts, and menus which contain multiple bindings.
|
||||
Puppeteer boasts the ability to bind mouse clicks, the mouse wheel, and keys to any combination of Shift/Ctrl/Alt modifiers. You can bind spells, macros, items, custom Lua scripts, and menus which contain multiple bindings. **Use the `/pt` command to open the configuration menu.**
|
||||
<p align="left">
|
||||
<img src="https://i.imgur.com/iglcV7z.png" width=30% align="top">
|
||||
<img src="https://i.imgur.com/7iIQTkk.png" width=30% align="top">
|
||||
@ -52,14 +52,21 @@ While not required, the mods listed below will massively improve your experience
|
||||
| Mod | Enhancement |
|
||||
| - | - |
|
||||
| SuperWoW ([GitHub](https://github.com/balakethelock/SuperWoW)) | - Shows more accurate incoming healing, and shows incoming healing from players that do not have HealComm<br>- Track the remaining duration of many buffs and HoTs on other players<br>- Allows casting on players without doing split-second target switching<br>- Lets you see accurate distance to friendly players/NPCs<br>- Lets you set units you're hovering over as your mouseover target |
|
||||
| UnitXP SP3 ([GitHub](https://github.com/allfoxwy/UnitXP_SP3)) | Allows Puppeteer to show very accurate distance to both friendly players and enemies, and show if they're out of line-of-sight |
|
||||
| UnitXP SP3 ([GitHub](https://github.com/jrc13245/UnitXP_SP3)) | Allows Puppeteer to show very accurate distance to both friendly players and enemies, and show if they're out of line-of-sight |
|
||||
| Nampower ([GitHub](https://github.com/pepopo978/nampower)) | Drastically decreases the amount of time in between casting consecutive spells |
|
||||
|
||||
### Planned Features
|
||||
### Roadmap of Major Planned Features
|
||||
|
||||
- [ ] Fully customizable unit frames
|
||||
- [ ] Customizable buff/debuff tracking
|
||||
- [ ] Support for non-English clients
|
||||
Tentative, this could change at any time.
|
||||
- [X] ~~1.0.0~~
|
||||
- ~~Overhaul bindings~~
|
||||
- ~~Lay out groundwork for GUI development~~
|
||||
- [ ] 1.1.0
|
||||
- Support non-English clients
|
||||
- Add Enemy frames (SuperWoW Required)
|
||||
- [ ] 1.2.0 and/or 1.3.0
|
||||
- Cell-like unit frame customization
|
||||
- Customizable buff/debuff tracking
|
||||
|
||||
### FAQ & Known Issues
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -315,6 +315,55 @@ function GenerateDefaultBindings()
|
||||
end
|
||||
end
|
||||
|
||||
PVPProtectOverrideTime = 0
|
||||
|
||||
PVPProtectMenu = PTGuiLib.Get("dropdown", UIParent)
|
||||
PVPProtectMenu:SetOptions({
|
||||
{
|
||||
text = colorize("PVP Flag Protection", 0.3, 1, 0.3),
|
||||
textHeight = 11,
|
||||
notCheckable = true,
|
||||
disabled = true
|
||||
},
|
||||
{
|
||||
notCheckable = true,
|
||||
disabled = true
|
||||
},
|
||||
{
|
||||
text = colorize("Whoops, thanks for the save!", 0.8, 1, 0.8),
|
||||
notCheckable = true,
|
||||
func = function()
|
||||
if UIErrorsFrame then
|
||||
UIErrorsFrame:AddMessage(colorize("No problem, stay safe", 0.2, 1, 0.2))
|
||||
end
|
||||
end
|
||||
},
|
||||
{
|
||||
notCheckable = true,
|
||||
disabled = true
|
||||
},
|
||||
{
|
||||
text = colorize("Disable protection for 5 min", 1, 0.8, 0.8),
|
||||
notCheckable = true,
|
||||
func = function()
|
||||
PVPProtectOverrideTime = GetTime() + (5 * 60)
|
||||
if UIErrorsFrame then
|
||||
UIErrorsFrame:AddMessage(colorize("Protection disabled for 5 min", 1, 0, 0))
|
||||
end
|
||||
end
|
||||
},
|
||||
{
|
||||
text = colorize("Disable protection this session", 1, 0.6, 0.6),
|
||||
notCheckable = true,
|
||||
func = function()
|
||||
PVPProtectOverrideTime = GetTime() + (1000 * 60)
|
||||
if UIErrorsFrame then
|
||||
UIErrorsFrame:AddMessage(colorize("Protection disabled this session", 1, 0, 0))
|
||||
end
|
||||
end
|
||||
}
|
||||
})
|
||||
|
||||
local Sound_Disabled = function() end
|
||||
|
||||
function RunTargetedAction(binding, unit, actionFunc, mustTempTarget)
|
||||
@ -347,6 +396,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 +422,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 +467,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 +494,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)
|
||||
@ -554,6 +617,15 @@ function RunBinding(binding, unit, unitFrame)
|
||||
local bindingType = binding.Type
|
||||
if bindingType == "SPELL" then
|
||||
if targetCastable then
|
||||
if PTOptions.PVPFlagProtection and not IsInInstance() and UnitIsPVP(unit) and UnitIsPlayer(unit)
|
||||
and not UnitIsPVP("player") and PVPProtectOverrideTime < GetTime() then
|
||||
PVPProtectMenu:SetToggleState(false)
|
||||
local frame = unitFrame:GetRootContainer()
|
||||
PVPProtectMenu:SetToggleState(true, frame, frame:GetWidth(), frame:GetHeight())
|
||||
PVPProtectMenu:SetKeepOpen(true)
|
||||
PlaySound("igMainMenuOpen")
|
||||
return
|
||||
end
|
||||
RunBinding_Spell(binding, unit)
|
||||
end
|
||||
elseif bindingType == "ACTION" then
|
||||
|
||||
@ -10,13 +10,13 @@ SlashCmdList["PUPPETEER"] = function(args)
|
||||
gc:ClearAllPoints()
|
||||
gc:SetPoint(PTUtil.GetCenterScreenPoint(gc:GetWidth(), gc:GetHeight()))
|
||||
end
|
||||
PuppeteerSettings.HM_SettingsContainer:ClearAllPoints()
|
||||
PuppeteerSettings.HM_SettingsContainer:SetPoint("CENTER", 0, 0)
|
||||
PTSettingsGui.TabFrame:ClearAllPoints()
|
||||
PTSettingsGui.TabFrame:SetPoint("CENTER", 0, 0)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("Reset all frame positions.")
|
||||
elseif args == "check" then
|
||||
Puppeteer.CheckGroup()
|
||||
elseif args == "update" then
|
||||
for _, ui in pairs(Puppeteer.AllUnitFrames) do
|
||||
for _, ui in ipairs(Puppeteer.AllUnitFrames) do
|
||||
ui:SizeElements()
|
||||
ui:UpdateAll()
|
||||
end
|
||||
@ -28,7 +28,7 @@ SlashCmdList["PUPPETEER"] = function(args)
|
||||
PTOptions.TestUI = not PTOptions.TestUI
|
||||
Puppeteer.TestUI = PTOptions.TestUI
|
||||
if PTOptions.TestUI then
|
||||
for _, ui in pairs(Puppeteer.AllUnitFrames) do
|
||||
for _, ui in ipairs(Puppeteer.AllUnitFrames) do
|
||||
ui.fakeStats = ui.GenerateFakeStats()
|
||||
ui:Show()
|
||||
end
|
||||
|
||||
@ -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,14 +110,27 @@ 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
|
||||
ui:UpdateRaidMark()
|
||||
end
|
||||
end)
|
||||
RegisterEventHandler("UNIT_FACTION", function()
|
||||
if not IsRelevantUnit(arg1) then
|
||||
return
|
||||
end
|
||||
for ui in UnitFrames(arg1) do
|
||||
ui:UpdatePVP()
|
||||
end
|
||||
end)
|
||||
RegisterEventHandler("PLAYER_LOGOUT", function()
|
||||
RemoveOverrideBindings()
|
||||
PuppeteerSettings.SaveFramePositions()
|
||||
end)
|
||||
|
||||
local GetKeyModifier = util.GetKeyModifier
|
||||
|
||||
@ -91,7 +91,10 @@ AddUpdateBindingsFrame("MainMenuMicroButton")
|
||||
AddUpdateBindingsFrame("QuestLogMicroButton")
|
||||
AddUpdateBindingsFrame("SocialsMicroButton")
|
||||
AddUpdateBindingsFrame("WorldMapMicroButton")
|
||||
AddUpdateBindingsFrame("pfActionBar") -- pfUI
|
||||
util.RunLater(function()
|
||||
AddUpdateBindingsFrame("pfActionBar") -- pfUI
|
||||
AddUpdateBindingsFrame("DFRL_HotkeyBinding") -- Dragonflight Reloaded
|
||||
end)
|
||||
|
||||
local function StopUpdateBindingsUpdates()
|
||||
if holdingFunctionsHostage then
|
||||
|
||||
152
core/Roles.lua
152
core/Roles.lua
@ -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,121 @@ 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)
|
||||
if not TalentCountRoleMap[class] then
|
||||
SetRoleAndUpdate(name, "Damage")
|
||||
return
|
||||
end
|
||||
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 +272,6 @@ do
|
||||
}
|
||||
end
|
||||
|
||||
RoleDropdown = PTGuiLib.Get("dropdown", UIParent)
|
||||
local options = {
|
||||
{
|
||||
initFunc = function(self)
|
||||
@ -178,7 +284,7 @@ do
|
||||
genRole("Tank"),
|
||||
genRole("Healer"),
|
||||
genRole("Damage"),
|
||||
genRole("No Role"),
|
||||
genRole("No Role"),
|
||||
{
|
||||
notCheckable = true,
|
||||
disabled = true
|
||||
@ -202,5 +308,39 @@ do
|
||||
func = massRoleFunc
|
||||
}
|
||||
}
|
||||
if PTGlobalOptions.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
|
||||
@ -297,8 +297,10 @@ function ApplySpellsTooltip(attachTo, unit, owner)
|
||||
powerText = colorize(powerText, powerColor)
|
||||
end
|
||||
|
||||
local modifier = util.GetKeyModifierTypeByID(1 + (options.AbbreviatedKeys and 2 or 0) + (options.ColoredKeys and 1 or 0))
|
||||
SpellsTooltip:AddDoubleLine(modifier, showPowerBar and " " or powerText, 1, 1, 1)
|
||||
local modifier = GetKeyModifier()
|
||||
local displayModifier = modifier ~= "None" and
|
||||
util.GetKeyModifierTypeByID(1 + (options.AbbreviatedKeys and 2 or 0) + (options.ColoredKeys and 1 or 0)) or " "
|
||||
SpellsTooltip:AddDoubleLine(displayModifier, showPowerBar and " " or powerText, 1, 1, 1)
|
||||
|
||||
local friendly = not UnitCanAttack("player", unit)
|
||||
|
||||
@ -315,7 +317,7 @@ function ApplySpellsTooltip(attachTo, unit, owner)
|
||||
end
|
||||
|
||||
--StartTiming("BindingDisplays")
|
||||
local entries = UpdateBindingDisplays(friendly and "Friendly" or "Hostile", GetKeyModifier())
|
||||
local entries = UpdateBindingDisplays(friendly and "Friendly" or "Hostile", modifier)
|
||||
--EndTiming("BindingDisplays")
|
||||
for _, button in ipairs(PTOptions.Buttons) do
|
||||
local focused = not CurrentlyHeldButton or button == CurrentlyHeldButton
|
||||
|
||||
@ -1,41 +1,51 @@
|
||||
PTUtil.SetEnvironment(Puppeteer)
|
||||
local _G = getfenv(0)
|
||||
|
||||
DistanceScannerFrame = CreateFrame("Frame", "PTDistanceScannerFrame", UIParent)
|
||||
UnitTrackerFrame = CreateFrame("Frame", "PTUnitTrackerFrame", UIParent)
|
||||
|
||||
local util = PTUtil
|
||||
local GetTime = GetTime
|
||||
local compost = AceLibrary("Compost-2.0")
|
||||
local TRACKING_MIN_DIST = 20
|
||||
local TRACKING_MAX_DIST = 60
|
||||
|
||||
local TRACKING_EVAL_INTERVAL = 1.25
|
||||
local RANGE_MIN_DIST = 20
|
||||
local RANGE_MAX_DIST = 60
|
||||
local SIGHT_MAX_DIST = 80
|
||||
local DISTANCE_UPDATE_INTERVAL = 0.1
|
||||
local SIGHT_UPDATE_INTERVAL = 0.1
|
||||
|
||||
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 = {}
|
||||
local sightTrackedUnits = {}
|
||||
local preciseDistance = util.CanClientGetPreciseDistance()
|
||||
local sightTrackingEnabled = util.CanClientSightCheck()
|
||||
local nextTrackingUpdate = GetTime() + 0.5
|
||||
local nextUpdate = GetTime() + 0.6
|
||||
if not preciseDistance and not sightTrackingEnabled then
|
||||
nextUpdate = nextUpdate + 99999999 -- Effectively disable updates
|
||||
local nextEval = GetTime() + 0.5
|
||||
local nextRangeUpdate = GetTime() + 0.6
|
||||
local nextSightUpdate = GetTime() + 0.6
|
||||
if not preciseDistance then
|
||||
nextRangeUpdate = nextRangeUpdate + 99999999 -- Effectively disable updates
|
||||
end
|
||||
if not sightTrackingEnabled then
|
||||
nextSightUpdate = nextSightUpdate + 99999999
|
||||
end
|
||||
|
||||
local TRACKING_UPDATE_INTERVAL = 1.25
|
||||
function LoadTrackingOptions()
|
||||
local opts = PTOptions.Tracking
|
||||
TRACKING_EVAL_INTERVAL = opts.EvaluateInterval
|
||||
RANGE_MIN_DIST = opts.MinDistanceTracking
|
||||
RANGE_MAX_DIST = opts.MaxDistanceTracking
|
||||
SIGHT_MAX_DIST = opts.MaxSightTracking
|
||||
DISTANCE_UPDATE_INTERVAL = opts.DistanceUpdateInterval
|
||||
SIGHT_UPDATE_INTERVAL = opts.SightUpdateInterval
|
||||
end
|
||||
|
||||
function RunTrackingScan()
|
||||
local UnitFrames = UnitFrames
|
||||
local time = GetTime()
|
||||
if time > nextTrackingUpdate then
|
||||
if time > nextEval then
|
||||
--StartTiming("TrackingEval")
|
||||
nextTrackingUpdate = time + TRACKING_UPDATE_INTERVAL
|
||||
nextEval = time + TRACKING_EVAL_INTERVAL
|
||||
|
||||
|
||||
compost:Erase(distanceTrackedUnits)
|
||||
@ -46,7 +56,7 @@ function RunTrackingScan()
|
||||
EvaluateTracking(guid)
|
||||
end
|
||||
else
|
||||
for _, unit in ipairs(almostAllUnits) do
|
||||
for _, unit in ipairs(AllUnits) do
|
||||
EvaluateTracking(unit)
|
||||
end
|
||||
end
|
||||
@ -60,9 +70,8 @@ function RunTrackingScan()
|
||||
--EndTiming("TrackingEval")
|
||||
end
|
||||
|
||||
--StartTiming("TrackingScan")
|
||||
if time > nextUpdate then
|
||||
nextUpdate = time + 0.1
|
||||
if time > nextRangeUpdate then
|
||||
nextRangeUpdate = time + DISTANCE_UPDATE_INTERVAL
|
||||
for _, unit in ipairs(distanceTrackedUnits) do
|
||||
local cache = PTUnit.Get(unit)
|
||||
if cache and cache:UpdateDistance() then
|
||||
@ -71,16 +80,21 @@ function RunTrackingScan()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if time > nextSightUpdate then
|
||||
nextSightUpdate = time + SIGHT_UPDATE_INTERVAL
|
||||
for _, unit in ipairs(sightTrackedUnits) do
|
||||
local cache = PTUnit.Get(unit)
|
||||
--StartTiming("SightScan")
|
||||
if cache and cache:UpdateSight() then
|
||||
for ui in UnitFrames(unit) do
|
||||
ui:UpdateSight()
|
||||
end
|
||||
end
|
||||
--EndTiming("SightScan")
|
||||
end
|
||||
end
|
||||
--EndTiming("TrackingScan")
|
||||
end
|
||||
|
||||
function EvaluateTracking(unit, update)
|
||||
@ -100,11 +114,17 @@ function EvaluateTracking(unit, update)
|
||||
end
|
||||
end
|
||||
end
|
||||
if cache:UpdatePVP() then
|
||||
for ui in UnitFrames(unit) do
|
||||
ui:UpdatePVP()
|
||||
end
|
||||
end
|
||||
local isTarget = UnitIsUnit(unit, "target")
|
||||
if PTGuidRoster then
|
||||
unit = PTGuidRoster.ResolveUnitGuid(unit)
|
||||
end
|
||||
if isTarget or (dist < TRACKING_MAX_DIST and dist > TRACKING_MIN_DIST) then -- Only closely track units that are close to the range threshold
|
||||
-- Only closely track units that are close to the range threshold
|
||||
if isTarget or (dist < RANGE_MAX_DIST and dist > RANGE_MIN_DIST) then
|
||||
if not update or not util.ArrayContains(distanceTrackedUnits, unit) then
|
||||
table.insert(distanceTrackedUnits, unit)
|
||||
end
|
||||
@ -116,6 +136,7 @@ function EvaluateTracking(unit, update)
|
||||
end
|
||||
end
|
||||
|
||||
function StartDistanceScanner()
|
||||
DistanceScannerFrame:SetScript("OnUpdate", RunTrackingScan)
|
||||
function StartUnitTracker()
|
||||
LoadTrackingOptions()
|
||||
UnitTrackerFrame:SetScript("OnUpdate", RunTrackingScan)
|
||||
end
|
||||
151
gui/Settings.lua
151
gui/Settings.lua
@ -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")
|
||||
@ -393,6 +393,9 @@ function CreateTab_Options_Casting(panel)
|
||||
local autoResInfo = not resSpell and "This does nothing for your class" or {"Replaces your bound spells with "..resSpell..
|
||||
" when clicking on a dead ally", "All other types of binds, such as Actions, will not be replaced"}
|
||||
factory:checkbox("Auto Resurrect", autoResInfo, "AutoResurrect")
|
||||
factory:checkbox("PVP Flag Protection", {"Stops you from casting spells on PVP flagged players if you're not flagged",
|
||||
"Attempting to cast will prompt you to make an exception",
|
||||
"Only stops you from using Spell bindings"}, "PVPFlagProtection")
|
||||
factory:checkbox("Target While Casting", {"Target the unit while most bindings run",
|
||||
"Note that these binding types override this rule:",
|
||||
"Spell - Always targets unless using SuperWoW",
|
||||
@ -436,7 +439,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 +480,37 @@ 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 experimentsLabel = CreateLabel(container, "Experiments")
|
||||
:SetPoint("TOP", container, "TOP", 0, -20)
|
||||
:SetFontSize(14)
|
||||
local experimentsInfo = CreateLabel(container, "Features which are not complete and/or need more testing. Use at your own risk.")
|
||||
:SetWidth(TEXT_WIDTH)
|
||||
:SetPoint("TOP", experimentsLabel, "BOTTOM", 0, -5)
|
||||
layout:offset(0, -70)
|
||||
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)}, "Global.Experiments.AutoRole",
|
||||
Puppeteer.InitRoleDropdown)
|
||||
|
||||
local scriptsLabel = CreateLabel(container, "Load & Postload Scripts")
|
||||
:SetPoint("TOP", container, "TOP", 0, -105)
|
||||
: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)
|
||||
@ -537,7 +555,7 @@ function CreateTab_Options_Advanced(panel)
|
||||
editor:GetEditbox():SetFocus()
|
||||
AddOverlayFrame(editor)
|
||||
end)
|
||||
local reloadInfo = CreateLabel(container, "A reload or relog is required for any changes to take effect.")
|
||||
local reloadInfo = CreateLabel(container, "A reload or relog is required for any script changes to take effect.")
|
||||
:SetWidth(TEXT_WIDTH)
|
||||
:SetPoint("TOP", postLoadScriptButton, "BOTTOM", 0, -20)
|
||||
local reloadButton = PTGuiLib.Get("button", container)
|
||||
@ -581,7 +599,8 @@ function CreateTab_Options_Mods(panel)
|
||||
"• Enhances spell casting by directly casting on targets rather than split-second target switching tricks\n"..
|
||||
"• Allows you to see accurate distance to other friendly players and NPCs\n"..
|
||||
"• Mousing over unit frames properly sets your mouseover target\n"..
|
||||
"• Shows incoming healing from players that do not have HealComm and predicts more accurate numbers")
|
||||
"• Shows incoming healing from players that do not have HealComm and predicts more accurate numbers\n"..
|
||||
"• Add players/mobs to a separate Focus frame (By using the Focus action bind)")
|
||||
:SetJustifyH("LEFT")
|
||||
:SetWidth(TEXT_WIDTH)
|
||||
:SetPoint("TOP", superWowDetectedLabel, "BOTTOM", 0, -10)
|
||||
@ -615,7 +634,7 @@ function CreateTab_Options_Mods(panel)
|
||||
:SetJustifyH("LEFT")
|
||||
:SetWidth(TEXT_WIDTH)
|
||||
:SetPoint("TOP", unitXPDetectedLabel, "BOTTOM", 0, -10)
|
||||
local unitXPLink = CreateLinkEditbox(container, "https://github.com/allfoxwy/UnitXP_SP3")
|
||||
local unitXPLink = CreateLinkEditbox(container, "https://github.com/jrc13245/UnitXP_SP3")
|
||||
:SetPoint("TOP", unitXPInfo, "BOTTOM", 0, -5)
|
||||
:SetSize(300, 20)
|
||||
local unitXPLinkLabel = CreateLabel(container, "Link:")
|
||||
@ -649,10 +668,20 @@ end
|
||||
|
||||
function CreateTab_Customize()
|
||||
local container = TabFrame:CreateTab("Customize")
|
||||
local layout = NewLabeledColumnLayout(container, {100, 340}, -40, 10)
|
||||
|
||||
local frameStyleContainer = PTGuiLib.Get("container", container)
|
||||
:SetSimpleBackground()
|
||||
:SetPoint("TOPLEFT", container, "TOPLEFT", 5, -26)
|
||||
:SetPoint("BOTTOMRIGHT", container, "TOPRIGHT", -5, -155)
|
||||
local layout = NewLabeledColumnLayout(frameStyleContainer, {100, 340, 175}, -25, 5)
|
||||
|
||||
local frameSettingsText = CreateLabel(frameStyleContainer, "Frame Group Settings")
|
||||
:SetPoint("TOP", frameStyleContainer, "TOP", 0, -5)
|
||||
:SetFontSize(14)
|
||||
|
||||
|
||||
local preferredFrameOrder = {"Party", "Pets", "Raid", "Raid Pets", "Target", "Focus"}
|
||||
local frameDropdown = CreateLabeledDropdown(container, "Select Frame", "The frame to edit the style of")
|
||||
local frameDropdown = CreateLabeledDropdown(frameStyleContainer, "Configure Frame", "The frame to edit the attributes of")
|
||||
:SetWidth(150)
|
||||
:SetDynamicOptions(function(addOption, level, args)
|
||||
for _, name in ipairs(preferredFrameOrder) do
|
||||
@ -677,14 +706,15 @@ function CreateTab_Customize()
|
||||
end,
|
||||
func = function(self, gui)
|
||||
StyleDropdown:UpdateText()
|
||||
HideFrameCheckbox:SetChecked(PuppeteerSettings.IsFrameHidden(self.text))
|
||||
AnchorDropdown:UpdateText()
|
||||
UpdateFrameOptions()
|
||||
end
|
||||
})
|
||||
:SetText("Party")
|
||||
FrameDropdown = frameDropdown
|
||||
layout:layoutComponent(frameDropdown)
|
||||
layout:column(3):layoutComponent(frameDropdown)
|
||||
local GetSelectedProfileName = PuppeteerSettings.GetSelectedProfileName
|
||||
local styleDropdown = CreateLabeledDropdown(container, "Choose Style", "The style of the frame")
|
||||
local styleDropdown = CreateLabeledDropdown(frameStyleContainer, "Choose Style", "The style of the frame")
|
||||
:SetWidth(150)
|
||||
:SetDynamicOptions(function(addOption, level, args)
|
||||
local profiles = PTProfileManager.GetProfileNames()
|
||||
@ -736,22 +766,83 @@ function CreateTab_Customize()
|
||||
self:SetText(GetSelectedProfileName(frameDropdown:GetText()))
|
||||
end)
|
||||
StyleDropdown = styleDropdown
|
||||
layout:offset(0, 10):layoutComponent(styleDropdown)
|
||||
layout:column(1):offset(0, -30):layoutComponent(styleDropdown)
|
||||
|
||||
local hideFrameCheckbox = CreateLabeledCheckbox(container, "Hide Frame", "If checked, this frame will not be visible")
|
||||
local anchors = {"TOPLEFT", "TOP", "TOPRIGHT", "LEFT", "CENTER", "RIGHT", "BOTTOMLEFT", "BOTTOM", "BOTTOMRIGHT"}
|
||||
local readableAnchorMap = {
|
||||
TOPLEFT = "Top Left",
|
||||
TOP = "Top",
|
||||
TOPRIGHT = "Top Right",
|
||||
LEFT = "Left",
|
||||
CENTER = "Center",
|
||||
RIGHT = "Right",
|
||||
BOTTOMLEFT = "Bottom Left",
|
||||
BOTTOM = "Bottom",
|
||||
BOTTOMRIGHT = "Bottom Right"
|
||||
}
|
||||
local anchorDropdown = CreateLabeledDropdown(frameStyleContainer, "Anchor",
|
||||
{"The point the frame is anchored to, affecting the direction it expands/retracts",
|
||||
"Top Left: Expands right and down",
|
||||
"Top: Expands equally left & right and down",
|
||||
"Top Right: Expands left and down",
|
||||
"Left: Expands right and equally up & down",
|
||||
"Center: Expands equally in all directions",
|
||||
"Right: Expands left and equally up & down",
|
||||
"Bottom Left: Expands right and up",
|
||||
"Bottom: Expands equally left & right and up",
|
||||
"Bottom Right: Expands left and up",})
|
||||
:SetWidth(150)
|
||||
:SetSimpleOptions(anchors, function(option)
|
||||
return {
|
||||
initFunc = function(self)
|
||||
self.checked = PuppeteerSettings.GetFramePosition(frameDropdown:GetText()) == option
|
||||
end,
|
||||
func = function(self, gui)
|
||||
local group = Puppeteer.UnitFrameGroups[frameDropdown:GetText()]
|
||||
util.ConvertAnchor(group:GetContainer(), option)
|
||||
PuppeteerSettings.SaveFramePositions()
|
||||
gui:UpdateText()
|
||||
end,
|
||||
text = readableAnchorMap[option]
|
||||
}
|
||||
end)
|
||||
:SetTextUpdater(function(self)
|
||||
self:SetText(readableAnchorMap[PuppeteerSettings.GetFramePosition(frameDropdown:GetText())])
|
||||
end)
|
||||
layout:layoutComponent(anchorDropdown)
|
||||
AnchorDropdown = anchorDropdown
|
||||
|
||||
local lockFrameCheckbox = CreateLabeledCheckbox(frameStyleContainer, "Lock Frame", {"If checked, this frame will not be movable",
|
||||
"Note: This setting is also accessible by right-clicking the group title bar"})
|
||||
:OnClick(function(self)
|
||||
local frameName = frameDropdown:GetText()
|
||||
PuppeteerSettings.SetFrameLocked(frameName, self:GetChecked() == 1)
|
||||
end)
|
||||
layout:column(2):offset(0, -30):layoutComponent(lockFrameCheckbox)
|
||||
LockFrameCheckbox = lockFrameCheckbox
|
||||
|
||||
local hideTitleCheckbox = CreateLabeledCheckbox(frameStyleContainer, "Hide Title", {"If checked, the title of this frame will be hidden",
|
||||
colorize("Note: When you want to move the frame, you need to enable the title!", 1, 0.4, 0.4)})
|
||||
:OnClick(function(self)
|
||||
local frameName = frameDropdown:GetText()
|
||||
PuppeteerSettings.SetTitleHidden(frameName, self:GetChecked() == 1)
|
||||
end)
|
||||
layout:layoutComponent(hideTitleCheckbox)
|
||||
HideTitleCheckbox = hideTitleCheckbox
|
||||
|
||||
local hideFrameCheckbox = CreateLabeledCheckbox(frameStyleContainer, "Hide Frame", "If checked, this frame will not be visible")
|
||||
:OnClick(function(self)
|
||||
local frameName = frameDropdown:GetText()
|
||||
if not PTOptions.FrameOptions[frameName] then
|
||||
PTOptions.FrameOptions[frameName] = {}
|
||||
end
|
||||
PuppeteerSettings.SetFrameHidden(frameName, self:GetChecked() == 1)
|
||||
Puppeteer.CheckGroup()
|
||||
end)
|
||||
layout:column(2):levelAt(1):layoutComponent(hideFrameCheckbox)
|
||||
layout:layoutComponent(hideFrameCheckbox)
|
||||
HideFrameCheckbox = hideFrameCheckbox
|
||||
|
||||
UpdateFrameOptions()
|
||||
|
||||
local overrideContainer = PTGuiLib.Get("scroll_frame", container)
|
||||
:SetPoint("TOPLEFT", container, "TOPLEFT", 5, -100)
|
||||
:SetPoint("TOPLEFT", frameStyleContainer, "BOTTOMLEFT", 0, -5)
|
||||
:SetPoint("BOTTOMRIGHT", container, "BOTTOMRIGHT", -5, 5)
|
||||
:SetSimpleBackground()
|
||||
StyleOverrideContainer = overrideContainer
|
||||
@ -810,19 +901,27 @@ function CreateTab_Customize()
|
||||
add(createDropdown("Health Bar Color", nil, "HealthBarColor", {"Green To Red", "Green", "Class"}), -10)
|
||||
add(createDropdown("Health Bar Texture", nil, "HealthBarStyle", barStyles))
|
||||
add(createDropdown("Health Display", "What kind of text is displayed as health", "HealthDisplay", {"Health", "Health/Max Health", "% Health", "Hidden"}))
|
||||
add(createDropdown("Missing Health Display", "What kind of text is displayed as missing health", "MissingHealthDisplay", {"Hidden", "-Health", "-% Health"}))
|
||||
add(createDropdown("Missing Health Display", "What kind of text is displayed as missing health", "MissingHealthDisplay", {"-Health", "-% Health", "Hidden"}))
|
||||
add(createDropdown("Incoming Heal Display", nil, "IncomingHealDisplay", {"Overheal", "Heal", "Hidden"}))
|
||||
add(createDropdown("Power Bar Texture", nil, "PowerBarStyle", barStyles))
|
||||
add(createDropdown("Power Display", "What kind of text is displayed as missing", "PowerDisplay", {"Power", "Power/Max Power", "% Power", "Hidden"}))
|
||||
add(createDropdown("Power Display", "What kind of text is displayed as power", "PowerDisplay", {"Power", "Power/Max Power", "% Power", "Hidden"}))
|
||||
add(createDropdown("Name Text Color", "'Default' is default Blizzard yellow text", "NameText.Color", {"Class", "Default"}))
|
||||
add(createDropdown("Show Debuff Colors On", nil, "ShowDebuffColorsOn", {"Health Bar", "Name", "Health", "Hidden"}))
|
||||
add(createDropdown("Sort Units By", "The sorting algorithm for units in a group", "SortUnitsBy", {"ID", "Name", "Class Name"}))
|
||||
add(createDropdown("Growth Direction", "Vertical grows units down, Horizontal grows units right", "Orientation", {"Vertical", "Horizontal"}))
|
||||
add(createDropdown("Growth Orientation", "Vertical grows units up and down, Horizontal grows units left and right", "Orientation", {"Vertical", "Horizontal"}))
|
||||
add(createDropdown("Border Style", "The border of the group", "BorderStyle", {"Tooltip", "Dialog Box", "Borderless"}))
|
||||
add(createDropdown("Max Units In Axis", "The maximum number of units in the growth axis until it must shift down", "MaxUnitsInAxis", {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))
|
||||
add(createDropdown("Min Units X", "The minimum amount of unit space to take on the X-axis", "MinUnitsX", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))
|
||||
add(createDropdown("Min Units Y", "The minimum amount of unit space to take on the Y-axis", "MinUnitsY", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))
|
||||
add(createDropdown("Horizontal Spacing", "The number of pixels between units", "HorizontalSpacing", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))
|
||||
add(createDropdown("Vertical Spacing", "The number of pixels between units", "VerticalSpacing", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))
|
||||
add(createDropdown("Out of Range Opacity", "How opaque out of range players appear in %", "OutOfRangeOpacity", {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}))
|
||||
end
|
||||
|
||||
function UpdateFrameOptions()
|
||||
LockFrameCheckbox:SetChecked(PuppeteerSettings.IsFrameLocked(FrameDropdown:GetText()))
|
||||
HideTitleCheckbox:SetChecked(PuppeteerSettings.IsTitleHidden(FrameDropdown:GetText()))
|
||||
HideFrameCheckbox:SetChecked(PuppeteerSettings.IsFrameHidden(FrameDropdown:GetText()))
|
||||
end
|
||||
|
||||
StyleOverrideComponents = {}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -323,7 +323,8 @@ function PTSpellLine:Update()
|
||||
self:SetEnabledContent("editbox")
|
||||
self:GetTypeDropdown():SetText("Macro")
|
||||
self:GetContentEditbox():SetText(binding.Data or "")
|
||||
self:GetContentEditbox():ApplyTooltip("Enter the name of one of your macros")
|
||||
self:GetContentEditbox():ApplyTooltip("Enter the name of one of your macros",
|
||||
"Note that macro binds won't target unless you enable", "\"Target While Casting\" in this binding's settings or globally")
|
||||
self:ApplySearchableEditbox("MACRO", SearchMacros, 1)
|
||||
elseif binding.Type == "ITEM" then
|
||||
self:SetEnabledContent("editbox")
|
||||
|
||||
@ -9,7 +9,7 @@ local turtle = PTUtil.IsTurtleWow()
|
||||
local trackedCastedAuras = {
|
||||
-- Druid
|
||||
["Rejuvenation"] = 12,
|
||||
["Regrowth"] = 21,
|
||||
["Regrowth"] = turtle and 20 or 21,
|
||||
["Mark of the Wild"] = 30 * 60,
|
||||
["Gift of the Wild"] = 60 * 60,
|
||||
["Thorns"] = 10 * 60,
|
||||
@ -33,6 +33,7 @@ local trackedCastedAuras = {
|
||||
["Fear Ward"] = 10 * 60,
|
||||
["Champion's Grace"] = 30 * 60,
|
||||
["Empower Champion"] = 10 * 60,
|
||||
["Champion's Bond"] = 10 * 60,
|
||||
["Spirit of Redemption"] = 10,
|
||||
["Abolish Disease"] = 20,
|
||||
["Inner Fire"] = 10 * 60,
|
||||
|
||||
@ -24,12 +24,17 @@ function ResetRoster()
|
||||
end
|
||||
|
||||
function PopulateRoster()
|
||||
for _, unit in ipairs(util.AllUnits) do
|
||||
for _, unit in ipairs(util.AllRealUnits) do
|
||||
local exists, guid = UnitExists(unit)
|
||||
if exists then
|
||||
AddUnit(guid, unit)
|
||||
end
|
||||
end
|
||||
for guid, units in pairs(PTUnitProxy.GUIDCustomUnitMap) do
|
||||
for _, unit in ipairs(units) do
|
||||
AddUnit(guid, unit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AddUnit(guid, unit)
|
||||
|
||||
@ -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"]
|
||||
|
||||
@ -8,8 +8,10 @@ local _G = getfenv(0)
|
||||
local util = PTUtil
|
||||
local GetAuraInfo = util.GetAuraInfo
|
||||
local AllUnits = util.AllUnits
|
||||
local AllRealUnits = util.AllRealUnits
|
||||
local AllUnitsSet = util.AllUnitsSet
|
||||
local superwow = util.IsSuperWowPresent()
|
||||
local canGetAuraIDs = util.CanClientGetAuraIDs()
|
||||
|
||||
local compost = AceLibrary("Compost-2.0")
|
||||
|
||||
@ -35,6 +37,8 @@ PTUnit.HasHealingModifier = false
|
||||
-- Only used with SuperWoW, managed in AuraTracker.lua
|
||||
PTUnit.AuraTimes = {} -- Key: Aura Name | Value: {"startTime", "duration"}
|
||||
|
||||
PTUnit.DisplayPVP = false -- This is not the real PVP status of the unit, this is affected by other conditions
|
||||
|
||||
PTUnit.Distance = 0
|
||||
PTUnit.InSight = true
|
||||
PTUnit.IsNew = false
|
||||
@ -53,7 +57,7 @@ end
|
||||
function UpdateGuidCaches()
|
||||
local cached = PTUnit.Cached
|
||||
local prevCached = PTUtil.CloneTableCompost(cached)
|
||||
for _, unit in ipairs(AllUnits) do
|
||||
for _, unit in ipairs(AllRealUnits) do
|
||||
local exists, guid = UnitExists(unit)
|
||||
if exists then
|
||||
if not cached[guid] then
|
||||
@ -92,7 +96,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 +111,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
|
||||
@ -128,6 +133,7 @@ end
|
||||
|
||||
function PTUnit:UpdateAll()
|
||||
self:UpdateAuras()
|
||||
self:UpdatePVP()
|
||||
self:UpdateDistance()
|
||||
self:UpdateSight()
|
||||
end
|
||||
@ -140,13 +146,29 @@ function PTUnit:CheckNew()
|
||||
end
|
||||
end
|
||||
|
||||
function PTUnit:UpdatePVP()
|
||||
if not self.Unit then
|
||||
return
|
||||
end
|
||||
local shouldDisplay = UnitIsPVP(self.Unit) and (not IsInInstance() or not UnitIsVisible(self.Unit))
|
||||
if self.DisplayPVP ~= shouldDisplay then
|
||||
self.DisplayPVP = shouldDisplay
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function PTUnit:ShouldDisplayPVP()
|
||||
return self.DisplayPVP
|
||||
end
|
||||
|
||||
-- Returns true if the distance changed
|
||||
function PTUnit:UpdateDistance()
|
||||
if not self.Unit then
|
||||
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 +183,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 +224,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 +256,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 +264,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 +280,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 +290,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
|
||||
@ -304,14 +318,14 @@ function PTUnit:HasBuff(name)
|
||||
return self.BuffsMap[name] ~= nil
|
||||
end
|
||||
|
||||
-- SuperWoW only
|
||||
-- SuperWoW/Turtle WoW only
|
||||
function PTUnit:HasBuffID(id)
|
||||
return self.BuffsIDSet[id] ~= nil
|
||||
end
|
||||
|
||||
-- Looks for ID if SuperWoW is present, otherwise searches by name
|
||||
-- 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)
|
||||
@ -321,14 +335,14 @@ function PTUnit:HasDebuff(name)
|
||||
return self.DebuffsMap[name] ~= nil
|
||||
end
|
||||
|
||||
-- SuperWoW only
|
||||
-- SuperWoW/Turtle WoW only
|
||||
function PTUnit:HasDebuffID(id)
|
||||
return self.DebuffsIDSet[id] ~= nil
|
||||
end
|
||||
|
||||
-- Looks for ID if SuperWoW is present, otherwise searches by name
|
||||
-- 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 +377,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
|
||||
|
||||
@ -407,6 +407,8 @@ function CreateUnitProxies()
|
||||
UnitProxy("FollowUnit", _G.FollowUnit, nil)
|
||||
UnitProxy("AssistUnit", _G.AssistUnit, nil)
|
||||
UnitProxy("UnitAffectingCombat", _G.UnitAffectingCombat, false)
|
||||
UnitProxy("UnitIsPVP", _G.UnitIsPVP, false)
|
||||
UnitProxy("UnitFactionGroup", _G.UnitFactionGroup, nil)
|
||||
DoubleUnitProxy("UnitIsFriend", _G.UnitIsFriend, false)
|
||||
DoubleUnitProxy("UnitIsEnemy", _G.UnitIsEnemy, false)
|
||||
DoubleUnitProxy("UnitIsUnit", _G.UnitIsUnit, false)
|
||||
|
||||
@ -35,7 +35,7 @@ if SUPERWOW_VERSION then
|
||||
end
|
||||
Nampower = QueueSpellByName ~= nil
|
||||
|
||||
TurtleWow = true
|
||||
TurtleWow = TURTLE_WOW_VERSION ~= nil
|
||||
|
||||
PowerColors = {
|
||||
["mana"] = {0.1, 0.25, 1}, --{r = 0, g = 0, b = 0.882}, Not accurate, changed color to make brighter
|
||||
@ -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,36 @@ 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
|
||||
if not id then -- Uh oh, Turtle lost the ID
|
||||
return ScanAuraInfo(unit, index, type)
|
||||
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
|
||||
@ -1030,6 +1077,34 @@ function GetCenterScreenPoint(componentWidth, componentHeight)
|
||||
return "TOPLEFT", (GetScreenWidth() / 2) - (componentWidth / 2), -((GetScreenHeight() / 2) - (componentHeight / 2))
|
||||
end
|
||||
|
||||
-- Keeps the frame at the current position, while modifying the anchor point
|
||||
function ConvertAnchor(frame, anchor)
|
||||
local leftX, rightX, topY, bottomY = frame:GetLeft(), frame:GetRight(), frame:GetTop(), frame:GetBottom()
|
||||
local centerX, centerY = frame:GetCenter()
|
||||
local x, y
|
||||
if anchor == "TOPLEFT" then
|
||||
x, y = leftX, topY
|
||||
elseif anchor == "TOPRIGHT" then
|
||||
x, y = rightX, topY
|
||||
elseif anchor == "BOTTOMLEFT" then
|
||||
x, y = leftX, bottomY
|
||||
elseif anchor == "BOTTOMRIGHT" then
|
||||
x, y = rightX, bottomY
|
||||
elseif anchor == "TOP" then
|
||||
x, y = centerX, topY
|
||||
elseif anchor == "BOTTOM" then
|
||||
x, y = centerX, bottomY
|
||||
elseif anchor == "LEFT" then
|
||||
x, y = leftX, centerY
|
||||
elseif anchor == "RIGHT" then
|
||||
x, y = rightX, centerY
|
||||
elseif anchor == "CENTER" then
|
||||
x, y = centerX, centerY
|
||||
end
|
||||
frame:ClearAllPoints()
|
||||
frame:SetPoint(anchor, UIParent, "TOPLEFT", x, y - GetScreenHeight())
|
||||
end
|
||||
|
||||
function GetPowerType(unit)
|
||||
return PowerTypeMap[UnitPowerType(unit)]
|
||||
end
|
||||
@ -1151,6 +1226,10 @@ function CanClientSightCheck()
|
||||
return UnitXPSP3
|
||||
end
|
||||
|
||||
function CanClientGetAuraIDs()
|
||||
return SuperWoW or TurtleWow
|
||||
end
|
||||
|
||||
function IsSuperWowPresent()
|
||||
return SuperWoW
|
||||
end
|
||||
|
||||
@ -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)
|
||||
Loading…
Reference in New Issue
Block a user