Merge pull request #1 from Seraphic8x2244/feedpet-pethappiness

new command /feedpet, new conditional [pethappiness]
This commit is contained in:
brues-code
2026-08-25 09:43:41 -05:00
committed by GitHub
3 changed files with 120 additions and 1 deletions
+51 -1
View File
@@ -4895,7 +4895,7 @@ function CleveRoids.ValidatePlayerAuraCount(bigger, amount)
end
function CleveRoids.IsReactive(name)
return CleveRoids.reactiveSpells[spellName] ~= nil
return CleveRoids.reactiveSpells[name] ~= nil
end
-- NOTE: CleveRoids.GetActionButtonInfo is defined in Extensions/Tooltip/Generic.lua
@@ -5403,6 +5403,23 @@ local function MakeTypedPowerKeyword(condKey, unitDefault, powerType)
end
end
local PET_HAPPINESS_STATES = {
unhappy = 1,
content = 2,
happy = 3,
}
local function ResolvePetHappinessState(value)
local state = tonumber(value)
if state then
return state
end
if type(value) ~= "string" then
return nil
end
return PET_HAPPINESS_STATES[GetLowercaseString(value)]
end
-- A list of Conditionals and their functions to validate them
CleveRoids.Keywords = {
exists = function(conditionals)
@@ -7222,6 +7239,39 @@ CleveRoids.Keywords = {
end, conditionals, "nopet")
end,
-- Hunter pet happiness: 1=unhappy, 2=content, 3=happy.
pethappiness = function(conditionals)
local happiness = GetPetHappiness()
local _, isHunterPet = HasPetUI()
if not isHunterPet or not happiness then
return false
end
if conditionals.pethappiness == true then
return true
end
return Multi(conditionals.pethappiness, function(requiredState)
return happiness == ResolvePetHappinessState(requiredState)
end, conditionals, "pethappiness")
end,
nopethappiness = function(conditionals)
local happiness = GetPetHappiness()
local _, isHunterPet = HasPetUI()
if not isHunterPet or not happiness then
return true
end
if conditionals.nopethappiness == true then
return false
end
return NegatedMulti(conditionals.nopethappiness, function(forbiddenState)
return happiness ~= ResolvePetHappinessState(forbiddenState)
end, conditionals, "nopethappiness")
end,
-- [focus] / [nofocus] - whether a focus is set. Covers pfUI's emulated focus
-- and ClassicAPI's native focus token (set via /focus or the FOCUSTARGET keybind).
focus = function(conditionals)
+68
View File
@@ -164,6 +164,8 @@ local BOOLEAN_CONDITIONALS = {
stopattack = true,
pet = true,
nopet = true,
pethappiness = true,
nopethappiness = true,
focus = true,
nofocus = true,
bg = true,
@@ -549,6 +551,7 @@ function CleveRoids.DisableAddon(reason)
SlashCmdList.CLEVEROID = disabledMsg
SlashCmdList.CAST = disabledMsg
SlashCmdList.USE = disabledMsg
SlashCmdList.FEEDPET = disabledMsg
SlashCmdList.EQUIP = disabledMsg
SlashCmdList.EQUIPMH = disabledMsg
SlashCmdList.EQUIPOH = disabledMsg
@@ -4849,6 +4852,7 @@ CleveRoids.Frame:RegisterEvent("BAG_UPDATE_DELAYED")
CleveRoids.Frame:RegisterEvent("GET_ITEM_INFO_RECEIVED")
CleveRoids.Frame:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
CleveRoids.Frame:RegisterEvent("UNIT_PET")
CleveRoids.Frame:RegisterEvent("UNIT_HAPPINESS")
-- == STATE CHANGE EVENT REGISTRATION (for performance) ==
CleveRoids.Frame:RegisterEvent("PLAYER_TARGET_CHANGED")
@@ -4924,6 +4928,12 @@ function CleveRoids.Frame:UNIT_PET()
end
end
function CleveRoids.Frame:UNIT_HAPPINESS()
if CleveRoidMacros.realtime == 0 then
CleveRoids.QueueActionUpdate()
end
end
-- Handle shutdown to prevent SuperWoW API crashes during logout
function CleveRoids.Frame:PLAYER_LOGOUT()
CleveRoids.isShuttingDown = true
@@ -7082,6 +7092,54 @@ local function FindItemInBags(itemName)
return nil
end
function CleveRoids.DoFeedPet(msg)
-- Check macro stop flags
if CleveRoids.stopMacroFlag or CleveRoids.skipMacroFlag then
return false
end
local action = function(itemName)
-- Defensive: make sure we are not in "split stack" mode and nothing is on the cursor
if type(CloseStackSplitFrame) == "function" then CloseStackSplitFrame() end
if CursorHasItem and CursorHasItem() then ClearCursor() end
local _, isHunterPet = HasPetUI()
if not isHunterPet or not UnitExists("pet") or UnitHealth("pet") <= 0 then
return false
end
local bag, bagSlot = FindItemInBags(itemName)
if not bag then
CleveRoids.Print("Item not found: " .. itemName)
return false
end
local feedPet = C_Spell.GetSpellName(6991) or "Feed Pet"
CastSpellByName(feedPet)
-- Only apply the food if Feed Pet actually entered item-targeting mode.
if SpellIsTargeting and not SpellIsTargeting() then
return false
end
PickupContainerItem(bag, bagSlot)
return true
end
-- PERFORMANCE: Use numeric iteration to avoid pairs() iterator allocation
local parts = CleveRoids.splitStringIgnoringQuotes(msg)
for i = 1, table.getn(parts) do
if CleveRoids.DoWithConditionals(parts[i], action, CleveRoids.FixEmptyTarget, false, action) then
-- If /firstaction was used, stop macro evaluation after first successful feed
if CleveRoids.stopOnCastFlag then
CleveRoids.stopMacroFlag = true
end
return true
end
end
return false
end
function CleveRoids.DoApply(hand, msg)
local weaponSlots = {
["main"] = 16,
@@ -7123,6 +7181,16 @@ function CleveRoids.DoApply(hand, msg)
return handled
end
SLASH_FEEDPET1 = "/feedpet"
SlashCmdList.FEEDPET = function(msg)
-- Require an item name argument
if not msg or msg == "" or string.gsub(msg, "%s+", "") == "" then
CleveRoids.Print("Usage: /feedpet [conditionals] ItemName")
return
end
CleveRoids.DoFeedPet(msg)
end
SLASH_APPLYMAIN1 = "/applymain"
SlashCmdList.APPLYMAIN = function(msg)
-- Require an item name argument
+1
View File
@@ -124,6 +124,7 @@ CleveRoids.dynamicCmds = {
["/castpet"] = true,
["/castsequence"] = true,
["/use"] = true,
["/feedpet"] = true,
["/equip"] = true,
["/equipmh"] = true,
["/equipoh"] = true,