278 lines
6.8 KiB
Lua
278 lines
6.8 KiB
Lua
-- AdePet.lua
|
|
-- Hunter-only addon for the 1.12 client.
|
|
-- Shows: Pet_Name: Loyalty_Level (Loyalty_Name)
|
|
-- and, under it, "Pet is hungry" when the pet's happiness drops below Happy (yellow/red).
|
|
-- Window hides itself at max loyalty (Level 6).
|
|
--
|
|
-- Commands:
|
|
-- /hungry X set hunger check interval to X seconds (default 15)
|
|
-- /adepet lock | unlock | reset (alias: /ap)
|
|
|
|
AdePetDB = AdePetDB or {}
|
|
|
|
local LOYALTY_INTERVAL = 1.0
|
|
local DEFAULT_HUNGRY_INTERVAL = 15
|
|
local MAX_LOYALTY = 6
|
|
|
|
local LOYALTY_NAMES = {
|
|
[1] = "Rebellious",
|
|
[2] = "Unruly",
|
|
[3] = "Submissive",
|
|
[4] = "Dependable",
|
|
[5] = "Faithful",
|
|
[6] = "Best Friend",
|
|
}
|
|
|
|
local isHunter = false
|
|
local isHungry = false
|
|
local hungerLevel = 3 -- 1 = unhappy (red), 2 = content (yellow), 3 = happy (green)
|
|
|
|
local frame = CreateFrame("Frame", "AdePetFrame", UIParent)
|
|
frame:SetWidth(150)
|
|
frame:SetHeight(28)
|
|
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 200)
|
|
frame:SetMovable(true)
|
|
frame:EnableMouse(true)
|
|
frame:RegisterForDrag("LeftButton")
|
|
frame:SetClampedToScreen(true)
|
|
frame:Hide()
|
|
|
|
frame:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 12,
|
|
insets = { left = 3, right = 3, top = 3, bottom = 3 },
|
|
})
|
|
frame:SetBackdropColor(0, 0, 0, 0.7)
|
|
|
|
local text = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
|
text:SetPoint("TOP", frame, "TOP", 0, -8)
|
|
text:SetJustifyH("CENTER")
|
|
|
|
local hungryText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
hungryText:SetPoint("TOP", text, "BOTTOM", 0, -3)
|
|
hungryText:SetJustifyH("CENTER")
|
|
hungryText:Hide()
|
|
|
|
frame:SetScript("OnDragStart", function()
|
|
if not AdePetDB.locked then
|
|
this:StartMoving()
|
|
end
|
|
end)
|
|
|
|
frame:SetScript("OnDragStop", function()
|
|
this:StopMovingOrSizing()
|
|
local point, _, relPoint, x, y = this:GetPoint()
|
|
AdePetDB.point = point
|
|
AdePetDB.relPoint = relPoint
|
|
AdePetDB.x = x
|
|
AdePetDB.y = y
|
|
end)
|
|
|
|
local function GetHungryInterval()
|
|
return AdePetDB.hungryInterval or DEFAULT_HUNGRY_INTERVAL
|
|
end
|
|
|
|
-- Fit the window to the visible text lines.
|
|
local function ResizeToText()
|
|
local w = text:GetStringWidth()
|
|
local h1 = text:GetHeight()
|
|
if not h1 or h1 < 1 then h1 = 12 end
|
|
local height = 8 + h1 + 8
|
|
|
|
if hungryText:IsShown() then
|
|
local w2 = hungryText:GetStringWidth()
|
|
if w2 > w then w = w2 end
|
|
local h2 = hungryText:GetHeight()
|
|
if not h2 or h2 < 1 then h2 = 10 end
|
|
height = height + h2 + 3
|
|
end
|
|
|
|
w = w + 24
|
|
if w < 90 then w = 90 end
|
|
frame:SetWidth(w)
|
|
frame:SetHeight(height)
|
|
end
|
|
|
|
-- Reads the pet's happiness. 1 = unhappy, 2 = content, 3 = happy.
|
|
-- Anything below "happy" is treated as hungry.
|
|
local function UpdateHunger()
|
|
if not isHunter or not UnitExists("pet") then
|
|
isHungry = false
|
|
return
|
|
end
|
|
local happiness = GetPetHappiness()
|
|
if type(happiness) ~= "number" then
|
|
happiness = tonumber(happiness)
|
|
end
|
|
if happiness and happiness < 3 then
|
|
isHungry = true
|
|
hungerLevel = happiness
|
|
else
|
|
isHungry = false
|
|
end
|
|
end
|
|
|
|
-- Extract numeric loyalty level. Standard API returns a number; some servers
|
|
-- (e.g. OctoWoW) return text like "(Loyalty Level 1) Rebellious".
|
|
local function ParseLoyalty(raw)
|
|
if type(raw) == "number" then
|
|
return raw
|
|
elseif type(raw) == "string" then
|
|
local _, _, digits = string.find(raw, "(%d+)")
|
|
if digits then
|
|
return tonumber(digits)
|
|
end
|
|
-- fallback: match by rank name
|
|
local lower = string.lower(raw)
|
|
for level, name in pairs(LOYALTY_NAMES) do
|
|
if string.find(lower, string.lower(name), 1, true) then
|
|
return level
|
|
end
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function UpdateDisplay()
|
|
if not isHunter then
|
|
frame:Hide()
|
|
return
|
|
end
|
|
|
|
if not UnitExists("pet") then
|
|
text:SetText("No Pet")
|
|
hungryText:Hide()
|
|
ResizeToText()
|
|
frame:Show()
|
|
return
|
|
end
|
|
|
|
local petName = UnitName("pet") or "Pet"
|
|
local loyaltyLevel = ParseLoyalty(GetPetLoyalty())
|
|
|
|
if loyaltyLevel and loyaltyLevel >= MAX_LOYALTY then
|
|
frame:Hide()
|
|
return
|
|
end
|
|
|
|
if loyaltyLevel then
|
|
local loyaltyName = LOYALTY_NAMES[loyaltyLevel] or "Unknown"
|
|
text:SetText(petName .. ": " .. loyaltyLevel .. " (" .. loyaltyName .. ")")
|
|
else
|
|
text:SetText(petName)
|
|
end
|
|
|
|
if isHungry then
|
|
hungryText:SetText("Pet is hungry")
|
|
if hungerLevel == 1 then
|
|
hungryText:SetTextColor(1, 0.2, 0.2)
|
|
else
|
|
hungryText:SetTextColor(1, 0.9, 0.1)
|
|
end
|
|
hungryText:Show()
|
|
else
|
|
hungryText:Hide()
|
|
end
|
|
|
|
ResizeToText()
|
|
frame:Show()
|
|
end
|
|
|
|
local function CheckHunger()
|
|
UpdateHunger()
|
|
UpdateDisplay()
|
|
end
|
|
|
|
local loyaltyElapsed = 0
|
|
local hungerElapsed = 0
|
|
frame:SetScript("OnUpdate", function()
|
|
if not isHunter then
|
|
return
|
|
end
|
|
loyaltyElapsed = loyaltyElapsed + arg1
|
|
hungerElapsed = hungerElapsed + arg1
|
|
|
|
if hungerElapsed >= GetHungryInterval() then
|
|
hungerElapsed = 0
|
|
loyaltyElapsed = 0
|
|
CheckHunger()
|
|
elseif loyaltyElapsed >= LOYALTY_INTERVAL then
|
|
loyaltyElapsed = 0
|
|
UpdateDisplay()
|
|
end
|
|
end)
|
|
|
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
frame:RegisterEvent("UNIT_PET")
|
|
frame:RegisterEvent("PLAYER_REGEN_ENABLED") -- left combat
|
|
|
|
frame:SetScript("OnEvent", function()
|
|
if event == "PLAYER_ENTERING_WORLD" then
|
|
local _, englishClass = UnitClass("player")
|
|
isHunter = (englishClass == "HUNTER")
|
|
|
|
if not isHunter then
|
|
frame:Hide()
|
|
return
|
|
end
|
|
|
|
if AdePetDB.point then
|
|
frame:ClearAllPoints()
|
|
frame:SetPoint(AdePetDB.point, UIParent, AdePetDB.relPoint, AdePetDB.x, AdePetDB.y)
|
|
end
|
|
end
|
|
|
|
if not isHunter then
|
|
return
|
|
end
|
|
|
|
if event == "UNIT_PET" and arg1 ~= "player" then
|
|
return
|
|
end
|
|
|
|
-- Entering world, pet change, or leaving combat: check hunger right away.
|
|
hungerElapsed = 0
|
|
CheckHunger()
|
|
end)
|
|
|
|
SLASH_ADEPETHUNGRY1 = "/hungry"
|
|
SlashCmdList["ADEPETHUNGRY"] = function(msg)
|
|
if not isHunter then
|
|
DEFAULT_CHAT_FRAME:AddMessage("AdePet: this addon only works for Hunters.")
|
|
return
|
|
end
|
|
local seconds = tonumber(msg)
|
|
if not seconds or seconds < 1 then
|
|
DEFAULT_CHAT_FRAME:AddMessage("AdePet: hunger check every " .. GetHungryInterval() .. "s. Usage: /hungry X (X = seconds, minimum 1)")
|
|
return
|
|
end
|
|
AdePetDB.hungryInterval = seconds
|
|
hungerElapsed = 0
|
|
DEFAULT_CHAT_FRAME:AddMessage("AdePet: hunger check interval set to " .. seconds .. "s.")
|
|
end
|
|
|
|
SLASH_ADEPET1 = "/adepet"
|
|
SLASH_ADEPET2 = "/ap"
|
|
SlashCmdList["ADEPET"] = function(msg)
|
|
msg = string.lower(msg or "")
|
|
if not isHunter then
|
|
DEFAULT_CHAT_FRAME:AddMessage("AdePet: this addon only works for Hunters.")
|
|
return
|
|
end
|
|
if msg == "lock" then
|
|
AdePetDB.locked = true
|
|
DEFAULT_CHAT_FRAME:AddMessage("AdePet: window locked.")
|
|
elseif msg == "unlock" then
|
|
AdePetDB.locked = false
|
|
DEFAULT_CHAT_FRAME:AddMessage("AdePet: window unlocked (drag to move).")
|
|
elseif msg == "reset" then
|
|
AdePetDB.point = nil
|
|
frame:ClearAllPoints()
|
|
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 200)
|
|
DEFAULT_CHAT_FRAME:AddMessage("AdePet: position reset.")
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage("AdePet commands: /adepet lock, unlock, reset | /hungry X")
|
|
end
|
|
end
|