跟随版本 0.8.19

This commit is contained in:
rucky
2026-03-24 15:56:28 +08:00
parent 40d37dc8c4
commit c0f1ecc713
19 changed files with 2227 additions and 259 deletions

View File

@@ -350,7 +350,9 @@ function SFrames.Pet:Initialize()
self.frame = f
self.frame.unit = "pet"
f:Hide()
self:CreateAuras()
self:CreateHappinessWarning()
self:CreateCastbar()
SFrames:RegisterEvent("UNIT_PET", function() if arg1 == "player" then self:UpdateAll() end end)
@@ -395,6 +397,7 @@ function SFrames.Pet:UpdateAll()
if SFramesDB and SFramesDB.showPetFrame == false then
self.frame:Hide()
if self.foodPanel then self.foodPanel:Hide() end
self:HideAuras()
return
end
@@ -403,6 +406,7 @@ function SFrames.Pet:UpdateAll()
self:UpdatePowerType()
self:UpdatePower()
self:UpdateHappiness()
self:UpdateAuras()
local name = UnitName("pet")
if name == UNKNOWNOBJECT or name == "未知目标" or name == "Unknown" then
@@ -415,6 +419,7 @@ function SFrames.Pet:UpdateAll()
else
self.frame:Hide()
if self.foodPanel then self.foodPanel:Hide() end
self:HideAuras()
end
end
@@ -452,6 +457,7 @@ function SFrames.Pet:UpdateHappiness()
local happiness = GetPetHappiness()
if not happiness then
self.frame.happinessBG:Hide()
self:HideHappinessWarning()
self:UpdateFoodButton()
return
end
@@ -471,8 +477,10 @@ function SFrames.Pet:UpdateHappiness()
self.frame.happiness:SetTexCoord(0, 0.1875, 0, 0.359375)
self.frame.happinessBG:Show()
end
self:ShowHappinessWarning(happiness)
else
self.frame.happinessBG:Hide()
self:HideHappinessWarning()
end
self:UpdateFoodButton()
end
@@ -1018,6 +1026,430 @@ function SFrames.Pet:UpdateFoodButton()
end
end
--------------------------------------------------------------------------------
-- Pet Buff / Debuff Auras
--------------------------------------------------------------------------------
local PET_AURA_SIZE = 20
local PET_AURA_SPACING = 2
local PET_AURA_ROW_SPACING = 1
local PET_AURAS_PER_ROW = 6
local PET_BUFF_COUNT = 16
local PET_DEBUFF_COUNT = 16
function SFrames.Pet:CreateAuras()
local f = self.frame
f.buffs = {}
f.debuffs = {}
for i = 1, PET_BUFF_COUNT do
local b = CreateFrame("Button", "SFramesPetBuff" .. i, f)
b:SetWidth(PET_AURA_SIZE)
b:SetHeight(PET_AURA_SIZE)
SFrames:CreateUnitBackdrop(b)
b.icon = b:CreateTexture(nil, "ARTWORK")
b.icon:SetAllPoints()
b.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
b.cdText = SFrames:CreateFontString(b, 8, "CENTER")
b.cdText:SetPoint("BOTTOM", b, "BOTTOM", 0, 1)
b.cdText:SetTextColor(1, 0.82, 0)
b.cdText:SetShadowColor(0, 0, 0, 1)
b.cdText:SetShadowOffset(1, -1)
b:SetScript("OnEnter", function()
GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT")
GameTooltip:SetUnitBuff("pet", this:GetID())
end)
b:SetScript("OnLeave", function() GameTooltip:Hide() end)
if i == 1 then
b:SetPoint("TOPLEFT", f, "BOTTOMLEFT", 0, -1)
elseif math.mod(i - 1, PET_AURAS_PER_ROW) == 0 then
b:SetPoint("TOP", f.buffs[i - PET_AURAS_PER_ROW], "BOTTOM", 0, -PET_AURA_ROW_SPACING)
else
b:SetPoint("LEFT", f.buffs[i - 1], "RIGHT", PET_AURA_SPACING, 0)
end
b:Hide()
f.buffs[i] = b
end
for i = 1, PET_DEBUFF_COUNT do
local b = CreateFrame("Button", "SFramesPetDebuff" .. i, f)
b:SetWidth(PET_AURA_SIZE)
b:SetHeight(PET_AURA_SIZE)
SFrames:CreateUnitBackdrop(b)
b.icon = b:CreateTexture(nil, "ARTWORK")
b.icon:SetAllPoints()
b.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
b.cdText = SFrames:CreateFontString(b, 8, "CENTER")
b.cdText:SetPoint("BOTTOM", b, "BOTTOM", 0, 1)
b.cdText:SetTextColor(1, 0.82, 0)
b.cdText:SetShadowColor(0, 0, 0, 1)
b.cdText:SetShadowOffset(1, -1)
b:SetScript("OnEnter", function()
GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT")
GameTooltip:SetUnitDebuff("pet", this:GetID())
end)
b:SetScript("OnLeave", function() GameTooltip:Hide() end)
if i == 1 then
b:SetPoint("TOPLEFT", f, "BOTTOMLEFT", 0, -1)
elseif math.mod(i - 1, PET_AURAS_PER_ROW) == 0 then
b:SetPoint("TOP", f.debuffs[i - PET_AURAS_PER_ROW], "BOTTOM", 0, -PET_AURA_ROW_SPACING)
else
b:SetPoint("LEFT", f.debuffs[i - 1], "RIGHT", PET_AURA_SPACING, 0)
end
b:Hide()
f.debuffs[i] = b
end
SFrames:RegisterEvent("UNIT_AURA", function()
if arg1 == "pet" then SFrames.Pet:UpdateAuras() end
end)
self.petAuraUpdater = CreateFrame("Frame", nil, f)
self.petAuraUpdater.timer = 0
self.petAuraUpdater:SetScript("OnUpdate", function()
this.timer = this.timer + arg1
if this.timer >= 0.25 then
SFrames.Pet:TickAuras()
this.timer = 0
end
end)
end
function SFrames.Pet:UpdateAuras()
if not UnitExists("pet") then return end
local f = self.frame
if not f.buffs then return end
local numBuffs = 0
for i = 1, PET_BUFF_COUNT do
local texture = UnitBuff("pet", i)
local b = f.buffs[i]
b:SetID(i)
if texture then
b.icon:SetTexture(texture)
if SFrames.Tooltip then
SFrames.Tooltip:SetOwner(UIParent, "ANCHOR_NONE")
SFrames.Tooltip:ClearLines()
SFrames.Tooltip:SetUnitBuff("pet", i)
end
local timeLeft = SFrames:GetAuraTimeLeft("pet", i, true)
if SFrames.Tooltip then SFrames.Tooltip:Hide() end
if timeLeft and timeLeft > 0 then
b.expirationTime = GetTime() + timeLeft
b.cdText:SetText(SFrames:FormatTime(timeLeft))
else
b.expirationTime = nil
b.cdText:SetText("")
end
b:Show()
numBuffs = numBuffs + 1
else
b.expirationTime = nil
b.cdText:SetText("")
b:Hide()
end
end
local firstDebuff = f.debuffs[1]
if firstDebuff then
firstDebuff:ClearAllPoints()
if numBuffs > 0 then
local lastRowStart = math.floor((numBuffs - 1) / PET_AURAS_PER_ROW) * PET_AURAS_PER_ROW + 1
firstDebuff:SetPoint("TOP", f.buffs[lastRowStart], "BOTTOM", 0, -PET_AURA_ROW_SPACING)
else
firstDebuff:SetPoint("TOPLEFT", f, "BOTTOMLEFT", 0, -1)
end
end
local hasNP = NanamiPlates_SpellDB and NanamiPlates_SpellDB.UnitDebuff
local npFormat = NanamiPlates_Auras and NanamiPlates_Auras.FormatTime
for i = 1, PET_DEBUFF_COUNT do
local texture, debuffCount, debuffType = UnitDebuff("pet", i)
local b = f.debuffs[i]
b:SetID(i)
if texture then
b.icon:SetTexture(texture)
if debuffType and DebuffTypeColor and DebuffTypeColor[debuffType] then
local c = DebuffTypeColor[debuffType]
b:SetBackdropBorderColor(c.r, c.g, c.b, 1)
else
b:SetBackdropBorderColor(0.8, 0, 0, 1)
end
local timeLeft = 0
local effectName = nil
if hasNP then
local effect, rank, _, stacks, dtype, duration, npTimeLeft, isOwn = NanamiPlates_SpellDB:UnitDebuff("pet", i)
effectName = effect
if npTimeLeft and npTimeLeft > 0 then
timeLeft = npTimeLeft
elseif effect and effect ~= "" and duration and duration > 0
and NanamiPlates_Auras and NanamiPlates_Auras.timers then
local unitKey = (UnitGUID and UnitGUID("pet")) or UnitName("pet") or ""
local cached = NanamiPlates_Auras.timers[unitKey .. "_" .. effect]
if not cached and UnitName("pet") then
cached = NanamiPlates_Auras.timers[UnitName("pet") .. "_" .. effect]
end
if cached and cached.startTime and cached.duration then
local remaining = cached.duration - (GetTime() - cached.startTime)
if remaining > 0 then timeLeft = remaining end
end
end
end
if timeLeft <= 0 then
if SFrames.Tooltip then
SFrames.Tooltip:SetOwner(UIParent, "ANCHOR_NONE")
SFrames.Tooltip:ClearLines()
SFrames.Tooltip:SetUnitDebuff("pet", i)
end
timeLeft = SFrames:GetAuraTimeLeft("pet", i, false)
if SFrames.Tooltip then SFrames.Tooltip:Hide() end
end
if timeLeft and timeLeft > 0 then
b.expirationTime = GetTime() + timeLeft
b.effectName = effectName
if npFormat then
local text, r, g, bc, a = npFormat(timeLeft)
b.cdText:SetText(text)
if r then b.cdText:SetTextColor(r, g, bc, a or 1) end
else
b.cdText:SetText(SFrames:FormatTime(timeLeft))
end
else
b.expirationTime = nil
b.effectName = nil
b.cdText:SetText("")
end
b:Show()
else
b.expirationTime = nil
b.effectName = nil
b.cdText:SetText("")
b:SetBackdropBorderColor(0, 0, 0, 1)
b:Hide()
end
end
end
function SFrames.Pet:TickAuras()
if not UnitExists("pet") then return end
local f = self.frame
if not f.buffs then return end
local timeNow = GetTime()
local npFormat = NanamiPlates_Auras and NanamiPlates_Auras.FormatTime
local hasNP = NanamiPlates_SpellDB and NanamiPlates_SpellDB.FindEffectData
local petName, petLevel, petGUID
if hasNP then
petName = UnitName("pet")
petLevel = UnitLevel("pet") or 0
petGUID = UnitGUID and UnitGUID("pet")
end
for i = 1, PET_BUFF_COUNT do
local b = f.buffs[i]
if b:IsShown() and b.expirationTime then
local timeLeft = b.expirationTime - timeNow
if timeLeft > 0 and timeLeft < 3600 then
if npFormat then
local text, r, g, bc, a = npFormat(timeLeft)
b.cdText:SetText(text)
if r then b.cdText:SetTextColor(r, g, bc, a or 1) end
else
b.cdText:SetText(SFrames:FormatTime(timeLeft))
end
else
b.cdText:SetText("")
end
end
end
for i = 1, PET_DEBUFF_COUNT do
local b = f.debuffs[i]
if b:IsShown() then
local timeLeft = nil
if hasNP and b.effectName then
local data = petGUID and NanamiPlates_SpellDB:FindEffectData(petGUID, petLevel, b.effectName)
if not data and petName then
data = NanamiPlates_SpellDB:FindEffectData(petName, petLevel, b.effectName)
end
if data and data.start and data.duration then
local remaining = data.duration + data.start - timeNow
if remaining > 0 then
timeLeft = remaining
b.expirationTime = timeNow + remaining
end
end
end
if not timeLeft and b.expirationTime then
timeLeft = b.expirationTime - timeNow
end
if timeLeft and timeLeft > 0 and timeLeft < 3600 then
if npFormat then
local text, r, g, bc, a = npFormat(timeLeft)
b.cdText:SetText(text)
if r then b.cdText:SetTextColor(r, g, bc, a or 1) end
else
b.cdText:SetText(SFrames:FormatTime(timeLeft))
end
else
b.cdText:SetText("")
end
end
end
end
function SFrames.Pet:HideAuras()
local f = self.frame
if not f or not f.buffs then return end
for i = 1, PET_BUFF_COUNT do
f.buffs[i].expirationTime = nil
f.buffs[i].cdText:SetText("")
f.buffs[i]:Hide()
end
for i = 1, PET_DEBUFF_COUNT do
f.debuffs[i].expirationTime = nil
f.debuffs[i].effectName = nil
f.debuffs[i].cdText:SetText("")
f.debuffs[i]:SetBackdropBorderColor(0, 0, 0, 1)
f.debuffs[i]:Hide()
end
end
--------------------------------------------------------------------------------
-- Pet Happiness Warning
--------------------------------------------------------------------------------
local WARNING_REMIND_INTERVAL_YELLOW = 60
local WARNING_REMIND_INTERVAL_RED = 30
function SFrames.Pet:CreateHappinessWarning()
local f = self.frame
local fontPath = SFrames:GetFont()
local outline = (SFrames.Media and SFrames.Media.fontOutline) or "OUTLINE"
local warnFrame = CreateFrame("Frame", "SFramesPetHappinessWarn", f)
warnFrame:SetWidth(180)
warnFrame:SetHeight(22)
warnFrame:SetPoint("BOTTOM", f, "TOP", 0, 2)
warnFrame:SetFrameStrata("HIGH")
local warnBg = warnFrame:CreateTexture(nil, "BACKGROUND")
warnBg:SetAllPoints()
warnBg:SetTexture("Interface\\Buttons\\WHITE8X8")
warnBg:SetVertexColor(0, 0, 0, 0.55)
warnFrame.bg = warnBg
local warnText = warnFrame:CreateFontString(nil, "OVERLAY")
warnText:SetFont(fontPath, 11, outline)
warnText:SetPoint("CENTER", warnFrame, "CENTER", 0, 0)
warnText:SetShadowColor(0, 0, 0, 1)
warnText:SetShadowOffset(1, -1)
warnFrame.text = warnText
warnFrame:Hide()
self.warnFrame = warnFrame
self.lastHappiness = nil
self.lastWarnTime = 0
self.warnFlashAlpha = 1
self.warnFlashDir = -1
warnFrame:SetScript("OnUpdate", function()
SFrames.Pet:WarningFlashUpdate()
end)
end
function SFrames.Pet:WarningFlashUpdate()
if not self.warnFrame or not self.warnFrame:IsShown() then return end
if not self.warnSeverity or self.warnSeverity ~= "red" then return end
local speed = 2.5
local dt = arg1 or 0.016
self.warnFlashAlpha = self.warnFlashAlpha + self.warnFlashDir * speed * dt
if self.warnFlashAlpha <= 0.25 then
self.warnFlashAlpha = 0.25
self.warnFlashDir = 1
elseif self.warnFlashAlpha >= 1 then
self.warnFlashAlpha = 1
self.warnFlashDir = -1
end
self.warnFrame.text:SetAlpha(self.warnFlashAlpha)
self.warnFrame.bg:SetVertexColor(0.4, 0, 0, 0.55 * self.warnFlashAlpha)
end
function SFrames.Pet:ShowHappinessWarning(happiness)
if not self.warnFrame then return end
if happiness == 3 then
self:HideHappinessWarning()
return
end
local now = GetTime()
local isNewState = (self.lastHappiness ~= happiness)
if happiness == 2 then
self.warnFrame.text:SetText("宠物心情一般,攻击力受影响!")
self.warnFrame.text:SetTextColor(1, 0.82, 0.2)
self.warnFrame.bg:SetVertexColor(0.3, 0.25, 0, 0.55)
self.warnFrame.text:SetAlpha(1)
self.warnSeverity = "yellow"
self.warnFrame:Show()
if isNewState or (now - self.lastWarnTime >= WARNING_REMIND_INTERVAL_YELLOW) then
SFrames:Print("|cffffff00宠物心情一般|r - 攻击力下降,请及时喂食!")
self.lastWarnTime = now
end
elseif happiness == 1 then
self.warnFrame.text:SetText("宠物很不开心,快要跑了!")
self.warnFrame.text:SetTextColor(1, 0.2, 0.2)
self.warnFrame.bg:SetVertexColor(0.4, 0, 0, 0.55)
self.warnFlashAlpha = 1
self.warnFlashDir = -1
self.warnSeverity = "red"
self.warnFrame:Show()
if isNewState or (now - self.lastWarnTime >= WARNING_REMIND_INTERVAL_RED) then
SFrames:Print("|cffff3333宠物非常不开心即将离你而去|r 请立即喂食!")
UIErrorsFrame:AddMessage("宠物快要跑了!请立即喂食!", 1, 0.2, 0.2, 1, 3)
self.lastWarnTime = now
end
end
self.lastHappiness = happiness
end
function SFrames.Pet:HideHappinessWarning()
if self.warnFrame then
self.warnFrame:Hide()
end
self.warnSeverity = nil
self.lastHappiness = nil
end
--------------------------------------------------------------------------------
-- Pet Castbar
--------------------------------------------------------------------------------