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