mirror of
https://github.com/OldManAlpha/Puppeteer.git
synced 2025-11-28 23:48:35 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
899408c4e9 | ||
|
|
8b67661ed9 | ||
|
|
7be8640a6f | ||
|
|
c8fceaf243 | ||
|
|
224f329d08 | ||
|
|
5e4a63d651 | ||
|
|
34f549744e | ||
|
|
e1898c1486 | ||
|
|
e3ba7e831c | ||
|
|
27bd99c7a8 | ||
|
|
0faa8b9184 | ||
|
|
30da69e21b | ||
|
|
f7563933ee | ||
|
|
ad54a21b6a | ||
|
|
93a0594410 | ||
|
|
be859b3b90 | ||
|
|
b44605879e | ||
|
|
5049852079 |
@ -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)
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -132,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
|
||||
@ -156,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
|
||||
@ -187,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())
|
||||
@ -204,6 +206,7 @@ function PTUnitFrameGroup:Initialize()
|
||||
if not container.bulkMovement then
|
||||
container:StopMovingOrSizing()
|
||||
self:ApplyToplevel()
|
||||
util.ConvertAnchor(container, PuppeteerSettings.GetFramePosition(self.name))
|
||||
return
|
||||
end
|
||||
|
||||
@ -214,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)
|
||||
@ -240,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()
|
||||
@ -275,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 = {}
|
||||
@ -308,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
|
||||
|
||||
@ -321,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
|
||||
@ -366,7 +384,7 @@ function OnAddonLoaded()
|
||||
end
|
||||
|
||||
initUnitFrames()
|
||||
StartDistanceScanner()
|
||||
StartUnitTracker()
|
||||
|
||||
PuppeteerLib:RegisterEvent("Banzai_UnitGainedAggro", function(unit)
|
||||
if PTGuidRoster then
|
||||
@ -738,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()
|
||||
@ -815,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.4
|
||||
## 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,13 +133,19 @@ function SetDefaults()
|
||||
["Medium"] = 10, -- <=2 min
|
||||
["Long"] = 60 * 2 -- >2 min
|
||||
},
|
||||
["Experiments"] = {
|
||||
["AutoRole"] = false
|
||||
["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,
|
||||
@ -287,6 +293,9 @@ function SetDefaults()
|
||||
do
|
||||
local defaults = {
|
||||
["ShowLoadMessage"] = true,
|
||||
["Experiments"] = {
|
||||
["AutoRole"] = false
|
||||
},
|
||||
["OptionsVersion"] = OPTIONS_VERSION
|
||||
}
|
||||
ApplyDefaults(PTGlobalOptions, defaults)
|
||||
@ -307,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
|
||||
@ -459,14 +472,18 @@ 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
|
||||
@ -476,13 +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
|
||||
|
||||
|
||||
@ -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)
|
||||
@ -568,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
|
||||
|
||||
@ -120,8 +120,17 @@ RegisterEventHandler("RAID_TARGET_UPDATE", function()
|
||||
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
|
||||
|
||||
@ -308,7 +308,7 @@ function InitRoleDropdown()
|
||||
func = massRoleFunc
|
||||
}
|
||||
}
|
||||
if PTOptions.Experiments.AutoRole then
|
||||
if PTGlobalOptions.Experiments.AutoRole then
|
||||
table.insert(options, 6, {
|
||||
text = colorize("Auto Detect", 1, 0.6, 0),
|
||||
func = function()
|
||||
|
||||
@ -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,34 +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 AllUnits = util.AllUnits
|
||||
|
||||
local distanceTrackedUnits = util.CloneTable(AllUnits) -- Initially scan all units
|
||||
local sightTrackedUnits = util.CloneTable(AllUnits)
|
||||
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)
|
||||
@ -53,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
|
||||
@ -64,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)
|
||||
@ -93,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
|
||||
@ -109,6 +136,7 @@ function EvaluateTracking(unit, update)
|
||||
end
|
||||
end
|
||||
|
||||
function StartDistanceScanner()
|
||||
DistanceScannerFrame:SetScript("OnUpdate", RunTrackingScan)
|
||||
function StartUnitTracker()
|
||||
LoadTrackingOptions()
|
||||
UnitTrackerFrame:SetScript("OnUpdate", RunTrackingScan)
|
||||
end
|
||||
104
gui/Settings.lua
104
gui/Settings.lua
@ -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",
|
||||
@ -489,8 +492,19 @@ function CreateTab_Options_Advanced(panel)
|
||||
|
||||
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, -10)
|
||||
: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, "..
|
||||
@ -541,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)
|
||||
@ -551,14 +565,6 @@ 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)
|
||||
@ -593,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)
|
||||
@ -627,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:")
|
||||
@ -665,8 +672,8 @@ function CreateTab_Customize()
|
||||
local frameStyleContainer = PTGuiLib.Get("container", container)
|
||||
:SetSimpleBackground()
|
||||
:SetPoint("TOPLEFT", container, "TOPLEFT", 5, -26)
|
||||
:SetPoint("BOTTOMRIGHT", container, "TOPRIGHT", -5, -120)
|
||||
local layout = NewLabeledColumnLayout(frameStyleContainer, {100, 340}, -35, 10)
|
||||
: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)
|
||||
@ -674,7 +681,7 @@ function CreateTab_Customize()
|
||||
|
||||
|
||||
local preferredFrameOrder = {"Party", "Pets", "Raid", "Raid Pets", "Target", "Focus"}
|
||||
local frameDropdown = CreateLabeledDropdown(frameStyleContainer, "Select Frame", "The frame to edit the attributes 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
|
||||
@ -699,12 +706,13 @@ function CreateTab_Customize()
|
||||
end,
|
||||
func = function(self, gui)
|
||||
StyleDropdown:UpdateText()
|
||||
AnchorDropdown:UpdateText()
|
||||
UpdateFrameOptions()
|
||||
end
|
||||
})
|
||||
:SetText("Party")
|
||||
FrameDropdown = frameDropdown
|
||||
layout:layoutComponent(frameDropdown)
|
||||
layout:column(3):layoutComponent(frameDropdown)
|
||||
local GetSelectedProfileName = PuppeteerSettings.GetSelectedProfileName
|
||||
local styleDropdown = CreateLabeledDropdown(frameStyleContainer, "Choose Style", "The style of the frame")
|
||||
:SetWidth(150)
|
||||
@ -758,7 +766,51 @@ 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 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"})
|
||||
@ -766,9 +818,18 @@ function CreateTab_Customize()
|
||||
local frameName = frameDropdown:GetText()
|
||||
PuppeteerSettings.SetFrameLocked(frameName, self:GetChecked() == 1)
|
||||
end)
|
||||
layout:column(2):layoutComponent(lockFrameCheckbox)
|
||||
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()
|
||||
@ -840,23 +901,26 @@ 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 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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -8,6 +8,7 @@ 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()
|
||||
@ -36,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
|
||||
@ -54,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
|
||||
@ -130,6 +133,7 @@ end
|
||||
|
||||
function PTUnit:UpdateAll()
|
||||
self:UpdateAuras()
|
||||
self:UpdatePVP()
|
||||
self:UpdateDistance()
|
||||
self:UpdateSight()
|
||||
end
|
||||
@ -142,6 +146,22 @@ 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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -1077,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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user