This commit is contained in:
rucky
2026-03-16 13:48:46 +08:00
commit 2a55dd6dad
93 changed files with 75075 additions and 0 deletions

1176
Units/Party.lua Normal file

File diff suppressed because it is too large Load Diff

787
Units/Pet.lua Normal file
View File

@@ -0,0 +1,787 @@
SFrames.Pet = {}
local _A = SFrames.ActiveTheme
local function Clamp(value, minValue, maxValue)
if value < minValue then return minValue end
if value > maxValue then return maxValue end
return value
end
function SFrames.Pet:Initialize()
local f = CreateFrame("Button", "SFramesPetFrame", UIParent)
f:SetWidth(150)
f:SetHeight(30)
if SFramesDB and SFramesDB.Positions and SFramesDB.Positions["PetFrame"] then
local pos = SFramesDB.Positions["PetFrame"]
f:SetPoint(pos.point, UIParent, pos.relativePoint, pos.xOfs, pos.yOfs)
else
f:SetPoint("TOPLEFT", SFramesPlayerFrame, "BOTTOMLEFT", 10, -55)
end
local frameScale = (SFramesDB and type(SFramesDB.petFrameScale) == "number") and SFramesDB.petFrameScale or 1
f:SetScale(Clamp(frameScale, 0.7, 1.8))
f:SetMovable(true)
f:EnableMouse(true)
f:RegisterForDrag("LeftButton")
f:SetScript("OnDragStart", function() if IsAltKeyDown() or SFrames.isUnlocked then f:StartMoving() end end)
f:SetScript("OnDragStop", function()
f:StopMovingOrSizing()
if not SFramesDB then SFramesDB = {} end
if not SFramesDB.Positions then SFramesDB.Positions = {} end
local point, relativeTo, relativePoint, xOfs, yOfs = f:GetPoint()
SFramesDB.Positions["PetFrame"] = { point = point, relativePoint = relativePoint, xOfs = xOfs, yOfs = yOfs }
end)
f:RegisterForClicks("LeftButtonUp", "RightButtonUp")
f:SetScript("OnClick", function()
if arg1 == "LeftButton" then
if SpellIsTargeting() then
SpellTargetUnit("pet")
elseif CursorHasItem() then
DropItemOnUnit("pet")
else
TargetUnit("pet")
end
else
ToggleDropDownMenu(1, nil, PetFrameDropDown, "SFramesPetFrame", 106, 27)
end
end)
f:SetScript("OnReceiveDrag", function()
if CursorHasItem() then
DropItemOnUnit("pet")
end
end)
f:SetScript("OnEnter", function()
GameTooltip_SetDefaultAnchor(GameTooltip, this)
GameTooltip:SetUnit("pet")
GameTooltip:Show()
end)
f:SetScript("OnLeave", function()
GameTooltip:Hide()
end)
SFrames:CreateUnitBackdrop(f)
-- Health Bar
f.health = SFrames:CreateStatusBar(f, "SFramesPetHealth")
f.health:SetPoint("TOPLEFT", f, "TOPLEFT", 1, -1)
f.health:SetPoint("TOPRIGHT", f, "TOPRIGHT", -1, -1)
f.health:SetHeight(18)
local hbg = CreateFrame("Frame", nil, f)
hbg:SetPoint("TOPLEFT", f.health, "TOPLEFT", -1, 1)
hbg:SetPoint("BOTTOMRIGHT", f.health, "BOTTOMRIGHT", 1, -1)
hbg:SetFrameLevel(f:GetFrameLevel() - 1)
SFrames:CreateUnitBackdrop(hbg)
f.health.bg = f.health:CreateTexture(nil, "BACKGROUND")
f.health.bg:SetAllPoints()
f.health.bg:SetTexture(SFrames:GetTexture())
f.health.bg:SetVertexColor(_A.slotBg[1], _A.slotBg[2], _A.slotBg[3], _A.slotBg[4] or 1)
-- Power Bar
f.power = SFrames:CreateStatusBar(f, "SFramesPetPower")
f.power:SetPoint("TOPLEFT", f.health, "BOTTOMLEFT", 0, -1)
f.power:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -1, 1)
local pbg = CreateFrame("Frame", nil, f)
pbg:SetPoint("TOPLEFT", f.power, "TOPLEFT", -1, 1)
pbg:SetPoint("BOTTOMRIGHT", f.power, "BOTTOMRIGHT", 1, -1)
pbg:SetFrameLevel(f:GetFrameLevel() - 1)
SFrames:CreateUnitBackdrop(pbg)
f.power.bg = f.power:CreateTexture(nil, "BACKGROUND")
f.power.bg:SetAllPoints()
f.power.bg:SetTexture(SFrames:GetTexture())
f.power.bg:SetVertexColor(_A.slotBg[1], _A.slotBg[2], _A.slotBg[3], _A.slotBg[4] or 1)
-- Texts
local fontPath = SFrames:GetFont()
local outline = (SFrames and SFrames.Media and SFrames.Media.fontOutline) or "OUTLINE"
f.nameText = SFrames:CreateFontString(f.health, 10, "LEFT")
f.nameText:SetPoint("LEFT", f.health, "LEFT", 4, 0)
f.nameText:SetWidth(75)
f.nameText:SetHeight(12)
f.nameText:SetJustifyH("LEFT")
f.nameText:SetFont(fontPath, 10, outline)
f.nameText:SetShadowColor(0, 0, 0, 1)
f.nameText:SetShadowOffset(1, -1)
f.healthText = SFrames:CreateFontString(f.health, 10, "RIGHT")
f.healthText:SetPoint("RIGHT", f.health, "RIGHT", -4, 0)
f.healthText:SetFont(fontPath, 10, outline)
f.healthText:SetShadowColor(0, 0, 0, 1)
f.healthText:SetShadowOffset(1, -1)
-- Happiness Icon (for hunters)
local hBG = CreateFrame("Frame", nil, f)
hBG:SetWidth(20)
hBG:SetHeight(20)
hBG:SetPoint("RIGHT", f, "LEFT", -2, 0)
SFrames:CreateUnitBackdrop(hBG)
f.happiness = hBG:CreateTexture(nil, "OVERLAY")
f.happiness:SetPoint("TOPLEFT", hBG, "TOPLEFT", 1, -1)
f.happiness:SetPoint("BOTTOMRIGHT", hBG, "BOTTOMRIGHT", -1, 1)
f.happiness:SetTexture("Interface\\PetPaperDollFrame\\UI-PetHappiness")
f.happinessBG = hBG
f.happinessBG:Hide()
self.frame = f
self.frame.unit = "pet"
f:Hide()
SFrames:RegisterEvent("UNIT_PET", function() if arg1 == "player" then self:UpdateAll() end end)
SFrames:RegisterEvent("PET_BAR_UPDATE", function() self:UpdateAll() end)
SFrames:RegisterEvent("UNIT_HEALTH", function() if arg1 == "pet" then self:UpdateHealth() end end)
SFrames:RegisterEvent("UNIT_MAXHEALTH", function() if arg1 == "pet" then self:UpdateHealth() end end)
SFrames:RegisterEvent("UNIT_MANA", function() if arg1 == "pet" then self:UpdatePower() end end)
SFrames:RegisterEvent("UNIT_MAXMANA", function() if arg1 == "pet" then self:UpdatePower() end end)
SFrames:RegisterEvent("UNIT_ENERGY", function() if arg1 == "pet" then self:UpdatePower() end end)
SFrames:RegisterEvent("UNIT_MAXENERGY", function() if arg1 == "pet" then self:UpdatePower() end end)
SFrames:RegisterEvent("UNIT_FOCUS", function() if arg1 == "pet" then self:UpdatePower() end end)
SFrames:RegisterEvent("UNIT_MAXFOCUS", function() if arg1 == "pet" then self:UpdatePower() end end)
SFrames:RegisterEvent("UNIT_RAGE", function() if arg1 == "pet" then self:UpdatePower() end end)
SFrames:RegisterEvent("UNIT_MAXRAGE", function() if arg1 == "pet" then self:UpdatePower() end end)
SFrames:RegisterEvent("UNIT_DISPLAYPOWER", function() if arg1 == "pet" then self:UpdatePowerType() end end)
SFrames:RegisterEvent("UNIT_HAPPINESS", function() if arg1 == "pet" then self:UpdateHappiness() end end)
SFrames:RegisterEvent("UNIT_NAME_UPDATE", function() if arg1 == "pet" then self:UpdateAll() end end)
SFrames:RegisterEvent("PLAYER_ENTERING_WORLD", function() self:UpdateAll() end)
self:InitFoodFeature()
self:UpdateAll()
end
function SFrames.Pet:UpdateAll()
if UnitExists("pet") then
if SFramesDB and SFramesDB.showPetFrame == false then
self.frame:Hide()
if self.foodPanel then self.foodPanel:Hide() end
return
end
self.frame:Show()
self:UpdateHealth()
self:UpdatePowerType()
self:UpdatePower()
self:UpdateHappiness()
local name = UnitName("pet")
if name == UNKNOWNOBJECT or name == "未知目标" or name == "Unknown" then
name = "宠物"
end
self.frame.nameText:SetText(name)
local r, g, b = 0.33, 0.59, 0.33
self.frame.health:SetStatusBarColor(r, g, b)
else
self.frame:Hide()
if self.foodPanel then self.foodPanel:Hide() end
end
end
function SFrames.Pet:UpdateHealth()
local hp = UnitHealth("pet")
local maxHp = UnitHealthMax("pet")
self.frame.health:SetMinMaxValues(0, maxHp)
self.frame.health:SetValue(hp)
if maxHp > 0 then
self.frame.healthText:SetText(hp .. " / " .. maxHp)
else
self.frame.healthText:SetText("")
end
end
function SFrames.Pet:UpdatePowerType()
local powerType = UnitPowerType("pet")
local color = SFrames.Config.colors.power[powerType]
if color then
self.frame.power:SetStatusBarColor(color.r, color.g, color.b)
else
self.frame.power:SetStatusBarColor(0, 0, 1)
end
end
function SFrames.Pet:UpdatePower()
local power = UnitMana("pet")
local maxPower = UnitManaMax("pet")
self.frame.power:SetMinMaxValues(0, maxPower)
self.frame.power:SetValue(power)
end
function SFrames.Pet:UpdateHappiness()
local happiness = GetPetHappiness()
if not happiness then
self.frame.happinessBG:Hide()
self:UpdateFoodButton()
return
end
local isHunter = false
local _, class = UnitClass("player")
if class == "HUNTER" then isHunter = true end
if isHunter then
if happiness == 1 then
self.frame.happiness:SetTexCoord(0.375, 0.5625, 0, 0.359375)
self.frame.happinessBG:Show()
elseif happiness == 2 then
self.frame.happiness:SetTexCoord(0.1875, 0.375, 0, 0.359375)
self.frame.happinessBG:Show()
elseif happiness == 3 then
self.frame.happiness:SetTexCoord(0, 0.1875, 0, 0.359375)
self.frame.happinessBG:Show()
end
else
self.frame.happinessBG:Hide()
end
self:UpdateFoodButton()
end
--------------------------------------------------------------------------------
-- Pet Food Feature (Hunter only)
-- Food button on pet frame, food selection panel, quick-feed via right-click
--------------------------------------------------------------------------------
local petFoodScanTip
local cachedFeedSpell
local function EnsureFoodScanTooltip()
if not petFoodScanTip then
petFoodScanTip = CreateFrame("GameTooltip", "NanamiPetFoodScanTip", UIParent, "GameTooltipTemplate")
petFoodScanTip:SetOwner(UIParent, "ANCHOR_NONE")
end
return petFoodScanTip
end
local function GetFeedPetSpell()
if cachedFeedSpell then return cachedFeedSpell end
for tab = 1, GetNumSpellTabs() do
local _, _, offset, numSpells = GetSpellTabInfo(tab)
for i = offset + 1, offset + numSpells do
local spellName = GetSpellName(i, BOOKTYPE_SPELL)
if spellName and (spellName == "Feed Pet" or spellName == "喂养宠物") then
cachedFeedSpell = spellName
return cachedFeedSpell
end
end
end
cachedFeedSpell = "Feed Pet"
return cachedFeedSpell
end
local REJECT_NAME_PATTERNS = {
"Potion", "potion", "药水",
"Elixir", "elixir", "药剂",
"Flask", "flask", "合剂",
"Bandage", "bandage", "绷带",
"Scroll", "scroll", "卷轴",
"Healthstone", "healthstone", "治疗石",
"Mana Gem", "法力宝石",
"Thistle Tea", "蓟花茶",
"Firewater", "火焰花水",
"Juju", "符咒",
}
local function NameIsRejected(itemName)
for i = 1, table.getn(REJECT_NAME_PATTERNS) do
if string.find(itemName, REJECT_NAME_PATTERNS[i], 1, true) then
return true
end
end
return false
end
local function IsItemPetFood(bag, slot)
local link = GetContainerItemLink(bag, slot)
if not link then return false end
local texture = GetContainerItemInfo(bag, slot)
local _, _, itemIdStr = string.find(link, "item:(%d+)")
local name, itemType, subType
if itemIdStr then
local n, _, _, _, _, t, st = GetItemInfo("item:" .. itemIdStr)
name = n
itemType = t
subType = st
end
if not name then
local _, _, parsed = string.find(link, "%[(.+)%]")
name = parsed
end
if not name then return false end
if NameIsRejected(name) then
return false
end
if itemType then
if itemType ~= "Consumable" and itemType ~= "消耗品" then
return false
end
if subType then
if string.find(subType, "Potion", 1, true) or string.find(subType, "药水", 1, true)
or string.find(subType, "Elixir", 1, true) or string.find(subType, "药剂", 1, true)
or string.find(subType, "Flask", 1, true) or string.find(subType, "合剂", 1, true)
or string.find(subType, "Bandage", 1, true) or string.find(subType, "绷带", 1, true)
or string.find(subType, "Scroll", 1, true) or string.find(subType, "卷轴", 1, true) then
return false
end
if string.find(subType, "Food", 1, true) or string.find(subType, "食物", 1, true) then
return true, name, texture
end
end
end
local tip = EnsureFoodScanTooltip()
tip:SetOwner(UIParent, "ANCHOR_NONE")
tip:SetBagItem(bag, slot)
local found = false
local rejected = false
for i = 1, tip:NumLines() do
local leftObj = _G["NanamiPetFoodScanTipTextLeft" .. i]
if leftObj then
local text = leftObj:GetText()
if text then
if string.find(text, "进食", 1, true) or string.find(text, "eating", 1, true) then
found = true
end
if string.find(text, "Well Fed", 1, true) or string.find(text, "充分进食", 1, true) then
found = true
end
if string.find(text, "Restores", 1, true) and string.find(text, "health", 1, true)
and string.find(text, "over", 1, true) then
found = true
end
if string.find(text, "恢复", 1, true) and string.find(text, "生命", 1, true)
and string.find(text, "", 1, true) then
found = true
end
if string.find(text, "Potion", 1, true) or string.find(text, "药水", 1, true)
or string.find(text, "Elixir", 1, true) or string.find(text, "药剂", 1, true)
or string.find(text, "Bandage", 1, true) or string.find(text, "绷带", 1, true) then
rejected = true
end
end
end
end
tip:Hide()
if found and not rejected then
return true, name, texture
end
if itemType and subType then
if (itemType == "Consumable" or itemType == "消耗品")
and (subType == "Food & Drink" or subType == "食物和饮料") then
return true, name, texture
end
end
return false
end
function SFrames.Pet:ScanBagsForFood()
local foods = {}
for bag = 0, 4 do
for slot = 1, GetContainerNumSlots(bag) do
local isFood, name, itemTex = IsItemPetFood(bag, slot)
if isFood then
local texture, itemCount = GetContainerItemInfo(bag, slot)
local link = GetContainerItemLink(bag, slot)
table.insert(foods, {
bag = bag,
slot = slot,
name = name,
link = link,
texture = texture or itemTex,
count = itemCount or 1,
})
end
end
end
return foods
end
function SFrames.Pet:FeedPet(bag, slot)
if not UnitExists("pet") then return end
local link = GetContainerItemLink(bag, slot)
local tex = GetContainerItemInfo(bag, slot)
local spell = GetFeedPetSpell()
CastSpellByName(spell)
PickupContainerItem(bag, slot)
if link then
local _, _, itemId = string.find(link, "item:(%d+)")
if itemId then
if not SFramesDB then SFramesDB = {} end
SFramesDB.lastPetFoodId = tonumber(itemId)
end
end
if tex and self.foodButton then
self.foodButton.icon:SetTexture(tex)
if not SFramesDB then SFramesDB = {} end
SFramesDB.lastPetFoodIcon = tex
end
end
function SFrames.Pet:QuickFeed()
if not UnitExists("pet") then return end
local foods = self:ScanBagsForFood()
if table.getn(foods) == 0 then
DEFAULT_CHAT_FRAME:AddMessage("|cffff9900[Nanami]|r 背包中没有可喂食的食物")
return
end
local preferred = SFramesDB and SFramesDB.lastPetFoodId
if preferred then
for i = 1, table.getn(foods) do
local f = foods[i]
if f.link then
local _, _, itemId = string.find(f.link, "item:(%d+)")
if itemId and tonumber(itemId) == preferred then
self:FeedPet(f.bag, f.slot)
return
end
end
end
end
self:FeedPet(foods[1].bag, foods[1].slot)
end
--------------------------------------------------------------------------------
-- Food Button & Panel UI
--------------------------------------------------------------------------------
local FOOD_COLS = 6
local FOOD_SLOT_SIZE = 30
local FOOD_SLOT_GAP = 2
local FOOD_PAD = 8
function SFrames.Pet:CreateFoodButton()
local f = self.frame
local A = SFrames.ActiveTheme
local btn = CreateFrame("Button", "SFramesPetFoodBtn", f)
btn:SetWidth(20)
btn:SetHeight(20)
btn:SetPoint("TOP", f.happinessBG, "BOTTOM", 0, -2)
SFrames:CreateUnitBackdrop(btn)
local icon = btn:CreateTexture(nil, "ARTWORK")
icon:SetPoint("TOPLEFT", btn, "TOPLEFT", 1, -1)
icon:SetPoint("BOTTOMRIGHT", btn, "BOTTOMRIGHT", -1, 1)
icon:SetTexture("Interface\\Icons\\INV_Misc_Food_14")
btn.icon = icon
btn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
local pet = self
btn:SetScript("OnClick", function()
if CursorHasItem() then
local curTex = pet:GetCursorItemTexture()
DropItemOnUnit("pet")
if curTex then
pet:SetFoodIcon(curTex)
end
return
end
if arg1 == "RightButton" then
pet:QuickFeed()
else
if pet.foodPanel and pet.foodPanel:IsShown() then
pet.foodPanel:Hide()
else
pet:ShowFoodPanel()
end
end
end)
btn:SetScript("OnEnter", function()
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:AddLine("喂养宠物", 1, 1, 1)
GameTooltip:AddLine("左键: 选择食物", 0.7, 0.7, 0.7)
GameTooltip:AddLine("右键: 快速喂食", 0.7, 0.7, 0.7)
GameTooltip:AddLine("可拖拽背包食物到此按钮", 0.7, 0.7, 0.7)
GameTooltip:Show()
end)
btn:SetScript("OnLeave", function()
GameTooltip:Hide()
end)
btn:SetScript("OnReceiveDrag", function()
if CursorHasItem() then
DropItemOnUnit("pet")
end
end)
self.foodButton = btn
btn:Hide()
end
function SFrames.Pet:CreateFoodPanel()
if self.foodPanel then return self.foodPanel end
local A = SFrames.ActiveTheme
local panel = CreateFrame("Frame", "SFramesPetFoodPanel", UIParent)
panel:SetFrameStrata("DIALOG")
panel:SetFrameLevel(20)
panel:SetWidth(FOOD_COLS * (FOOD_SLOT_SIZE + FOOD_SLOT_GAP) + FOOD_PAD * 2 - FOOD_SLOT_GAP)
panel:SetHeight(80)
panel:SetPoint("BOTTOMLEFT", self.frame, "TOPLEFT", -22, 4)
SFrames:CreateUnitBackdrop(panel)
panel:EnableMouse(true)
panel:Hide()
local titleBar = CreateFrame("Frame", nil, panel)
titleBar:SetPoint("TOPLEFT", panel, "TOPLEFT", 1, -1)
titleBar:SetPoint("TOPRIGHT", panel, "TOPRIGHT", -1, -1)
titleBar:SetHeight(18)
titleBar:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8X8" })
local hdr = A.headerBg or A.panelBg
titleBar:SetBackdropColor(hdr[1], hdr[2], hdr[3], (hdr[4] or 0.9) * 0.6)
local titleText = titleBar:CreateFontString(nil, "OVERLAY")
titleText:SetFont(SFrames:GetFont(), 10, SFrames.Media.fontOutline or "OUTLINE")
titleText:SetPoint("LEFT", titleBar, "LEFT", FOOD_PAD, 0)
titleText:SetTextColor(A.title[1], A.title[2], A.title[3])
titleText:SetText("选择食物")
panel.titleText = titleText
local hintText = panel:CreateFontString(nil, "OVERLAY")
hintText:SetFont(SFrames:GetFont(), 9, SFrames.Media.fontOutline or "OUTLINE")
hintText:SetPoint("BOTTOMLEFT", panel, "BOTTOMLEFT", FOOD_PAD, 4)
hintText:SetPoint("BOTTOMRIGHT", panel, "BOTTOMRIGHT", -FOOD_PAD, 4)
hintText:SetJustifyH("LEFT")
local dim = A.dimText or { 0.5, 0.5, 0.5 }
hintText:SetTextColor(dim[1], dim[2], dim[3])
hintText:SetText("点击喂食 | 可拖拽食物到此面板")
panel.hintText = hintText
local emptyText = panel:CreateFontString(nil, "OVERLAY")
emptyText:SetFont(SFrames:GetFont(), 10, SFrames.Media.fontOutline or "OUTLINE")
emptyText:SetPoint("CENTER", panel, "CENTER", 0, 0)
emptyText:SetTextColor(dim[1], dim[2], dim[3])
emptyText:SetText("背包中没有可喂食的食物")
emptyText:Hide()
panel.emptyText = emptyText
local pet = self
panel:SetScript("OnReceiveDrag", function()
if CursorHasItem() then
local curTex = pet:GetCursorItemTexture()
DropItemOnUnit("pet")
if curTex then
pet:SetFoodIcon(curTex)
end
end
end)
table.insert(UISpecialFrames, "SFramesPetFoodPanel")
panel.slots = {}
self.foodPanel = panel
return panel
end
function SFrames.Pet:CreateFoodSlot(parent, index)
local A = SFrames.ActiveTheme
local slot = CreateFrame("Button", "SFramesPetFoodSlot" .. index, parent)
slot:SetWidth(FOOD_SLOT_SIZE)
slot:SetHeight(FOOD_SLOT_SIZE)
slot:SetBackdrop({
bgFile = "Interface\\Buttons\\WHITE8X8",
edgeFile = "Interface\\Buttons\\WHITE8X8",
tile = false, tileSize = 0, edgeSize = 1,
insets = { left = 1, right = 1, top = 1, bottom = 1 }
})
slot:SetBackdropColor(A.slotBg[1], A.slotBg[2], A.slotBg[3], A.slotBg[4] or 0.9)
slot:SetBackdropBorderColor(0, 0, 0, 1)
local icon = slot:CreateTexture(nil, "ARTWORK")
icon:SetPoint("TOPLEFT", 2, -2)
icon:SetPoint("BOTTOMRIGHT", -2, 2)
slot.icon = icon
local count = slot:CreateFontString(nil, "OVERLAY")
count:SetFont(SFrames:GetFont(), 10, "OUTLINE")
count:SetPoint("BOTTOMRIGHT", -2, 2)
count:SetJustifyH("RIGHT")
count:SetTextColor(1, 1, 1)
slot.count = count
slot:RegisterForClicks("LeftButtonUp", "RightButtonUp")
local pet = self
slot:SetScript("OnClick", function()
if CursorHasItem() then
local curTex = pet:GetCursorItemTexture()
DropItemOnUnit("pet")
if curTex then
pet:SetFoodIcon(curTex)
end
return
end
if IsShiftKeyDown() and this.foodLink then
if ChatFrameEditBox and ChatFrameEditBox:IsVisible() then
ChatFrameEditBox:Insert(this.foodLink)
end
return
end
if this.foodBag and this.foodSlot then
pet:FeedPet(this.foodBag, this.foodSlot)
if pet.foodPanel then pet.foodPanel:Hide() end
end
end)
slot:SetScript("OnEnter", function()
if this.foodBag and this.foodSlot then
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetBagItem(this.foodBag, this.foodSlot)
GameTooltip:AddLine(" ")
GameTooltip:AddLine("点击: 喂食宠物", 0.5, 1, 0.5)
GameTooltip:AddLine("Shift+点击: 链接到聊天", 0.7, 0.7, 0.7)
GameTooltip:Show()
end
this:SetBackdropBorderColor(0.4, 0.4, 0.4, 1)
end)
slot:SetScript("OnLeave", function()
GameTooltip:Hide()
this:SetBackdropBorderColor(0, 0, 0, 1)
end)
slot:SetScript("OnReceiveDrag", function()
if CursorHasItem() then
DropItemOnUnit("pet")
end
end)
return slot
end
function SFrames.Pet:ShowFoodPanel()
self:CreateFoodPanel()
self:RefreshFoodPanel()
self.foodPanel:Show()
end
function SFrames.Pet:RefreshFoodPanel()
local panel = self.foodPanel
if not panel then return end
local foods = self:ScanBagsForFood()
local numFoods = table.getn(foods)
for i = 1, table.getn(panel.slots) do
panel.slots[i]:Hide()
end
if numFoods == 0 then
panel:SetHeight(60)
panel.emptyText:Show()
panel.hintText:Hide()
return
end
panel.emptyText:Hide()
panel.hintText:Show()
local rows = math.ceil(numFoods / FOOD_COLS)
local panelH = FOOD_PAD + 20 + rows * (FOOD_SLOT_SIZE + FOOD_SLOT_GAP) + 18
panel:SetHeight(panelH)
for i = 1, numFoods do
local food = foods[i]
local slot = panel.slots[i]
if not slot then
slot = self:CreateFoodSlot(panel, i)
panel.slots[i] = slot
end
local col = mod(i - 1, FOOD_COLS)
local row = math.floor((i - 1) / FOOD_COLS)
slot:ClearAllPoints()
slot:SetPoint("TOPLEFT", panel, "TOPLEFT",
FOOD_PAD + col * (FOOD_SLOT_SIZE + FOOD_SLOT_GAP),
-(FOOD_PAD + 18 + row * (FOOD_SLOT_SIZE + FOOD_SLOT_GAP)))
slot.icon:SetTexture(food.texture)
slot.count:SetText(food.count > 1 and tostring(food.count) or "")
slot.foodBag = food.bag
slot.foodSlot = food.slot
slot.foodName = food.name
slot.foodLink = food.link
slot:Show()
end
end
function SFrames.Pet:GetCursorItemTexture()
for bag = 0, 4 do
for slot = 1, GetContainerNumSlots(bag) do
local texture, count, locked = GetContainerItemInfo(bag, slot)
if locked and texture then
return texture
end
end
end
return nil
end
function SFrames.Pet:SetFoodIcon(tex)
if not tex or not self.foodButton then return end
self.foodButton.icon:SetTexture(tex)
if not SFramesDB then SFramesDB = {} end
SFramesDB.lastPetFoodIcon = tex
end
function SFrames.Pet:InitFoodFeature()
local _, playerClass = UnitClass("player")
if playerClass ~= "HUNTER" then return end
self:CreateFoodButton()
if SFramesDB and SFramesDB.lastPetFoodIcon then
self.foodButton.icon:SetTexture(SFramesDB.lastPetFoodIcon)
end
local pet = self
SFrames:RegisterEvent("BAG_UPDATE", function()
if pet.foodPanel and pet.foodPanel:IsShown() then
pet:RefreshFoodPanel()
end
end)
end
function SFrames.Pet:UpdateFoodButton()
if not self.foodButton then return end
local _, class = UnitClass("player")
if class == "HUNTER" and UnitExists("pet") then
self.foodButton:Show()
local happiness = GetPetHappiness()
if happiness and happiness == 1 then
self.foodButton.icon:SetVertexColor(1, 0.3, 0.3)
elseif happiness and happiness == 2 then
self.foodButton.icon:SetVertexColor(1, 0.8, 0.4)
else
self.foodButton.icon:SetVertexColor(1, 1, 1)
end
else
self.foodButton:Hide()
if self.foodPanel then self.foodPanel:Hide() end
end
end

1449
Units/Player.lua Normal file

File diff suppressed because it is too large Load Diff

1064
Units/Raid.lua Normal file

File diff suppressed because it is too large Load Diff

1065
Units/TalentTree.lua Normal file

File diff suppressed because it is too large Load Diff

1046
Units/Target.lua Normal file

File diff suppressed because it is too large Load Diff

85
Units/ToT.lua Normal file
View File

@@ -0,0 +1,85 @@
SFrames.ToT = {}
local _A = SFrames.ActiveTheme
function SFrames.ToT:Initialize()
local f = CreateFrame("Button", "SFramesToTFrame", UIParent)
f:SetWidth(120)
f:SetHeight(25)
f:SetPoint("BOTTOMLEFT", SFramesTargetFrame, "BOTTOMRIGHT", 5, 0)
f:RegisterForClicks("LeftButtonUp", "RightButtonUp")
f:SetScript("OnClick", function()
if arg1 == "LeftButton" then
TargetUnit("targettarget")
end
end)
-- Health Bar
f.health = SFrames:CreateStatusBar(f, "SFramesToTHealth")
f.health:SetPoint("TOPLEFT", f, "TOPLEFT", 1, -1)
f.health:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -1, 1)
local hbg = CreateFrame("Frame", nil, f)
hbg:SetPoint("TOPLEFT", f.health, "TOPLEFT", -1, 1)
hbg:SetPoint("BOTTOMRIGHT", f.health, "BOTTOMRIGHT", 1, -1)
hbg:SetFrameLevel(f:GetFrameLevel() - 1)
SFrames:CreateUnitBackdrop(hbg)
f.health.bg = f.health:CreateTexture(nil, "BACKGROUND")
f.health.bg:SetAllPoints()
f.health.bg:SetTexture(SFrames:GetTexture())
f.health.bg:SetVertexColor(_A.slotBg[1], _A.slotBg[2], _A.slotBg[3], _A.slotBg[4] or 1)
f.nameText = SFrames:CreateFontString(f.health, 10, "CENTER")
f.nameText:SetPoint("CENTER", f.health, "CENTER", 0, 0)
self.frame = f
f:Hide()
-- Update loop since targettarget changes don't fire precise events in Vanilla
self.updater = CreateFrame("Frame")
self.updater.timer = 0
self.updater:SetScript("OnUpdate", function()
this.timer = this.timer + arg1
if this.timer >= 0.2 then
SFrames.ToT:Update()
this.timer = 0
end
end)
end
function SFrames.ToT:Update()
if UnitExists("targettarget") then
self.frame:Show()
local hp = UnitHealth("targettarget")
local maxHp = UnitHealthMax("targettarget")
self.frame.health:SetMinMaxValues(0, maxHp)
self.frame.health:SetValue(hp)
self.frame.nameText:SetText(UnitName("targettarget"))
if UnitIsPlayer("targettarget") then
local _, class = UnitClass("targettarget")
local color = SFrames.Config.colors.class[class]
if color then
self.frame.health:SetStatusBarColor(color.r, color.g, color.b)
self.frame.nameText:SetTextColor(color.r, color.g, color.b)
else
self.frame.health:SetStatusBarColor(0, 1, 0)
self.frame.nameText:SetTextColor(1, 1, 1)
end
else
local r, g, b = 0.85, 0.77, 0.36 -- Neutral
if UnitIsEnemy("player", "targettarget") then
r, g, b = 0.78, 0.25, 0.25 -- Enemy
elseif UnitIsFriend("player", "targettarget") then
r, g, b = 0.33, 0.59, 0.33 -- Friend
end
self.frame.health:SetStatusBarColor(r, g, b)
self.frame.nameText:SetTextColor(r, g, b)
end
else
self.frame:Hide()
end
end