vanilla-wow-addons – Rev 1
?pathlinks?
--[[
path: /PetFeeder/
filename: PetFeeder.lua
author: Jeff Parker <jeff3parker@gmail.com>
created: Tue, 22 Jan 2005 14:15:00 -0800
updated: Tue, 22 Jan 2005 21:39:00 -0800
Pet Feeder: a GUI interface allowing you configure happiness level for your pet &
drag/drop foods you wish your pet to eat. When the pet happiness drops below
the selected threshold will automatically feed your pet.
To remove a food from the list, simply click on it.
]]
PETFEEDER_ITEM_HEIGHT = 32;
PETFEEDER_ITEMS_SHOWN = 7;
PETFEEDER_FL_DISLIKED = 0;
PETFEEDER_FL_UNKNOWN = 1;
PETFEEDER_FL_APPROVED = 2;
-- Configuration
PeetFeederPlayer_Config = {};
UIPanelWindows["PetFeederFrame"] = { area = "left", pushable = 4 };
PETFEEDER_TAB_SUBFRAMES = { "PetFeeder_FoodsFrame", "PetFeeder_ApprovedFoodsFrame", "PetFeeder_UnlikedFoodsFrame" };
-- Foods Lists
PetFeederPlayer_Foods = {};
PetFeeder_Foods = {};
PetFeeder_BadFoods = {};
PetFeeder_QuestItems = {};
PetFeeder_PetName = "";
local LastPetName = nil;
PetFeeder_Pets = {};
-- Variables
PetFeeder_Var = { };
PetFeeder_Var.PetInCombat = false;
PetFeeder_Var.PlayerInCombat = false;
PetFeeder_Var.PetDead = false;
PetFeeder_Var.PlayerDead = false;
PetFeeder_Var.TradeOrLoot = false;
PetFeeder_Var.Searching = false;
PetFeeder_Var.isSitting = false;
PetFeeder_Var.sitPosX = -1;
PetFeeder_Var.sitPosY = -1;
PetFeeder_Var.feedStartTime = 0;
PetFeeder_Var.debug = false;
PetFeeder_Var.AutoFindFoodTimer = 0;
PetFeeder_Var.AutoFindFoodTimeout = 60; -- 60 seconds
PetFeeder_Var.LastItemAttempted = nil;
PetFeeder_Var.Feed = false;
PetFeeder_Var.DialogShowing = false;
-- Hooked function variables
Pre_SitOrStand = nil;
Pre_DoEmote = nil;
Pre_PetFeeder_ZMI = nil;
Pre_PetFeeder_ZMO = nil;
--Pre_Jump = nil; -- blocked by Blizzard in v1.10
PetDies_ChatParseInfo = { AddOn = "PetFeeder" };
function PetFeeder_PetIsDead(value)
PetFeeder_Var.PetDead = value;
if ( value == true ) then
PFDebugMessage("PF-Died", "PET DIED. <from messages>", "debug");
else
PFDebugMessage("PF-Died", "PET REVIVED. <from messages>", "debug");
end
end
--[[
=============================================================================
Debug message output
=============================================================================
]]
function PFDebugMessage(x,y,z)
if ( z == "error" ) then
DEFAULT_CHAT_FRAME:AddMessage(format("|cffff0000[%s]: %s|r", x, y))
end
if ( PetFeeder_Var.debug ) then
DEFAULT_CHAT_FRAME:AddMessage(format("|ccfff0000[%s]: %s|r", x, y))
end
end
--[[
=============================================================================
The loading frame handles getting our AddOn initialized properly
=============================================================================
]]
function PetFeederLoadingFrame_OnUpdate()
if ( PetFeederFrame.loaded ) then
PetFeederLoadingFrame:UnregisterEvent("VARIABLES_LOADED");
PetFeederLoadingFrame:UnregisterEvent("UNIT_NAME_UPDATE");
PetFeederLoadingFrame:Hide();
PetFeederLoadingFrame = nil;
elseif ( PetFeederLoadingFrame.loadTime + 10 <= GetTime() ) then
--PetFeederFrame_LoadData();
PetFeederFrame.loaded = true;
PetFeederLoadingFrame.loadTime = GetTime();
end
end
function PetFeederLoadingFrame_OnLoad()
PetFeederLoadingFrame:RegisterEvent("VARIABLES_LOADED");
PetFeederLoadingFrame:RegisterEvent("UNIT_NAME_UPDATE");
PetFeederLoadingFrame.init = 0;
PetFeederLoadingFrame.loadTime = GetTime();
end
function PetFeederLoadingFrame_OnEvent(event, arg1)
if ( not PetFeederLoadingFrame ) then
return;
end
if ( event == "VARIABLES_LOADED" or event == "UNIT_NAME_UPDATE" ) then
PetFeederLoadingFrame.init = PetFeederLoadingFrame.init + 1;
end
end
--[[
=============================================================================
Initialize data, perform hooks, register for events
=============================================================================
]]
function PetFeederFrame_LoadData()
if ( UnitClass("player") ~= PETFEEDER_HUNTER) then
return;
end
PetFeederFrame_InitConfig();
PetFeeder_PetName = UnitName( "pet" );
if ( PetFeeder_PetName == "Unknown Entity" ) then
PetFeeder_PetName = nil;
return
end
if ( PetFeeder_PetName ~= nil ) then
initChatParseforPetDiesEvent();
PetDies_ChatParseInfo.template = PetFeeder_PetName.." dies.";
PFChatParse_RegisterEvent(PetDies_ChatParseInfo);
PFDebugMessage("PF-Register", "registering Pet Died event", "debug");
-- Check for old version of foods
if ( PetFeederPlayer_Foods[PetFeeder_PetName] and getn(PetFeederPlayer_Foods[PetFeeder_PetName]) > 0) then
anItem = PetFeederPlayer_Foods[PetFeeder_PetName][1];
if ( not anItem.quality ) then
FixOldInventoryData();
end
end
if ( PetFeederPlayer_Foods[PetFeeder_PetName] ) then
for i=1, table.getn( PetFeederPlayer_Foods[PetFeeder_PetName] ) do
if ( not PetFeederPlayer_Foods[PetFeeder_PetName][i].foodlikedstate ) then
PetFeederPlayer_Foods[PetFeeder_PetName][i].foodlikedstate = PETFEEDER_FL_UNKNOWN;
return true;
end
end
end
end
PetFeederFrame.loaded = true;
end
function PetFeederFrame_InitConfig()
PetFeederFrame_SetPlayerConfig("Enabled",1);
PetFeederFrame_SetPlayerConfig("BarEnabled",1);
PetFeederFrame_SetPlayerConfig("Alert",1);
PetFeederFrame_SetPlayerConfig("Level",2);
PetFeederFrame_SetPlayerConfig("SortOption",1);
PetFeederFrame_SetPlayerConfig("SortOption1",1);
PetFeederFrame_SetPlayerConfig("SortOption2",1);
PetFeederFrame_SetPlayerConfig("AutoFindFood",1);
PetFeederFrame_SetPlayerConfig("SkipBuffFoods",1);
PetFeederFrame_SetPlayerConfig("RequireApproval",1);
PetFeederFrame_SetPlayerConfig("FeedOnlyApproved",1);
end
function PetFeederFrame_SetPlayerConfig(ftableitem,defaultvalue)
if ( not defaultvalue ) then
defaultvalue = 0;
end
PeetFeederPlayer_Config[ftableitem] = PeetFeederPlayer_Config[ftableitem] or defaultvalue;
end
function initChatParseforPetDiesEvent()
PetDies_ChatParseInfo.event = "CHAT_MSG_COMBAT_FRIENDLY_DEATH";
PetDies_ChatParseInfo.func = function(t) PetFeeder_PetIsDead(true); end;
PetDies_ChatParseInfo.template = "%s "..PETFEEDER_PET_DIES_MSG;
PetDies_ChatParseInfo.english = "Aslok dies."; -- example
PetDies_ChatParseInfo.fields = { };
end
--[[
=============================================================================
Initialize saves, slash cmd and panels
=============================================================================
]]
function PetFeederFrame_OnLoad()
if ( UnitClass("player") ~= PETFEEDER_HUNTER ) then
if ( DEFAULT_CHAT_FRAME ) then
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFFF00PetFeeder:|r "..PETFEEDER_SESSION_DISABLED);
end
return;
end
PetFeederFrame_LoadData();
-- Register for Events
this:RegisterEvent("PET_ATTACK_START");
this:RegisterEvent("PET_ATTACK_STOP");
this:RegisterEvent("UNIT_HAPPINESS");
this:RegisterEvent("PLAYER_REGEN_DISABLED");
this:RegisterEvent("PLAYER_REGEN_ENABLED");
this:RegisterEvent("PLAYER_PET_CHANGED");
this:RegisterEvent("PLAYER_ALIVE");
this:RegisterEvent("PLAYER_UNGHOST")
this:RegisterEvent("PLAYER_DEAD");
this:RegisterEvent("TRADE_SHOW");
this:RegisterEvent("TRADE_CLOSED");
this:RegisterEvent("LOOT_SHOW");
this:RegisterEvent("LOOT_CLOSED");
this:RegisterEvent("CHAT_MSG_COMBAT_FRIENDLY_DEATH");
this:RegisterEvent("PET_BAR_UPDATE"); -- to get the rez pet event
this:RegisterEvent("BAG_UPDATE");
this:RegisterEvent("UNIT_NAME_UPDATE");
this:RegisterEvent("LOCALPLAYER_PET_RENAMED");
-- this is player initiated and will help fire the feeding
this:RegisterEvent("PLAYER_TARGET_CHANGED");
-- Hook functions
if ( not Pre_DoEmote ) then
Pre_DoEmote = DoEmote;
DoEmote = PetFeeder_DoEmote;
end
if ( not Pre_PetFeeder_ZMI ) then
Pre_PetFeeder_ZMI = CameraZoomIn;
CameraZoomIn = PetFeeder_ZMI;
end
if ( not Pre_PetFeeder_ZMO ) then
Pre_PetFeeder_ZMO = CameraZoomOut;
CameraZoomOut = PetFeeder_ZMO;
end
local chatParseInfo = { AddOn = "PetFeeder" };
chatParseInfo.event = "CHAT_MSG_SPELL_FAILED_LOCALPLAYER";
chatParseInfo.func = function(t) PetFeeder_RemoveBadFood(); end;
chatParseInfo.template = PETFEEDER_FAILED_TO_FEED;
chatParseInfo.english = "You fail to perform Feed Pet: Your pet doesn't like that food.";
chatParseInfo.fields = { };
if ( not PFChatParse_RegisterEvent ) then
PFDebugMessage("PF", "function PFChatParse_RegisterEvent not defined!", "error");
end
PFChatParse_RegisterEvent(chatParseInfo);
local chatParseInfo1 = { AddOn = "PetFeeder" };
chatParseInfo1.event = "CHAT_MSG_SPELL_FAILED_LOCALPLAYER";
chatParseInfo1.func = function(t) PetFeeder_RemoveBadFood(); end;
chatParseInfo1.template = PETFEEDER_FOODTOOLOW;
chatParseInfo1.english = "You fail to perform Feed Pet: That food's level is not high enough for your pet.";
chatParseInfo1.fields = { };
PFChatParse_RegisterEvent(chatParseInfo1);
local chatParseInfo2 = { AddOn = "PetFeeder" };
chatParseInfo2.event = "CHAT_MSG_SYSTEM";
chatParseInfo2.func = function() PetFeeder_DoEmote("SIT"); end;
chatParseInfo2.template = PETFEEDER_AFK;
chatParseInfo2.english = "You are now AFK: Away from Keyboard";
chatParseInfo2.fields = { };
PFChatParse_RegisterEvent(chatParseInfo2);
if ( DEFAULT_CHAT_FRAME ) then
DEFAULT_CHAT_FRAME:AddMessage("Jeff's "..PETFEEDER_TITLE.." AddOn loaded. Use /pf");
end
UIErrorsFrame:AddMessage(loadMessage, 1.0, 1.0, 0.0, 1.0, UIERRORS_HOLD_TIME);
-- Register Slash Commands
SLASH_PetFeeder1 = "/PetFeeder";
SLASH_PetFeeder2 = "/pf";
SlashCmdList["PetFeeder"] = function(msg)
PetFeeder_SlashCmd(msg);
end
-- Tab Handling code
PanelTemplates_SetNumTabs(PetFeederFrame, 3);
PanelTemplates_SetTab(PetFeederFrame, 1);
this.loaded = nil;
end
--[[
=============================================================================
Called when PF opens or closes
=============================================================================
]]
function PetFeederFrame_OnShow()
PlaySound("igCharacterInfoOpen");
PetFeeder_Update_Frames();
end
function PetFeederFrame_OnHide()
PlaySound("igCharacterInfoClose");
end
--[[
=============================================================================
Hooked Functions
replaces the original calls with our own and then calls the original. These
methods are hooked so we can detect when a player performs a specific action
such as sitting, jumping, etc.
=============================================================================
]]
function PetFeeder_DoEmote(token,...)
if ( token == "SIT" or token == "sit") then
-- DEFAULT_CHAT_FRAME:AddMessage("emote SIT");
PetFeeder_Var.sitPosX, PetFeeder_Var.sitPosY = GetPlayerMapPosition("player");
PetFeeder_Var.isSitting = true;
end
if ( token == "STAND" ) then
PetFeeder_Var.isSitting = false;
end
if ( table.getn(arg) > 0 ) then
Pre_DoEmote(token,arg[1]);
else
Pre_DoEmote(token);
end
end
-- Zoom in mouse wheel hook to call our event handler
function PetFeeder_ZMI(arg1)
PetFeederFrame_OnEvent("PLAYER_TARGET_CHANGED","pet");
Pre_PetFeeder_ZMI(arg1);
end
-- Zoom out mouse wheel hook to call our event handler
function PetFeeder_ZMO(arg1)
PetFeederFrame_OnEvent("PLAYER_TARGET_CHANGED","pet");
Pre_PetFeeder_ZMO(arg1);
end
--[[
=============================================================================
Walked through our list of foods and obtains the ItemCount for each
=============================================================================
]]
function PetFeeder_UpdateQuantities()
PetFeeder_GetQuestItems();
for index, value in PetFeederPlayer_Foods[PetFeeder_PetName] do
-- update the item count
PetFeederPlayer_Foods[PetFeeder_PetName][index].quantity = PetFeeder_GetItemCount( value.name );
end
end
function PetFeeder_GetQuestItems()
PetFeeder_QuestItems = nil;
PetFeeder_QuestItems = {};
local numEntries, numQuests = GetNumQuestLogEntries()
for questNum = 1, GetNumQuestLogEntries() do
SelectQuestLogEntry(questNum);
local questTitle, level, questTag, isHeader, isCollapsed, isComplete = GetQuestLogTitle(questNum);
if ( not isHeader ) then
for requiredItem = 1, GetNumQuestLeaderBoards(questNum) do
local text, type, finished = GetQuestLogLeaderBoard(requiredItem);
if ( type == "item" ) then
local _, _, itemName, numCurrent, numRequired = string.find(text, "(.*): (%d+)/(%d+)");
--DEFAULT_CHAT_FRAME:AddMessage("itemName="..itemName);
--DEFAULT_CHAT_FRAME:AddMessage("numRequired="..numRequired);
if (PetFeeder_QuestItems[itemName]) then
PetFeeder_QuestItems[itemName] = PetFeeder_QuestItems[itemName] + numRequired;
else
PetFeeder_QuestItems[itemName] = numRequired;
end
end
end
end
end
end
function togglePetFeeder(tab)
if not ( PetFeeder_HasPet() ) then
UIErrorsFrame:AddMessage(PETFEEDER_ESTABLISH_PET, 0.8, 0, 0, 1.0, UIERRORS_HOLD_TIME);
return;
end
if ( not tab ) then
if ( PetFeederFrame:IsVisible() ) then
HideUIPanel(PetFeederFrame);
else
ShowUIPanel(PetFeederFrame);
local selectedFrame = getglobal(PETFEEDER_TAB_SUBFRAMES[PetFeederFrame.selectedTab]);
if ( not selectedFrame:IsVisible() ) then
selectedFrame:Show();
end
end
else
local subFrame = getglobal(tab);
if ( subFrame ) then
PanelTemplates_SetTab(PetFeederFrame, subFrame:GetID() );
if ( PetFeederFrame:IsVisible() ) then
if ( subFrame:IsVisible() ) then
HideUIPanel( PetFeederFrame );
else
PlaySound("igCharacterInfoTab");
PetFeederFrame_ShowSubFrame(tab);
end
else
ShowUIPanel( PetFeederFrame );
PetFeederFrame_ShowSubFrame(tab);
end
end
end
end
function PetFeederFrame_ShowSubFrame(frameName)
for index, value in PETFEEDER_TAB_SUBFRAMES do
if ( value == frameName ) then
getglobal(value):Show();
else
getglobal(value):Hide();
end
end
end
---------------------------------------------------
--Show config dialog when slash-command is called--
---------------------------------------------------
function PetFeeder_SlashCmd(msg)
if ( not PetFeeder_HasPet() ) then
UIErrorsFrame:AddMessage(PETFEEDER_ESTABLISH_PET, 0.8, 0, 0, 1.0, UIERRORS_HOLD_TIME);
return;
end
PetFeeder_PetName = UnitName( "pet" );
if (msg == "feed" ) then
PetFeeder_Feed();
elseif ( msg == "clear" ) then
PetFeeder_ClearFoods();
elseif ( msg == "clearbad" ) then
PetFeeder_ClearBadFoods();
elseif ( msg == "dump" ) then
PetFeeder_DebugDump();
elseif ( msg == "toggledebug" ) then
PetFeeder_Var.debug = not PetFeeder_Var.debug;
if ( PetFeeder_Var.debug ) then
DEFAULT_CHAT_FRAME:AddMessage("debug is ON");
else
DEFAULT_CHAT_FRAME:AddMessage("debug is OFF");
end
elseif ( msg == "buff" ) then
PetFeeder_PlayerBuff();
elseif ( msg == "populate" ) then
PetFeeder_PopulateFoods();
else
togglePetFeeder(nil);
end
end
-- Do not localize this
function PetFeeder_DebugDump()
local i;
DEFAULT_CHAT_FRAME:AddMessage("Petname is "..PetFeeder_PetName);
DEFAULT_CHAT_FRAME:AddMessage("PetFeeder Foods in the order of consumption");
for index, value in PetFeederPlayer_Foods[PetFeeder_PetName] do
DEFAULT_CHAT_FRAME:AddMessage(value.name.." "..value.foodlikedstate);
end
end
function PetFeeder_GetID(button)
if ( button == nil ) then
return 0;
end
return (button:GetID())
end
LLLAstEvetnt = nil;
local PetRename = false;
function PetFeederFrame_OnEvent(event, arg1)
--[[if ( LLLAstEvetnt ~= event ) then
LLLAstEvetnt = event;
DEFAULT_CHAT_FRAME:AddMessage(event);
if ( arg1 ) then
DEFAULT_CHAT_FRAME:AddMessage("Arg1: "..arg1);
end
if ( arg2 ) then
DEFAULT_CHAT_FRAME:AddMessage("Arg2: "..arg2);
end
end]]
if (not PeetFeederPlayer_Config.Enabled ) then
PFDebugMessage("PF", "PF is disabled", "debug");
return;
end
local eventmsg = "event="..event;
PFDebugMessage("PF", eventmsg, "debug");
if (arg1 ) then
eventmsg = "arg1="..arg1;
PFDebugMessage("PF", eventmsg, "debug");
end
if ( event == "PLAYER_PET_CHANGED" ) then
PetFeeder_Var.PetInCombat = false;
PetFeeder_Var.PetDead = false;
PetFeeder_Var.PlayerInCombat = false;
PetFeeder_Var.PlayerDead = false;
initChatParseforPetDiesEvent();
PFChatParse_UnregisterEvent(PetDies_ChatParseInfo);
PetDies_chatParseInfo.template = PetFeeder_PetName.." dies.";
PFChatParse_RegisterEvent(PetDies_ChatParseInfo);
PFDebugMessage("PF-Register", "registering Pet Died event", "debug");
return;
end
if ( event == "PET_ATTACK_START" ) then
PetFeeder_Var.PetInCombat = true;
PFDebugMessage("PF", "Pet START COMBAT", "debug");
return;
elseif ( event == "PLAYER_REGEN_DISABLED" ) then
PetFeeder_Var.PlayerInCombat = true;
return;
elseif ( event == "PET_ATTACK_STOP" ) then
PFDebugMessage("PF", "Pet EXIT COMBAT", "debug");
PetFeeder_Var.PetInCombat = false;
elseif ( event == "PLAYER_REGEN_ENABLED" ) then
PetFeeder_Var.PlayerInCombat = false;
elseif ( event == "PET_BAR_UPDATE" and arg1 == nil) then
if ( not PetFeeder_HasPet() ) then
return;
end
PetFeeder_PetName = UnitName("pet");
if ( LastPetName ) then
LastPetName = nil;
else
LastPetName = PetFeeder_PetName;
end
PetFeeder_Var.PetDead = false;
PetFeeder_Var.PetInCombat = false; -- Pet could have died during combat and we don't get notified
PFDebugMessage("PF-Alive", "Pet is alive <showgrid>", "debug");
if ( PeetFeederPlayer_Config.AutoFindFood ) then
PetFeeder_PopulateFoods();
end
PetFeeder_Update_Frames();
elseif ( event == "PLAYER_DEAD" ) then
PetFeeder_Var.PlayerDead = true;
return;
elseif ( event == "PLAYER_ALIVE" or event == "PLAYER_UNGHOST" ) then -- no notification of deaths, be sure to clear these
PetFeeder_Var.PetInCombat = false;
PetFeeder_Var.PlayerInCombat = false;
PetFeeder_Var.PlayerDead = false;
elseif ( event == "TRADE_SHOW" or event == "LOOT_SHOW") then
PetFeeder_Var.TradeOrLoot = true;
return;
elseif ( event == "TRADE_CLOSED" or event == "LOOT_CLOSED") then
PetFeeder_Var.TradeOrLoot = false;
return;
elseif ( event == "BAG_UPDATE" or event == "UNIT_PET" ) then
if ( not PetFeeder_HasPet() ) then
return;
end
if ( PeetFeederPlayer_Config.AutoFindFood ) then
PetFeeder_PopulateFoods();
end
PetFeeder_Update_Frames();
elseif ( event == "LOCALPLAYER_PET_RENAMED" ) then
PetRename = true;
elseif ( event == "UNIT_NAME_UPDATE" ) then
if ( arg1 and arg1 == "pet" ) then
if ( not PetFeeder_HasPet() ) then
return;
end
if ( PetFeeder_PetName ~= UnitName("pet") ) then
--DEFAULT_CHAT_FRAME:AddMessage("UNIT_NAME_UPDATE is running "..UnitName("pet"));
if ( PetRename ) then
if ( PetFeederPlayer_Foods[PetFeeder_PetName] ) then
PetFeederPlayer_Foods[UnitName("pet")] = PetFeederPlayer_Foods[PetFeeder_PetName];
end
PetRename = false;
elseif ( PetFeederPlayer_Foods[PetFeeder_PetName] ) then
PetFeederPlayer_Foods[PetFeeder_PetName] = {};
LastPetName = UnitName("pet");
end
PetFeeder_PetName = UnitName("pet");
else
return;
end
if ( PeetFeederPlayer_Config.AutoFindFood ) then
PetFeeder_PopulateFoods();
end
PetFeeder_Update_Frames();
return;
else
return;
end
end
-- HACK
-- in v1.10 Blizzard changed the DropItemOnUnit( ) method so that it must be player
-- click event related. This event identifies such an event.
-- There's no reason to even try feeding the pet unless this event has fired otherwise the feed attempt will fail.
if ( event == "PLAYER_TARGET_CHANGED" ) then
if ( PeetFeederPlayer_Config.Enabled ) then
PFDebugMessage("PF", "Attempt to feed", "debug");
if ( PetFeeder_CheckHappiness() == false ) then
return; -- feeding not necessary
end
PetFeeder_Feed();
end
end
end
function PetFeeder_CanFeed()
-- Abort routines
if not ( PetFeeder_HasPet() ) then
PFDebugMessage("PF-Abort", "cannot find a pet", "debug");
PetFeeder_Var.PetInCombat = false; -- Pet could have died during combat and we don't get notified
return;
end
if ( UnitHealth("pet") <= 0 ) then
PFDebugMessage("PF-Abort", "Pet Dead", "debug");
return false;
end
if ( UnitHealth("player") <= 0 ) then
PFDebugMessage("PF-Abort", "Player Dead", "debug");
return false;
end
if ( CastingBarFrameStatusBar:IsVisible() ) then
PFDebugMessage("PF-Abort", "Player Casting Spell", "debug");
return false;
end
if ( UnitOnTaxi("player") ) then
PFDebugMessage("PF-Abort", "Player On Taxi", "debug");
return false;
end
if ( PetFeeder_Var.PetInCombat == true or PetFeeder_Var.PlayerInCombat == true ) then
PFDebugMessage("PF-Abort", "Can't feed while in combat", "debug");
return false;
end
if ( PetFeeder_HasFeedEffect() ) then
PFDebugMessage("PF-Abort", "Pet already has Feed effect", "debug");
return false;
end
-- Extra check to clear sitting flag
if ( PetFeeder_Var.isSitting == true) then
local posX, posY = GetPlayerMapPosition("player");
if ( PetFeeder_Var.sitPosX ~= posX ) then
PetFeeder_Var.isSitting = false;
elseif (PetFeeder_Var.sitPosY ~= posY ) then
PetFeeder_Var.isSitting = false;
end
end
-- Must have Pet from here down
if ( not PetFeeder_PetName or PetFeeder_PetName == "" or PetFeeder_PetName == "Unknown Entity" ) then
PetFeeder_PetName = UnitName( "pet" );
if ( not PetFeeder_PetName or PetFeeder_PetName == "" ) then
PFDebugMessage("PF-Critical", "Did not find pet in <event handler>", "debug");
return false;
end
initChatParseforPetDiesEvent();
PFChatParse_UnregisterEvent(PetDies_ChatParseInfo);
PetDies_ChatParseInfo.template = PetFeeder_PetName.." dies.";
PFChatParse_RegisterEvent(PetDies_ChatParseInfo);
PFDebugMessage("PF-Register", "registering Pet Died event", "debug");
end
if ( not PetFeederPlayer_Foods[PetFeeder_PetName] ) then
PFDebugMessage("PF", "inserting new pet", "debug");
PetFeederPlayer_Foods[PetFeeder_PetName] = {};
end
-- Is there a debuff on the pet that will break the feeding Buff?
if ( PetFeeder_PetDebuff() ) then
PFDebugMessage("PF-Abort", "Pet is debuffed", "debug");
return false;
end
-- check for player buffs that might interfere with feeding
-- or result in undesired effects (such as stopping feign death or shadowmelding)
if ( PetFeeder_PlayerBuff() ) then
PFDebugMessage("PF-Abort", "Can't feed with these player buffs", "debug");
return false;
end
return true;
end
-- Check player buffs
-- return true if buff enabled we don't want to break by feeding
-- (i.e. FeignDeath or Shadowmeld )
function PetFeeder_PlayerBuff()
local i = 1;
local buff;
local unit = "player";
buff = UnitBuff(unit,i);
while buff do
--PetFeederTooltip:SetUnitBuff( unit, i );
--DEFAULT_CHAT_FRAME:AddMessage("debug::Player buff::"..i.."="..buff);
local debuginfo = "Player buff::"..i.."="..buff;
if ( isMounted( unit, i, buff ) ) then
PFDebugMessage("PF-Abort", "Player is mounted", "debug");
return true;
elseif ( string.find(buff, "Ability_Rogue_FeignDeath") ) then
PFDebugMessage("PF-Abort", debuginfo, "debug");
return true;
elseif ( string.find(buff, "Ability_Ambush") ) then -- shadowmeld
PFDebugMessage("PF-Abort", debuginfo, "debug");
return true;
elseif ( string.find(buff, "DemonBreath") ) then -- water breathing
PFDebugMessage("PF-Abort", debuginfo, "debug");
return true;
end
i = i + 1;
buff = UnitBuff(unit,i);
end
-- Check for eating or drinking
local playerBuffs = {"Interface\\Icons\\INV_Drink_07","Interface\\Icons\\INV_Misc_Fork&Knife"};
for i=0, 15 do
buff = GetPlayerBuffTexture(i);
if ( buff ) then
for k,v in playerBuffs do
if ( buff == v ) then
PFDebugMessage("PF-Abort", buff, "debug");
return true;
end
end
end
end
if ( PetFeeder_Var.TradeOrLoot ) then
return true;
end
return false;
end
--=============================================================================
-- Return information about the pattern
--
-- pattern pattern to find
local function BuffInformation( pattern )
if pattern then
return string.find( PetFeederTooltipTextLeft2:GetText(), pattern );
else
return 1;
end
end
--=============================================================================
-- Check to see if the player is mounted
function isMounted(unit, i, buff )
PetFeederTooltip:SetUnitBuff( unit, i );
if ( string.find(buff, "_Mount_" ) or string.find(buff,"INV_Misc_Foot_Kodo") ) then
local startpos,endpos,buffValue = BuffInformation(" (%d+)%%");
if ( buffValue ~= nil ) then
buffValue = buffValue + 0;
if ( buffValue >=60 ) then
return true;
end
end
end
return false;
end
-- Check pet debuffs
-- return true if pet has debuff that will break feeding
-- (i.e. poisoned )
function PetFeeder_PetDebuff()
local i = 1;
local buff;
buff = UnitDebuff("pet", i);
while buff do
local debuginfo = "Pet debuff::"..i.."="..buff;
--PFDebugMessage("PF", debuginfo, "debugbuff");
if ( string.find(buff, "Spell_Nature_CorrosiveBreath") ) then
return true; -- this comes from a Venom Spitter when it poisons the target
end
if ( string.find(buff, "Spell_Nature") ) then
return true; -- this might be too liberal, but should catch all instances we are searching for
end
i = i + 1;
buff = UnitDebuff("pet", i);
end
return false;
end
-- Check Feed Effect
function PetFeeder_HasFeedEffect()
local i = 1;
local buff;
buff = UnitBuff("pet", i);
while buff do
local debuginfo = "Pet buff::"..i.."="..buff;
--PFDebugMessage("PF", debuginfo, "debugbuff");
if ( string.find(buff, "Ability_Hunter_BeastTraining") ) then
return true;
end
i = i + 1;
buff = UnitBuff("pet", i);
end
return false;
end
-- Check Happiness
function PetFeeder_CheckHappiness()
if ( UnitHealth("pet") <= 0 ) then
PFDebugMessage("PF-Abort", "Pet Dead", "debug");
return false;
end
if ( UnitHealth("player") <= 0 ) then
PFDebugMessage("PF-Abort", "Player Dead", "debug");
return false;
end
-- Get Pet Info
--local pet = UnitName("pet");
local happiness, damage, loyalty = GetPetHappiness();
local level = PeetFeederPlayer_Config.Level + 1;
-- Check Happiness
if ( happiness == 0 ) or ( happiness == nil ) then
PFDebugMessage("PF-Abort", "Unable to determine pet happiness", "debug");
return false;
end
if ( happiness >= level ) then
local msg = "Feeding not necessary. Pet happiness is at threshold:"..PETFEEDER_LEVELS_DROPDOWN[happiness-1].name;
PFDebugMessage("PF-Abort", msg, "debug");
return false;
end
-- Check if Feeding is needed
PFDebugMessage("PF", "pet isn't happy enough", "debug");
if not ( PetFeeder_Var.Searching ) then
return true;
else
PFDebugMessage("PF-Abort", "Pet already searching for food", "debug");
end
return false;
end
-- Feed Pet
function PetFeeder_Feed()
if ( not PetFeeder_Var.feedStartTime) then
PetFeeder_Var.feedStartTime = GetTime();
else
local time = GetTime();
local timePast = time - PetFeeder_Var.feedStartTime;
if ( timePast < 2 ) then
return;
end
end
if ( not PetFeeder_CanFeed() ) then return; end
-- Check if dragging item
if ( CursorHasItem() ) then
PFDebugMessage("PF-Abort", "item is on cursor", "debug");
return;
end
-- Make sure PetFeeder_PetName has pet name
PetFeeder_PetName = UnitName( "pet" );
if ( not PetFeederPlayer_Foods[PetFeeder_PetName] ) then
PetFeederPlayer_Foods[PetFeeder_PetName] = {};
end
PetFeeder_UpdateQuantities();
PetFeeder_Var.Searching = true;
if ( PeetFeederPlayer_Config.Alert ) then
DEFAULT_CHAT_FRAME:AddMessage(PetFeeder_PetName..PETFEEDER_BEGIN_SEARCH);
end
-- 1. Get first available food from our list with quantity > 0
-- 2. Find the m,n location of it in the pack.
-- 3. Pick up and eat.
local lowestQuantity = 99;
local lowestM = 0;
local lowestN = 0;
for index, value in PetFeederPlayer_Foods[PetFeeder_PetName] do
if ( value.quantity > 0 ) then
if ( PeetFeederPlayer_Config.RequireApproval and PeetFeederPlayer_Config.RequireApproval == 1 and value.foodlikedstate == PETFEEDER_FL_UNKNOWN ) then
PetFeeder_ApproveFoodItem(value.name);
PetFeeder_Var.Feed = true;
return;
end
if ( (PeetFeederPlayer_Config.FeedOnlyApproved == 1 and value.foodlikedstate == PETFEEDER_FL_APPROVED) or ( PeetFeederPlayer_Config.FeedOnlyApproved == 0 and value.foodlikedstate > 0 ) )then
-- Find lowest instance of the food item
for m = 0, 4 do
for n = 1, 18 do
itemObject = PetFeeder_GetItemObject(m,n);
if ( itemObject and itemObject.name == value.name ) then
-- Using this itemCount because we need the actual value in the slot
local texture, itemCount, locked, quality, readable = GetContainerItemInfo(m,n);
if ( itemCount < lowestQuantity ) then
--DEFAULT_CHAT_FRAME:AddMessage("lowest M = "..m.." lowestN="..n.." lowestqty="..itemCount);
lowestQuantity = itemCount;
lowestM = m;
lowestN = n;
end
end
end
end
local msg = "Feed item in bag,slot="..lowestM..","..lowestN.." which is "..value.name;
PFDebugMessage("PF", msg, "debug" );
PickupContainerItem( lowestM, lowestN );
PetFeeder_Var.feedStartTime = GetTime();
if ( CursorHasItem() ) then
DropItemOnUnit("pet");
PetFeeder_Var.LastItemAttempted = value;
PFDebugMessage("PF", "Fed item "..value.name, "debug" );
end
if ( CursorHasItem() ) then
PickupContainerItem(lowestM, lowestN);
end
value.quantity = value.quantity - 1;
-- Alert
if ( PeetFeederPlayer_Config.Alert ) then
DEFAULT_CHAT_FRAME:AddMessage(PetFeeder_PetName..PETFEEDER_EATS_A..value.name );
end
PetFeeder_Var.Searching = false;
return;
end
end
end
-- No Food Could be Found
PFDebugMessage("PF", "No food could be found to feed the pet", "debug" );
if ( PeetFeederPlayer_Config.Alert ) then
DEFAULT_CHAT_FRAME:AddMessage(PetFeeder_PetName..PETFEEDER_NO_FOOD);
end
PetFeeder_Var.Searching = false;
end
function PetFeeder_ApproveFoodItem( lname )
local _,_,name = string.find(lname, "(.*) %(%d+%)");
if ( not name ) then
name = lname;
end
StaticPopupDialogs["PetFeeder_ApproveFoodItem"] = {
text = PETFEEDER_APPROVE_FOOD..": "..name,
button1 = PETFEEDER_APPROVE,
button2 = PETFEEDER_DISLIKE,
whileDead = 1,
OnAccept = function()
PetFeeder_AddFood(name, PETFEEDER_FL_APPROVED);
PetFeeder_Var.DialogShowing = false;
PetFeeder_Var.Searching = false;
if ( PetFeeder_Var.Feed == true ) then
PetFeeder_Feed();
end
PetFeeder_Update_Frames();
end,
OnCancel = function()
PetFeeder_AddFood(name, PETFEEDER_FL_DISLIKED);
PetFeeder_Var.DialogShowing = false;
PetFeeder_Var.Searching = false;
if ( PetFeeder_Var.Feed == true ) then
-- PetFeeder_Feed();
end
PetFeeder_Update_Frames();
end,
timeout = 0
};
PetFeeder_Var.DialogShowing = true;
StaticPopup_Show("PetFeeder_ApproveFoodItem");
end
------------------
-- Threshold Dropdown
------------------
local function PetFeederFrameDropDown_Initialize()
local info;
for i = 1, getn(PETFEEDER_LEVELS_DROPDOWN), 1 do
info = { };
info.text = PETFEEDER_LEVELS_DROPDOWN[i].name;
info.func = PetFeederFrameDropDownButton_OnClick;
UIDropDownMenu_AddButton(info);
end
end
function PetFeederFrameDropDown_OnLoad()
UIDropDownMenu_Initialize(PetFeederFrameDropDown, PetFeederFrameDropDown_Initialize);
UIDropDownMenu_SetWidth(80);
UIDropDownMenu_SetButtonWidth(24);
UIDropDownMenu_JustifyText("LEFT", PetFeederFrameDropDown)
end
function PetFeederFrameDropDownButton_OnClick()
UIDropDownMenu_SetSelectedID(PetFeederFrameDropDown, this:GetID());
PeetFeederPlayer_Config.Level = UIDropDownMenu_GetSelectedID(PetFeederFrameDropDown);
end
-- Sorting Algorithms
function PetFeeder_SortFoods()
if ( PetFeederPlayer_Foods[PetFeeder_PetName] == nil ) then
PetFeeder_ClearFoods();
return;
end
PetFeeder_UpdateQuantities();
table.sort( PetFeederPlayer_Foods[PetFeeder_PetName], function(a,b) return a.name > b.name end );
if ( PeetFeederPlayer_Config.SortOption == 1 ) then
return;
end;
table.sort( PetFeederPlayer_Foods[PetFeeder_PetName], PetFeeder_CompareItem );
end
--[[
=============================================================================
The primary sort compare method. We may call up to to actual sorting methods
depending on the results. The sorting methods return 1, 0, -1 while
this method results true|false;
returns:
=============================================================================
]]
function PetFeeder_CompareItem(a,b)
local result = 0;
if ( not PeetFeederPlayer_Config.SortOption ) then PeetFeederPlayer_Config.SortOption = 1; end
if ( PETFEEDER_SORTOPTION_DROPDOWN[PeetFeederPlayer_Config.SortOption].func ) then
result = PETFEEDER_SORTOPTION_DROPDOWN[PeetFeederPlayer_Config.SortOption].func(a,b);
end
if ( not PeetFeederPlayer_Config.SortOption2 ) then PeetFeederPlayer_Config.SortOption2 = 3; end
if (PETFEEDER_SORTOPTION_DROPDOWN[PeetFeederPlayer_Config.SortOption2].func and result == 0) then
result = PETFEEDER_SORTOPTION_DROPDOWN[PeetFeederPlayer_Config.SortOption2].func(a,b);
end
return result > 0;
end
function sortQuantityHighLow(a,b)
--table.sort( PetFeeder_Foods[PetFeeder_PetName], function(a,b) return a.quantity > b.quantity end );
if ( a and b ) then
return a.quantity - b.quantity;
else
return 0;
end
end
function sortQuantityLowHigh(a,b)
--table.sort( PetFeeder_Foods[PetFeeder_PetName], function(a,b) return a.quantity < b.quantity end );
if ( a and b ) then
return b.quantity - a.quantity;
else
return 0;
end
end
function sortQualityHighLow(a,b)
--table.sort( PetFeeder_Foods[PetFeeder_PetName], function(a,b) return a.quality > b.quality end );
if ( a and b ) then
return a.quality - b.quality;
else
return 0;
end
end
function sortQualityLowHigh(a,b)
--table.sort( PetFeeder_Foods[PetFeeder_PetName], function(a,b) return a.quality < b.quality end );
if ( a and b ) then
return b.quality - a.quality;
else
return 0;
end
end
function sortAlphabeticallyHighLow(a,b)
--table.sort( PetFeeder_Foods[PetFeeder_PetName], function(a,b) return a.name > b.name end );
if ( a and b ) then
if ( a.name > b.name ) then
return 1;
elseif ( a.name == b.name ) then
return 0;
end
return -1;
end
return 0;
end
function sortAlphabeticallyLowHigh(a,b)
--table.sort( PetFeeder_Foods[PetFeeder_PetName], function(a,b) return a.name < b.name end );
if ( a and b ) then
if ( a.name < b.name ) then
return 1;
elseif ( a.name == b.name ) then
return 0;
end
return -1;
end
return 0;
end
----------------------------
--PetFeeder Checkbuttons--
-----------------------------
function PetFeeder_PF_Enabled_CheckBt_Update(whatValue)
PeetFeederPlayer_Config.Enabled = whatValue;
PetFeeder_Update_Frames();
end
function PetFeeder_PF_AutoFindFood_CheckBt_Update(whatValue)
PeetFeederPlayer_Config.AutoFindFood = whatValue;
if ( PeetFeederPlayer_Config.AutoFindFood ) then
PetFeeder_PopulateFoods();
end
PetFeeder_Update_Frames();
end
function PetFeeder_PF_Alerts_CheckBt_Update(whatValue)
PeetFeederPlayer_Config.Alert = whatValue;
end
function PetFeeder_PF_SkipBuffFoods_CheckBt_Update(whatValue)
PeetFeederPlayer_Config.skipBuffFoods = whatValue;
if ( PeetFeederPlayer_Config.AutoFindFood ) then
PetFeeder_PopulateFoods();
end
PetFeeder_Update_Frames();
end
function PetFeeder_PF_FeedOnlyApproved_CheckBt_Update(whatValue)
PeetFeederPlayer_Config.FeedOnlyApproved = whatValue;
end
function PetFeeder_PF_RequireApproval_CheckBt_Update(whatValue)
PeetFeederPlayer_Config.RequireApproval = whatValue;
end
--[[
=============================================================================
Food Management Routines
=============================================================================
]]
--[[
=============================================================================
Adds a food item to the Food list or the Bad food list. Checks to ensure
that the food isn't already in the table and checks to ensure we aren't
re-adding food the Pet doesn't like.
params:
- PetFeederPlayer_Foods[PetFeeder_PetName]: list to add the item to.
- value : table object for the item
=============================================================================
]]
function PetFeeder_AddFood( value , foodlikedstate )
-- DEFAULT_CHAT_FRAME:AddMessage(value);
-- Make sure PetFeeder_PetName has real pet name
PetFeeder_PetName = UnitName( "pet" );
if ( not PetFeeder_PetName ) then
return;
end
if ( not PetFeederPlayer_Foods[PetFeeder_PetName] ) then
PetFeederPlayer_Foods[PetFeeder_PetName] = {};
end
local changeVal = true;
if ( not foodlikedstate ) then
foodlikedstate = PETFEEDER_FL_UNKNOWN;
changeVal = false;
end
if ( type(value) ~= "table" ) then
local _,_,name = string.find(value, "(.*) %(%d+%)");
if ( not name ) then
name = value;
end
if ( name ) then
for i=1, table.getn( PetFeederPlayer_Foods[PetFeeder_PetName] ) do
if ( PetFeederPlayer_Foods[PetFeeder_PetName][i].name == name ) then
value = PetFeederPlayer_Foods[PetFeeder_PetName][i];
end
end
end
end
if ( not value ) then
return;
end
-- don't add if already in the table
-- just change foodlikedstate state
PFDebugMessage("PF", "Pet Name: "..PetFeeder_PetName, "debug");
if ( not PetFeederPlayer_Foods[PetFeeder_PetName] ) then
PFDebugMessage("PF", "No table for pet", "debug");
end
PFDebugMessage("PF", "Food State Name: "..foodlikedstate, "debug");
for i=1, table.getn( PetFeederPlayer_Foods[PetFeeder_PetName] ) do
if ( PetFeederPlayer_Foods[PetFeeder_PetName][i].name == value.name ) then
if ( changeVal or not PetFeederPlayer_Foods[PetFeeder_PetName][i].foodlikedstate ) then
PFDebugMessage("PF", "Change Food State Name: "..foodlikedstate, "debug");
PetFeederPlayer_Foods[PetFeeder_PetName][i].foodlikedstate = foodlikedstate;
end
return true;
end
end
value.foodlikedstate = foodlikedstate;
table.insert(PetFeederPlayer_Foods[PetFeeder_PetName], value );
return true;
end
function PetFeeder_ClearFoods( foodlikedstate )
if not ( PetFeeder_HasPet() ) then
UIErrorsFrame:AddMessage(PETFEEDER_NEED_PET, 0.8, 0, 0, 1.0, UIERRORS_HOLD_TIME);
return;
end
PetFeeder_PetName = UnitName( "pet" );
if ( not foodlikedstate ) then
PetFeederPlayer_Foods[PetFeeder_PetName] = {};
else
for i=table.getn( PetFeederPlayer_Foods[PetFeeder_PetName] ), 1,-1 do
if ( PetFeederPlayer_Foods[PetFeeder_PetName][i].foodlikedstate == foodlikedstate ) then
table.remove(PetFeederPlayer_Foods[PetFeeder_PetName],i);
-- PetFeeder_AddFood(PetFeederPlayer_Foods[PetFeeder_PetName][i], PETFEEDER_FL_UNKNOWN);
end
end
end
PetFeeder_Update_Frames();
end
function PetFeeder_FoodsFrame_UpdateExt( foodlikedstate )
local frameCoWord;
if ( not foodlikedstate ) then
foodlikedstate = PETFEEDER_FL_UNKNOWN;
end
if ( foodlikedstate == PETFEEDER_FL_UNKNOWN ) then
frameCoWord = "";
elseif ( foodlikedstate == PETFEEDER_FL_APPROVED ) then
frameCoWord = "Approved";
else
frameCoWord = "Unliked";
end
local iItem;
local numEntries = 0;
for index, value in PetFeederPlayer_Foods[PetFeeder_PetName] do
if ( value.foodlikedstate == foodlikedstate ) then
numEntries = numEntries + 1;
end
end
--DEFAULT_CHAT_FRAME:AddMessage(frameCoWord.." numEntries "..numEntries);
local scrollFrame = getglobal("PetFeeder_"..frameCoWord.."FoodsFrameListScrollFrame");
FauxScrollFrame_Update(scrollFrame, numEntries, PETFEEDER_ITEMS_SHOWN, PETFEEDER_ITEM_HEIGHT, nil, nil, nil, nil, nil, PETFEEDER_ITEM_HEIGHT);
local scrollFrameOffset = FauxScrollFrame_GetOffset(scrollFrame);
--DEFAULT_CHAT_FRAME:AddMessage(" scrollFrameOffset "..scrollFrameOffset);
local realItem = 1;
local realIndex = 0;
local usedButtons = 1;
while usedButtons <= PETFEEDER_ITEMS_SHOWN do
realIndex = realIndex + 1
local buttonItem = getglobal("PetFeeder_"..frameCoWord.."FoodsFrameItem"..usedButtons);
if ( usedButtons > numEntries ) then
buttonItem:Hide();
usedButtons = usedButtons + 1;
else
iconTexture = getglobal("PetFeeder_"..frameCoWord.."FoodsFrameItem"..usedButtons.."ItemIconTexture");
if ( PetFeederPlayer_Foods[PetFeeder_PetName][realIndex] ) then
local value = PetFeederPlayer_Foods[PetFeeder_PetName][realIndex];
if ( value.foodlikedstate == foodlikedstate ) then
if ( realItem > scrollFrameOffset ) then
--DEFAULT_CHAT_FRAME:AddMessage(" realIndex "..realIndex.." Name "..value.name);
if ( value.texture ) then
iconTexture:SetTexture( value.texture );
end
local name = value.name.." ("..value.quantity..")";
if ( value.quality ) then
name = name.." - quality: "..value.quality;
end
buttonItem:SetText(name);
buttonItem:Show();
usedButtons = usedButtons + 1
end
realItem = realItem + 1;
end
else
usedButtons = usedButtons + 1;
end
end
end
end
--[[
=============================================================================
This method gets called by the ChatMsg callback functions when it detects
that a pet doesn't like the food we fed it.
- Bad food will be the first one readily available
- Only gets called when a bad food item is detected
- If the user manually feeds, the timer which is set when WE feed, will be off
by more than 2 clicks. We don't want to remove any foods from our list because
we don't know what the pet didn't like.
params:
- t: nil
=============================================================================
]]
function PetFeeder_RemoveBadFood()
PetFeeder_UpdateQuantities();
PFDebugMessage("PF", "Bad food detected "..PetFeeder_Var.LastItemAttempted.name, "debug");
if ( (GetTime() - PetFeeder_Var.feedStartTime) >= 2 ) then
PFDebugMessage("PF", "Not removing bad food as feed wasn't initiated by PF", "debug");
return;
end
PetFeeder_Var.feedStartTime = 0;
for index, value in PetFeederPlayer_Foods[PetFeeder_PetName] do
if ( value.name == PetFeeder_Var.LastItemAttempted.name ) then
if ( PeetFeederPlayer_Config.Alert ) then
DEFAULT_CHAT_FRAME:AddMessage(PETFEEDER_REMOVE_FOOD..value.name);
end
PetFeeder_AddFood( value , PETFEEDER_FL_DISLIKED );
break;
end
end
PetFeeder_Update_Frames();
end
--[[
=============================================================================
Gets called when we want to drop an item onto the list. Identifies which
item in bag,slot is being dropped, gets into about that item and then attempts
to add it to the list.
params:
- PetFeederPlayer_Foods[PetFeeder_PetName]: the name of the list to add the item to.
=============================================================================
]]
function PetFeeder_Update_Frames()
if ( not UnitName( "pet" ) ) then
return;
end
PetFeeder_SortFoods();
PetFeeder_UnlikedFoodsFrame_Update();
PetFeeder_FoodsFrame_Update();
PetFeeder_ApprovedFoodsFrame_Update();
end
function PetFeeder_DroptheItem( accept , foodlikedstate )
if CursorHasItem() and PetFeeder_PickedupItem then
local value = PetFeeder_GetItemObject( PetFeeder_PickedupItem.bag,PetFeeder_PickedupItem.slot );
if ( value ) then
--if ( accept == "any" ) then
-- if ( PetFeederFrame_IsFood( value ) or accept == "any" ) then
PetFeeder_AddFood( value, foodlikedstate );
--end
end
ResetCursor();
PetFeeder_TakeItemOffCursor(PetFeeder_PickedupItem.bag,PetFeeder_PickedupItem.slot);
end -- if has item and we know where it came from
PetFeeder_PickedupItem = nil;
end
--[[
=============================================================================
Returns the item name;
params:
- bag: the bag number of the item
- slot: the slot number of the item
=============================================================================
]]
function PetFeeder_GetItemName(bag, slot)
--local name,totalCount,quality,texture,linktext = PetFeeder_GetItemInfo(bag,slot);
local value = PetFeeder_GetItemObject( m, n );
if ( value ) then
return value.name;
end
return nil;
end
--[[
=============================================================================
Looks through all bags/slots to find the item and adds up the total quantity
for it.
params:
- itemName: name of the item
=============================================================================
]]
function PetFeeder_GetItemCount(itemName)
--DEFAULT_CHAT_FRAME:AddMessage("itemName="..itemName);
local totalItemCount = 0;
local itemQuality = 0;
-- calc total number of items
for m = 0, 4 do
for n = 1, 20 do
local curLinkText = GetContainerItemLink(m, n);
local curname;
if curLinkText then
_, _, id,curname = string.find(curLinkText, "^.*:(%d+):%d+:%d+:%d+.*%[(.*)%].*$");
end
if ( curname == itemName ) then
texture, itemCount, locked, quality, readable = GetContainerItemInfo(m,n);
itemQuality = quality;
if ( itemCount ) then
totalItemCount = totalItemCount + itemCount;
end
end
end
end
if ( PetFeeder_QuestItems[itemName] ) then
--DEFAULT_CHAT_FRAME:AddMessage("Quest itemName="..itemName);
local sum = totalItemCount - PetFeeder_QuestItems[itemName];
--DEFAULT_CHAT_FRAME:AddMessage("sum="..sum);
totalItemCount = max(sum,0);
end
return totalItemCount, itemQuality;
end
function PetFeeder_GetItemObject(bag,slot)
local value = { };
local linktext = GetContainerItemLink(bag, slot);
local itemTexture, itemCount, locked, itemQuality, readable = GetContainerItemInfo(bag,slot);
local itemColor, itemID, itemName;
local restores, overTime;
value.quality = 61;
-- no sense processing if there isn't an item
if ( not linktext ) then
return nil;
end
for itemColor, itemID, itemName in string.gfind(linktext, "|c(%x+)|Hitem:(%d+:%d+:%d+:%d+)|h%[(.-)%]|h|r") do
if ( itemColor and itemID and itemName ~= "" ) then
value.name = itemName;
value.color=itemColor;
value.id=itemID;
--DEFAULT_CHAT_FRAME:AddMessage("color="..itemColor.." itemID="..itemID.." name="..itemName.." texture="..itemTexture);
end
end
if ( not value.id ) then
return nil;
end
local _, _, _, _, itemType, itemSub = GetItemInfo("item:"..value.id)
--DEFAULT_CHAT_FRAME:AddMessage(value.name.." - "..itemType.." - "..itemSub)
value.type = itemSub;
value.texture = itemTexture;
value.link = linktext;
-- Look for 'Use: Restores XXXX health over YY seconds'
-- Regex looks for 'Use:', a space, 1 or more characters, a space, 1 or more digits
-- Return the digits as our version of quality
if ( value ) then
PetFeederTooltip:ClearLines();
PetFeederTooltip:SetHyperlink( "item:"..value.id );
--PFDebugMessage("PF", "Parse ITEM="..value.name, "info");
end
local i;
if ( PetFeederTooltipTextLeft2:GetText() ) then
--PFDebugMessage("PF", "TooltipTextLeft2="..PetFeederTooltipTextLeft2:GetText(), "info");
--for restores in string.gfind(PetFeederTooltipTextLeft2:GetText(), PETFEEDER_RESTORES.." (%d+)") do
for restores in string.gfind(PetFeederTooltipTextLeft2:GetText(), ITEM_SPELL_TRIGGER_ONUSE.." %w+ (%d+)") do
if ( restores ~= "" ) then
value.quality = tonumber(restores);
end
end
end
if ( PetFeederTooltipTextLeft3:GetText() ) then
--PFDebugMessage("PF", "TooltipTextLeft3="..PetFeederTooltipTextLeft3:GetText(), "info");
--for restores in string.gfind(PetFeederTooltipTextLeft3:GetText(), PETFEEDER_RESTORES.." (%d+)") do
for restores in string.gfind(PetFeederTooltipTextLeft3:GetText(), ITEM_SPELL_TRIGGER_ONUSE.." %w+ (%d+)") do
if ( restores ~= "" ) then
value.quality = tonumber(restores);
end
end
end
value.attributeBuffs = false;
if ( PetFeederTooltipTextLeft2:GetText() ) then
for i = 1, getn(PETFEEDER_ITEM_ATTRIBUTE_BUFFS), 1 do
for restores in string.gfind(PetFeederTooltipTextLeft2:GetText(), PETFEEDER_ITEM_ATTRIBUTE_BUFFS[i].search ) do
if ( restores ~= "" ) then
value.attributeBuffs = true;
break;
end
end
end
end
if ( PetFeederTooltipTextLeft3:GetText() and (value.attributeBuffs == false)) then
for i = 1, getn(PETFEEDER_ITEM_ATTRIBUTE_BUFFS), 1 do
for restores in string.gfind(PetFeederTooltipTextLeft3:GetText(), PETFEEDER_ITEM_ATTRIBUTE_BUFFS[i].search ) do
if ( restores ~= "" ) then
value.attributeBuffs = true;
break;
end
end
end
end
local totalItemCount = PetFeeder_GetItemCount( name );
value.quantity = totalItemCount;
-- if ( value.name and value.name == "Mystery Meat" ) then
-- DEFAULT_CHAT_FRAME:AddMessage("object::color="..value.color.." itemID="..value.id.." name="..value.name);
-- DEFAULT_CHAT_FRAME:AddMessage("object::texture="..value.texture.." quality="..value.quality.." link="..value.link);
-- DEFAULT_CHAT_FRAME:AddMessage("object::quantity="..value.quantity);
-- else
-- DEFAULT_CHAT_FRAME:AddMessage("null name in bag="..bag.." slot="..slot);
-- end
if ( value.name ) then
return value;
end
return nil;
end
function PetFeeder_TakeItemOffCursor(srcBag, srcSlot)
if srcBag == -1 then
PickupInventoryItem(srcSlot);
else
PickupContainerItem(srcBag, srcSlot);
end
end
--[[
=============================================================================
Algorithm to auto-populate foods into our food list. Uses pattern matching
to find foods based on popular words associated with foods in the game.
Alt Algorithm: uses texture to determine whether an item is a food item or not.
=============================================================================
]]
function PetFeeder_PopulateFoods()
--DEFAULT_CHAT_FRAME:AddMessage("PetFeeder_PopulateFoods");
if not ( PetFeeder_HasPet() ) then
return;
end
-- Walk through each inventory item
for m = 0, 4 do
for n = 1, 20 do
local value = PetFeeder_GetItemObject( m,n );
if ( value ) then
if ( PetFeederFrame_IsFood( value )
and ( (PeetFeederPlayer_Config.skipBuffFoods and value.attributeBuffs == false)
or (not PeetFeederPlayer_Config.skipBuffFoods)) )
then
-- DEFAULT_CHAT_FRAME:AddMessage(value.name);
PetFeeder_AddFood( value );
end
end
end
end
end
--[[
=============================================================================
Determine whether the item is food or not. We try three things to figure this out
1. If the texture contains the word _Food_ or _Misc_Bowl_ we assume its a food item
2. If the texture contains certain woods (ie: Weapon, Arrow) we eliminate it as a choice
3. Everything else goes through our food filter list to see if they contain
keywords for food items.
Even if we mis-identify something as a food item, it will get eliminated from
the pet's diet list as soon as it tries to eat it and the Add_Food routine
will eliminate it for us.
=============================================================================
]]
function PetFeederFrame_IsFood( item )
local isGood = false;
--DEFAULT_CHAT_FRAME:AddMessage("texture="..item.texture.." item="..item.name);
if ( item.type == PETFEEDER_CONSUMABLE or item.type == PETFEEDER_TRADEGOODS or PF_FOM_IsFood(item) ) then
local foodTextures = { "_Food_", "_Misc_", "_Fish_","_Mushroom_" };
local i
for i=1, table.getn( foodTextures ) do
if ( string.find( item.texture, foodTextures[i] ) ) then
isGood = true;
break;
end
end
else
return false;
end
local notFoodTextures = { "_Gem_", "_ArmorKit_", "_Flower_","_LeatherScrap_","_Bandage_","_MonsterScales_","_Herb_" };
local i
for i=1, table.getn( notFoodTextures ) do
if ( string.find( item.texture, notFoodTextures[i] ) ) then
return false;
end
end
return isGood;
end
--=============================================================================
-- Return information about the pattern
--
-- pattern pattern to find
local function BuffInformation( pattern )
if pattern then
return string.find( PetFeederTooltipTextLeft2:GetText(), pattern );
else
return 1;
end
end
--=============================================================================
-- Called when you click on a Tab
function PetFeederTab_OnClick()
if ( this:GetName() == "PetFeederFrameTab1" ) then
togglePetFeeder("PetFeeder_FoodsFrame");
elseif ( this:GetName() == "PetFeederFrameTab2" ) then
togglePetFeeder("PetFeeder_ApprovedFoodsFrame");
elseif ( this:GetName() == "PetFeederFrameTab3" ) then
togglePetFeeder("PetFeeder_UnlikedFoodsFrame");
end
PlaySound("igCharacterInfoTab");
end
--[[
=============================================================================
Hooked function that gets called when a user picks up an item
=============================================================================
]]
local PetFeeder_Save_PickupContainerItem = PickupContainerItem;
PickupContainerItem = function (bag,slot)
PetFeeder_PickedupItem = { };
PetFeeder_PickedupItem.bag = bag;
PetFeeder_PickedupItem.slot = slot;
return PetFeeder_Save_PickupContainerItem(bag,slot);
end
--[[
=============================================================================
Hooked function that gets called when a user picks up an item
=============================================================================
]]
local PetFeeder_Save_PickupInventoryItem = PickupInventoryItem;
PickupInventoryItem = function (slot)
PetFeeder_PickedupItem = { };
PetFeeder_PickedupItem.bag = -1;
PetFeeder_PickedupItem.slot = slot;
return PetFeeder_Save_PickupInventoryItem(slot);
end
function PetFeederItemButton_OnEnter(lname)
local _,_,name = string.find(lname, "(.*) %(%d+%)");
if ( not name ) then
name = lname;
end
local link = nil;
for index, value in PetFeederPlayer_Foods[PetFeeder_PetName] do
if ( value.name == name ) then
link = "item:"..value.id;
end
end
if( link ) then
GameTooltip:SetOwner(this,"ANCHOR_RIGHT");
GameTooltip:SetHyperlink(link);
GameTooltip:Show();
end
end
function PetFeederItemButton_OnLeave()
if( PetFeederFrame.TooltipButton ) then
PetFeederFrame.TooltipButton = nil;
HideUIPanel(PetFeederDisplayTooltip);
end
end
function FixOldInventoryData()
local itemObject;
for index, value in PetFeederPlayer_Foods[PetFeeder_PetName] do
for m = 0, 4 do
for n = 1, 18 do
itemObject = PetFeeder_GetItemObject(m,n);
if ( itemObject and itemObject.name == value.name ) then
value = itemObject;
break;
end
end
if ( itemObject and itemObject.name == value.name ) then
break;
end
end
end
end
--[[
=============================================================================
Test whether a pet is present or not.
=============================================================================
]]
function PetFeeder_HasPet()
if ( not UnitExists("pet") ) then
return false;
elseif ( UnitName("pet") == "Unknown Entity" or UnitName("pet") == "Unknown" ) then
return false;
end
return true;
end
function PetFeeder_IdFromLink(link)
if (link == nil) then return nil; end
local _, _, itemID = string.find(link, "(%d+):%d+:%d+:%d+");
-- DEFAULT_CHAT_FRAME:AddMessage("link ".. link .." to "..itemID);
if (tonumber(itemID)) then
return tonumber(itemID);
else
return nil;
end
end
Generated by GNU Enscript 1.6.5.90.