Skip to content

Commit

Permalink
Add pet cast action and pet autocast command
Browse files Browse the repository at this point in the history
  • Loading branch information
davidonete committed Dec 4, 2023
1 parent bf351d8 commit 5df163a
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 71 deletions.
81 changes: 45 additions & 36 deletions playerbot/PlayerbotAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "Group.h"
#include "Pet.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
#include "../ahbot/AhBot.h"
#include "GuildTaskMgr.h"
#include "PlayerbotDbStore.h"
Expand Down Expand Up @@ -3157,25 +3158,9 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget, bool
target = bot;

Pet* pet = bot->GetPet();
SpellEntry const *pSpellInfo = sServerFacade.LookupSpellInfo(spellId);
if (pet && pet->HasSpell(spellId))
{
bool autocast = false;
for(AutoSpellList::iterator i = pet->m_autospells.begin(); i != pet->m_autospells.end(); ++i)
{
if (*i == spellId)
{
autocast = true;
break;
}
}

pet->ToggleAutocast(spellId, !autocast);
ostringstream out;
out << (autocast ? "|cffff0000|Disabling" : "|cFF00ff00|Enabling") << " pet auto-cast for ";
out << chatHelper.formatSpell(pSpellInfo);
TellPlayer(GetMaster(), out);
return true;
if (pet && pet->HasSpell(spellId))
{
return CastPetSpell(spellId, target);
}

aiObjectContext->GetValue<LastMovement&>("last movement")->Get().Set(NULL);
Expand Down Expand Up @@ -3221,6 +3206,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget, bool
return false;
}

const SpellEntry* pSpellInfo = sServerFacade.LookupSpellInfo(spellId);
Spell *spell = new Spell(bot, pSpellInfo, false);

SpellCastTargets targets;
Expand Down Expand Up @@ -3374,25 +3360,9 @@ bool PlayerbotAI::CastSpell(uint32 spellId, float x, float y, float z, Item* ite
return false;

Pet* pet = bot->GetPet();
SpellEntry const* pSpellInfo = sServerFacade.LookupSpellInfo(spellId);
if (pet && pet->HasSpell(spellId))
{
bool autocast = false;
for (AutoSpellList::iterator i = pet->m_autospells.begin(); i != pet->m_autospells.end(); ++i)
{
if (*i == spellId)
{
autocast = true;
break;
}
}

pet->ToggleAutocast(spellId, !autocast);
ostringstream out;
out << (autocast ? "|cffff0000|Disabling" : "|cFF00ff00|Enabling") << " pet auto-cast for ";
out << chatHelper.formatSpell(pSpellInfo);
TellPlayer(GetMaster(), out);
return true;
return CastPetSpell(spellId, nullptr);
}

aiObjectContext->GetValue<LastMovement&>("last movement")->Get().Set(NULL);
Expand Down Expand Up @@ -3440,6 +3410,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, float x, float y, float z, Item* ite
return false;
}

const SpellEntry* pSpellInfo = sServerFacade.LookupSpellInfo(spellId);
Spell* spell = new Spell(bot, pSpellInfo, false);

SpellCastTargets targets;
Expand Down Expand Up @@ -3564,6 +3535,44 @@ bool PlayerbotAI::CastSpell(uint32 spellId, float x, float y, float z, Item* ite
return true;
}

bool PlayerbotAI::CastPetSpell(uint32 spellId, Unit* target)
{
Pet* pet = bot->GetPet();
if (pet && spellId && pet->HasSpell(spellId))
{
auto IsAutocastActive = [&pet, &spellId]() -> bool
{
for (AutoSpellList::iterator i = pet->m_autospells.begin(); i != pet->m_autospells.end(); ++i)
{
if (*i == spellId)
{
return true;
}
}

return false;
};

// Send pet spell action packet
uint8 flag = ACT_PASSIVE;
if (IsAutocastable(spellId))
{
flag = IsAutocastActive() ? ACT_ENABLED : ACT_DISABLED;
}

uint32 command = (flag << 24) | spellId;

WorldPacket data(CMSG_PET_ACTION);
data << pet->GetObjectGuid();
data << command;
data << (target ? target->GetObjectGuid() : ObjectGuid());
bot->GetSession()->HandlePetAction(data);
return true;
}

return false;
}

bool PlayerbotAI::CanCastVehicleSpell(uint32 spellId, Unit* target)
{
#ifdef MANGOSBOT_TWO
Expand Down
1 change: 1 addition & 0 deletions playerbot/PlayerbotAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ class PlayerbotAI : public PlayerbotAIBase
virtual bool CastSpell(string name, Unit* target, Item* itemTarget = NULL, bool waitForSpell = true, uint32* outSpellDuration = NULL, bool canUseReagentCheat = true);
bool CastSpell(uint32 spellId, Unit* target, Item* itemTarget = NULL, bool waitForSpell = true, uint32* outSpellDuration = NULL, bool canUseReagentCheat = true);
bool CastSpell(uint32 spellId, float x, float y, float z, Item* itemTarget = NULL, bool waitForSpell = true, uint32* outSpellDuration = NULL, bool canUseReagentCheat = true);
bool CastPetSpell(uint32 spellId, Unit* target);
bool CastVehicleSpell(uint32 spellId, Unit* target);
bool CastVehicleSpell(uint32 spellId, float x, float y, float z);

Expand Down
43 changes: 11 additions & 32 deletions playerbot/PlayerbotFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,12 +543,13 @@ void PlayerbotFactory::AddConsumables()

void PlayerbotFactory::InitPet()
{
// Randomize a new pet (only for hunters)
if (bot->getClass() != CLASS_HUNTER)
return;

Pet* pet = bot->GetPet();
if (!pet)
{
if (bot->getClass() != CLASS_HUNTER)
return;

Map* map = bot->GetMap();
if (!map)
return;
Expand Down Expand Up @@ -606,43 +607,23 @@ void PlayerbotFactory::InitPet()
pet->setFaction(bot->GetFaction());
pet->SetLevel(bot->GetLevel());
pet->InitStatsForLevel(bot->GetLevel());
#ifdef MANGOSBOT_TWO

#else
#ifndef MANGOSBOT_TWO
pet->SetLoyaltyLevel(BEST_FRIEND);
#endif
pet->SetPower(POWER_HAPPINESS, HAPPINESS_LEVEL_SIZE * 2);
pet->GetCharmInfo()->SetPetNumber(sObjectMgr.GeneratePetNumber(), true);
#ifdef CMANGOS
pet->GetMap()->Add((Creature*)pet);
pet->AIM_Initialize();
#endif
#ifdef MANGOS
pet->GetMap()->Add((Creature*)pet);
pet->AIM_Initialize();
#endif
pet->InitPetCreateSpells();
#ifdef CMANGOS
pet->LearnPetPassives();
pet->CastPetAuras(true);
pet->CastOwnerTalentAuras();
pet->UpdateAllStats();
#endif
#ifdef MANGOS
pet->LearnPetPassives();
pet->CastPetAuras(true);
pet->CastOwnerTalentAuras();
pet->UpdateAllStats();
#endif
bot->SetPet(pet);
bot->SetPetGuid(pet->GetObjectGuid());

sLog.outDebug( "Bot %s: assign pet %d (%d level)", bot->GetName(), co->Entry, bot->GetLevel());
pet->SavePetToDB(PET_SAVE_AS_CURRENT
#ifdef CMANGOS
, bot
#endif
);
pet->SavePetToDB(PET_SAVE_AS_CURRENT, bot);
bot->PetSpellInitialize();
break;
}
Expand All @@ -653,9 +634,7 @@ void PlayerbotFactory::InitPet()
{
pet->InitStatsForLevel(bot->GetLevel());
pet->SetLevel(bot->GetLevel());
#ifdef MANGOSBOT_TWO

#else
#ifndef MANGOSBOT_TWO
pet->SetLoyaltyLevel(BEST_FRIEND);
#endif
pet->SetPower(POWER_HAPPINESS, HAPPINESS_LEVEL_SIZE * 2);
Expand Down Expand Up @@ -695,7 +674,7 @@ void PlayerbotFactory::InitPetSpells()
// TO DO
// ...
}
// Warlock pets should auto learn spells on WOTLK
// Warlock pets should auto learn spells in WOTLK
#ifndef MANGOSBOT_TWO
else if (bot->getClass() == CLASS_WARLOCK)
{
Expand Down Expand Up @@ -769,7 +748,7 @@ void PlayerbotFactory::InitPetSpells()
spellList[PET_FELHUNTER].push_back(std::pair(64, 27280));
}

// Voidwalker
// Voidwalker spells
{
// Consume Shadows
spellList[PET_VOIDWALKER].push_back(std::pair(18, 17767));
Expand Down Expand Up @@ -814,7 +793,7 @@ void PlayerbotFactory::InitPetSpells()
spellList[PET_VOIDWALKER].push_back(std::pair(80, 47984));
}

// Succubus
// Succubus spells
{
// Lash of Pain
spellList[PET_SUCCUBUS].push_back(std::pair(20, 7814));
Expand All @@ -841,7 +820,7 @@ void PlayerbotFactory::InitPetSpells()
spellList[PET_SUCCUBUS].push_back(std::pair(70, 27275));
}

// Felguard
// Felguard spells
{
// Anguish
spellList[PET_FELGUARD].push_back(std::pair(50, 33698));
Expand Down
2 changes: 2 additions & 0 deletions playerbot/strategy/actions/ChatActionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ namespace ai
creators["focus heal target"] = &ChatActionContext::focus_heal_target;
creators["follow target"] = &ChatActionContext::follow_target;
creators["self resurrect"] = &ChatActionContext::self_resurrect;
creators["pet"] = &ChatActionContext::pet;

creators["guild invite"] = &ChatActionContext::guild_invite;
creators["guild join"] = &ChatActionContext::guild_join;
Expand Down Expand Up @@ -295,6 +296,7 @@ namespace ai
static Action* focus_heal_target(PlayerbotAI* ai) { return new SetFocusHealTargetAction(ai); }
static Action* follow_target(PlayerbotAI* ai) { return new SetFollowTargetAction(ai); }
static Action* self_resurrect(PlayerbotAI* ai) { return new SelfResurrectAction(ai); }
static Action* pet(PlayerbotAI* ai) { return new SetPetAction(ai); }

static Action* guild_invite(PlayerbotAI* ai) { return new GuildInviteAction(ai); }
static Action* guild_join(PlayerbotAI* ai) { return new GuildJoinAction(ai); }
Expand Down
85 changes: 82 additions & 3 deletions playerbot/strategy/actions/GenericActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ bool InitializePetAction::isUseful()

return !hasTamedPet;
}
// Warlock pets should auto learn spells in WOTLK
#ifndef MANGOSBOT_TWO
else if (bot->getClass() == CLASS_WARLOCK)
{
// Only initialize if warlock has the pet summoned
Expand Down Expand Up @@ -212,7 +214,7 @@ bool InitializePetAction::isUseful()
spellList[PET_FELHUNTER].push_back(std::pair(64, 27280));
}

// Voidwalker
// Voidwalker spells
{
// Consume Shadows
spellList[PET_VOIDWALKER].push_back(std::pair(18, 17767));
Expand Down Expand Up @@ -257,7 +259,7 @@ bool InitializePetAction::isUseful()
spellList[PET_VOIDWALKER].push_back(std::pair(80, 47984));
}

// Succubus
// Succubus spells
{
// Lash of Pain
spellList[PET_SUCCUBUS].push_back(std::pair(20, 7814));
Expand All @@ -284,7 +286,7 @@ bool InitializePetAction::isUseful()
spellList[PET_SUCCUBUS].push_back(std::pair(70, 27275));
}

// Felguard
// Felguard spells
{
// Anguish
spellList[PET_FELGUARD].push_back(std::pair(50, 33698));
Expand Down Expand Up @@ -330,7 +332,84 @@ bool InitializePetAction::isUseful()
}
}
}
#endif
}

return false;
}

bool SetPetAction::Execute(Event& event)
{
Player* requester = event.getOwner() ? event.getOwner() : GetMaster();
std::string command = event.getParam();

// Extract the command and the parameters
std::string parameter;
size_t spacePos = command.find_first_of(" ");
if (spacePos != std::string::npos)
{
parameter = command.substr(spacePos + 1);
command = command.substr(0, spacePos);
}

Pet* pet = bot->GetPet();
if (pet)
{
if (command == "autocast")
{
const std::string& spellName = parameter;
if (!spellName.empty())
{
const uint32 spellId = AI_VALUE2(uint32, "spell id", spellName);
if (pet->HasSpell(spellId) && IsAutocastable(spellId))
{
auto IsAutocastActive = [&pet, &spellId]() -> bool
{
for (AutoSpellList::iterator i = pet->m_autospells.begin(); i != pet->m_autospells.end(); ++i)
{
if (*i == spellId)
{
return true;
}
}

return false;
};

const bool autocastActive = IsAutocastActive();
pet->ToggleAutocast(spellId, !autocastActive);

ostringstream out;
out << (autocastActive ? "Disabling" : "Enabling") << " pet autocast for ";
out << ChatHelper::formatSpell(sServerFacade.LookupSpellInfo(spellId));
ai->TellPlayer(GetMaster(), out);

return true;
}
else
{
ai->TellPlayer(requester, "I can't set to autocast that spell.");
}
}
else
{
ai->TellPlayer(requester, "Please specify a pet spell to set the autocast.");
}
}
else
{
ai->TellPlayer(requester, "Please specify a pet command (Like autocast).");
}
}
else
{
ai->TellPlayer(requester, "I don't have any pets");
}

return false;
}

bool SetPetAction::isUseful()
{
return bot->GetPet();
}
8 changes: 8 additions & 0 deletions playerbot/strategy/actions/GenericActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,12 @@ namespace ai
bool Execute(Event& event) override;
bool isUseful() override;
};

class SetPetAction : public Action
{
public:
SetPetAction(PlayerbotAI* ai) : Action(ai, "pet") {}
bool Execute(Event& event) override;
bool isUseful() override;
};
}
Loading

0 comments on commit 5df163a

Please sign in to comment.