Skip to content

Commit ee41e79

Browse files
author
mergetest
committed
Merge PR #220: pet frames never appeared in arena (2v2 / 3v3 / shuffle)
# Conflicts: # CHANGELOG.md
2 parents c874c36 + 629d0b8 commit ee41e79

3 files changed

Lines changed: 141 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* (Click Casting) Fixed keyboard binds going dead on every frame for a whole fight when combat interrupted a binding refresh — typically zoning into a raid and a pull starting seconds later. (by Krathe)
99
* (Click Casting) Fixed hover keybinds dying for the rest of the session on some frames after visiting player housing. (by Krathe)
1010
* (Click Casting) Fixed cast-on-down silently switching itself off on Blizzard's own raid and party frames after every roster change. (by Krathe)
11+
* (Pet Frames) Fixed pet frames never appearing in arena (2v2, 3v3 and Solo Shuffle). Arena counts as a raid to the game, so pet frames were being looked for on the raid frames — which arena does not use. They now build alongside the arena frames, and follow your Party pet settings. (by Krathe)
1112

1213
### Improvements
1314

Core.lua

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5528,7 +5528,15 @@ DF._MainEventDispatcher = function(self, event, arg1)
55285528
elseif event == "PLAYER_REGEN_ENABLED" then
55295529
-- Track combat state
55305530
DF.playerInCombat = false
5531-
5531+
5532+
-- Arena pet frames deferred by the combat guard in UpdateArenaPetFrames.
5533+
-- Forced, because UpdateAllRaidPetFrames throttles to one run per frame and
5534+
-- something else may already have consumed this frame's slot.
5535+
if DF.pendingArenaPetUpdate then
5536+
DF.pendingArenaPetUpdate = nil
5537+
if DF.UpdateAllRaidPetFrames then DF:UpdateAllRaidPetFrames(true) end
5538+
end
5539+
55325540
-- Clean up after test mode was interrupted by combat
55335541
if DF.testModeInterruptedByCombat then
55345542
DF.testModeInterruptedByCombat = false

Frames/Pets.lua

Lines changed: 131 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ local addonName, DF = ...
99
DF.petFrames = DF.petFrames or {}
1010
DF.partyPetFrames = DF.partyPetFrames or {}
1111
DF.raidPetFrames = DF.raidPetFrames or {}
12+
-- Arena pets are their own set, mirroring the separate arenaHeader. They CANNOT
13+
-- share DF.raidPetFrames: those are anchored to the raid header's children, which
14+
-- is a different (hidden) frame set in arena, and they carry isRaidFrame = true,
15+
-- which would resolve their settings to the RAID config. See UpdateAllRaidPetFrames.
16+
DF.arenaPetFrames = DF.arenaPetFrames or {}
1217

1318
-- Storage for test mode pet frames (non-secure, independent of live frames)
1419
DF.testPetFrames = DF.testPetFrames or {} -- [0]=player pet, [1-4]=party pets
@@ -817,6 +822,14 @@ function DF:LightweightUpdatePetFrames()
817822
DF:PositionPetFrame(DF.raidPetFrames[i])
818823
end
819824
end
825+
-- Arena pets are a separate set (see UpdateAllRaidPetFrames); without this
826+
-- they would keep their creation-time look and ignore every settings change.
827+
for i = 1, 5 do
828+
if DF.arenaPetFrames[i] then
829+
DF:ApplyPetFrameStyle(DF.arenaPetFrames[i])
830+
DF:PositionPetFrame(DF.arenaPetFrames[i])
831+
end
832+
end
820833
end
821834
end
822835

@@ -914,6 +927,18 @@ function DF:UpdatePetGroupLayout()
914927
table.insert(petFrames, DF.testPetFrames[i])
915928
end
916929
end
930+
elseif DF.IsInArena and DF:IsInArena() then
931+
-- Arena: the team is raid-kind, so the pets are raidpet* on the arena
932+
-- header's frames — partypet* does not exist here and collecting it would
933+
-- leave the group empty. The container itself is fine: the arena header is
934+
-- parented to DF.partyContainer, which this layout already anchors against.
935+
-- (Grouped arena pets read the party config for the same reason the
936+
-- attached ones do — see UpdateArenaPetFrames.)
937+
for i = 1, 5 do
938+
if DF.arenaPetFrames[i] and UnitExists("raidpet" .. i) then
939+
table.insert(petFrames, DF.arenaPetFrames[i])
940+
end
941+
end
917942
else
918943
-- Normal mode - check which pets actually exist
919944
if DF.petFrames.player and UnitExists("pet") then
@@ -1403,6 +1428,10 @@ function DF:UpdateAllPetFrames(force)
14031428
-- Mirrors the raid-test-mode guard above, for real raids. Without this the party pet frames can
14041429
-- linger as an orphaned overlay over the raid frames, since the party frames they anchor to are
14051430
-- hidden once raid frames take over.
1431+
-- ⚠ ARENA lands here too — IsInRaid() is true and the units are raid-kind. Handing over is
1432+
-- still right (partypet* does not exist in arena), but the receiver is the ARENA track in
1433+
-- UpdateAllRaidPetFrames, not the raid one; the raid header is hidden in arena. Before that
1434+
-- existed, this early return was half of why pets never appeared in 2v2 / 3v3 / shuffle.
14061435
if not DF.testMode and IsInRaid() then
14071436
DF:Debug("PET", "UpdateAllPetFrames: hiding party pets (live raid active)")
14081437
if DF.petFrames.player then DF:SetPetFrameVisible(DF.petFrames.player, false) end
@@ -1494,12 +1523,99 @@ end
14941523

14951524
local lastRaidPetUpdateTime = 0
14961525

1526+
-- Hide every arena pet (leaving arena, or pets switched off).
1527+
local function HideArenaPetFrames()
1528+
for i = 1, 5 do
1529+
if DF.arenaPetFrames[i] then DF:SetPetFrameVisible(DF.arenaPetFrames[i], false) end
1530+
end
1531+
end
1532+
1533+
-- ARENA PETS. Arena is the odd one out: the group is RAID-kind (IsInRaid() is true,
1534+
-- units are raid1-5), so the party pet track hides itself and hands over to the raid
1535+
-- track — but the raid track walks the raid header, which is hidden in arena, while
1536+
-- DF shows its own arenaHeader. Nothing walked the arena header, so pets simply never
1537+
-- appeared in 2v2 / 3v3 / shuffle, with no error to show for it.
1538+
--
1539+
-- Settings come from the PARTY config even though the units are raidpet*: an arena
1540+
-- team reads as a party to a player, and that is where they will have configured it.
1541+
-- That is why the frames are created with isRaid = false — every downstream path
1542+
-- resolves through DF:GetFrameDB(frame), which keys off frame.isRaidFrame, so this
1543+
-- one flag routes size, layout and petEnabled to the party settings for free.
1544+
local function UpdateArenaPetFrames()
1545+
local db = DF:GetDB() -- party config, deliberately (see above)
1546+
1547+
if not db.petEnabled then
1548+
HideArenaPetFrames()
1549+
-- The PARTY container, not the raid one: grouped arena pets are laid out by
1550+
-- UpdatePetGroupLayout, which owns DF.petGroupContainer and re-parents the
1551+
-- pet buttons onto it. Hiding raidPetGroupContainer left the real container
1552+
-- shown.
1553+
DF:HidePetGroupContainer(DF.petGroupContainer)
1554+
return
1555+
end
1556+
1557+
-- Everything below this point touches protected state: CreatePetFrame builds a
1558+
-- SecureUnitButtonTemplate and calls SetSize/SetAttribute, and PositionPetFrame
1559+
-- does ClearAllPoints/SetParent/SetPoint. The raid track gets away without a
1560+
-- guard because you only reach it forming a group, out of combat. Arena does
1561+
-- not: a pet summoned or resurrected mid-match, a Solo Shuffle round
1562+
-- transition, or Core's PLAYER_REGEN_DISABLED handler ending test mode all
1563+
-- land here with the lockdown up.
1564+
--
1565+
-- Defer rather than drop, so the pets appear the moment combat ends instead of
1566+
-- waiting for whatever roster event happens to come next.
1567+
if InCombatLockdown() then
1568+
DF.pendingArenaPetUpdate = true
1569+
return
1570+
end
1571+
DF.pendingArenaPetUpdate = nil
1572+
1573+
-- Deferred creation, same shape as the raid track. The arena header's children
1574+
-- are the owners; raidpet<N> matches its raid<N> unit tokens.
1575+
local idx = 0
1576+
if DF.IterateArenaFrames then
1577+
DF:IterateArenaFrames(function(frame)
1578+
idx = idx + 1
1579+
if frame and not DF.arenaPetFrames[idx] then
1580+
DF.arenaPetFrames[idx] = DF:CreatePetFrame("raidpet" .. idx, frame, false)
1581+
end
1582+
end)
1583+
end
1584+
1585+
for i = 1, 5 do
1586+
if DF.arenaPetFrames[i] then
1587+
DF:UpdatePetFrame(DF.arenaPetFrames[i])
1588+
DF:PositionPetFrame(DF.arenaPetFrames[i])
1589+
end
1590+
end
1591+
1592+
-- GROUPED mode positions from the layout pass, not per-frame (PositionPetFrame
1593+
-- returns early for it). The party layout is the right one — same config — and
1594+
-- it collects arenaPetFrames when in arena.
1595+
if db.petGroupMode == "GROUPED" then
1596+
DF:UpdatePetGroupLayout()
1597+
end
1598+
end
1599+
14971600
function DF:UpdateAllRaidPetFrames(force)
14981601
-- Throttle: skip if already ran this frame (multiple callers during startup/updates)
14991602
local now = GetTime()
15001603
if not force and now == lastRaidPetUpdateTime then return end
15011604
lastRaidPetUpdateTime = now
15021605

1606+
-- Arena runs its own track (party settings, arena header) and never the raid one:
1607+
-- the raid header is hidden here, so its pets would anchor to invisible frames.
1608+
if not (DF.testMode or DF.raidTestMode) and DF.IsInArena and DF:IsInArena() then
1609+
for i = 1, 40 do
1610+
if DF.raidPetFrames[i] then DF:SetPetFrameVisible(DF.raidPetFrames[i], false) end
1611+
end
1612+
UpdateArenaPetFrames()
1613+
return
1614+
end
1615+
-- Left arena (or never in one): make sure no arena pet is left hanging over the
1616+
-- party/raid frames. Cheap — the table is empty until arena has been entered once.
1617+
HideArenaPetFrames()
1618+
15031619
local db = DF:GetRaidDB()
15041620

15051621
-- Hide raid pet frames if in party test mode (not raid test mode)
@@ -1604,6 +1720,15 @@ end
16041720
-- PET EVENT HANDLING
16051721
-- ============================================================
16061722

1723+
-- raid<N> / raidpet<N> tokens are used by BOTH the raid frames and the arena team,
1724+
-- so the token alone does not say which pet set owns the index. A pet summoned or
1725+
-- resurrected mid-match fires these; without the arena case the event would look up
1726+
-- the raid set, find nothing, and the frame would sit stale until the next full pass.
1727+
local function PetSetForRaidIndex()
1728+
if DF.IsInArena and DF:IsInArena() then return DF.arenaPetFrames end
1729+
return DF.raidPetFrames
1730+
end
1731+
16071732
function DF:OnPetChanged(unit)
16081733
-- Determine which pet frame to update based on unit
16091734
if unit == "player" or unit == "pet" then
@@ -1622,13 +1747,15 @@ function DF:OnPetChanged(unit)
16221747
end
16231748
elseif unit:match("^raid%d+$") then
16241749
local index = tonumber(unit:match("raid(%d+)"))
1625-
if index and DF.raidPetFrames[index] then
1626-
DF:UpdatePetFrame(DF.raidPetFrames[index])
1750+
local set = PetSetForRaidIndex()
1751+
if index and set[index] then
1752+
DF:UpdatePetFrame(set[index])
16271753
end
16281754
elseif unit:match("^raidpet%d+$") then
16291755
local index = tonumber(unit:match("raidpet(%d+)"))
1630-
if index and DF.raidPetFrames[index] then
1631-
DF:UpdatePetFrame(DF.raidPetFrames[index])
1756+
local set = PetSetForRaidIndex()
1757+
if index and set[index] then
1758+
DF:UpdatePetFrame(set[index])
16321759
end
16331760
end
16341761
end

0 commit comments

Comments
 (0)