diff --git a/playerbot/strategy/Engine.cpp b/playerbot/strategy/Engine.cpp index efb71131d..1090c3e44 100644 --- a/playerbot/strategy/Engine.cpp +++ b/playerbot/strategy/Engine.cpp @@ -466,6 +466,7 @@ void Engine::addStrategy(string name) LogAction("S:+%s", strategy->getName().c_str()); strategies[strategy->getName()] = strategy; + strategy->OnStrategyAdded(); } if(!initMode) Init(); @@ -497,6 +498,7 @@ bool Engine::removeStrategy(string name) return false; LogAction("S:-%s", name.c_str()); + i->second->OnStrategyRemoved(); strategies.erase(i); Init(); return true; diff --git a/playerbot/strategy/Strategy.h b/playerbot/strategy/Strategy.h index 18343bda1..2671952fe 100644 --- a/playerbot/strategy/Strategy.h +++ b/playerbot/strategy/Strategy.h @@ -52,6 +52,9 @@ namespace ai void Update() {} void Reset() {} + virtual void OnStrategyAdded() {} + virtual void OnStrategyRemoved() {} + protected: NamedObjectFactoryList actionNodeFactories; }; diff --git a/playerbot/strategy/actions/ActionContext.h b/playerbot/strategy/actions/ActionContext.h index a40db5b34..a231837b8 100644 --- a/playerbot/strategy/actions/ActionContext.h +++ b/playerbot/strategy/actions/ActionContext.h @@ -123,6 +123,7 @@ namespace ai creators["move to loot"] = &ActionContext::move_to_loot; creators["open loot"] = &ActionContext::open_loot; creators["guard"] = &ActionContext::guard; + creators["return to stay position"] = &ActionContext::return_to_stay_position; creators["move out of enemy contact"] = &ActionContext::move_out_of_enemy_contact; creators["set facing"] = &ActionContext::set_facing; creators["set behind"] = &ActionContext::set_behind; @@ -284,6 +285,7 @@ namespace ai static Action* select_new_target(PlayerbotAI* ai) { return new SelectNewTargetAction(ai); } static Action* attack_duel_opponent(PlayerbotAI* ai) { return new AttackDuelOpponentAction(ai); } static Action* guard(PlayerbotAI* ai) { return new GuardAction(ai); } + static Action* return_to_stay_position(PlayerbotAI* ai) { return new ReturnToStayPositionAction(ai); } static Action* open_loot(PlayerbotAI* ai) { return new OpenLootAction(ai); } static Action* move_to_loot(PlayerbotAI* ai) { return new MoveToLootAction(ai); } static Action* _return(PlayerbotAI* ai) { return new ReturnAction(ai); } diff --git a/playerbot/strategy/actions/ChatShortcutActions.cpp b/playerbot/strategy/actions/ChatShortcutActions.cpp index 518a9fc99..9365b0300 100644 --- a/playerbot/strategy/actions/ChatShortcutActions.cpp +++ b/playerbot/strategy/actions/ChatShortcutActions.cpp @@ -30,8 +30,8 @@ bool FollowChatShortcutAction::Execute(Event& event) return false; ai->Reset(); - ai->ChangeStrategy("+follow,-passive", BotState::BOT_STATE_NON_COMBAT); - ai->ChangeStrategy("-follow,-passive", BotState::BOT_STATE_COMBAT); + ai->ChangeStrategy("+follow,-passive,-stay", BotState::BOT_STATE_NON_COMBAT); + ai->ChangeStrategy("+follow,-passive,-stay", BotState::BOT_STATE_COMBAT); ai::PositionMap& posMap = context->GetValue("position")->Get(); ai::PositionEntry pos = posMap["return"]; @@ -88,8 +88,8 @@ bool StayChatShortcutAction::Execute(Event& event) return false; ai->Reset(); - ai->ChangeStrategy("+stay,-passive", BotState::BOT_STATE_NON_COMBAT); - ai->ChangeStrategy("-follow,-passive", BotState::BOT_STATE_COMBAT); + ai->ChangeStrategy("+stay,-follow,-passive", BotState::BOT_STATE_NON_COMBAT); + ai->ChangeStrategy("+stay,-follow,-passive", BotState::BOT_STATE_COMBAT); SetReturnPosition(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()); diff --git a/playerbot/strategy/actions/PositionAction.cpp b/playerbot/strategy/actions/PositionAction.cpp index 6b4bae74b..fe3e1db12 100644 --- a/playerbot/strategy/actions/PositionAction.cpp +++ b/playerbot/strategy/actions/PositionAction.cpp @@ -147,3 +147,25 @@ bool ReturnAction::isUseful() ai::PositionEntry pos = context->GetValue("position")->Get()[qualifier]; return pos.isSet() && AI_VALUE2(float, "distance", "position_random") > sPlayerbotAIConfig.followDistance; } + +bool ReturnToStayPositionAction::isPossible() +{ + PositionEntry stayPosition = context->GetValue("position")->Get()["stay position"]; + if (stayPosition.isSet()) + { + const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z); + if (distance > sPlayerbotAIConfig.reactDistance) + { + ai->TellError("The stay position is too far to return. I am going to stay where I am now"); + + // Set the stay position to current position + stayPosition.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); + PositionMap& posMap = AI_VALUE(PositionMap&, "position"); + posMap["stay position"] = stayPosition; + } + + return true; + } + + return false; +} \ No newline at end of file diff --git a/playerbot/strategy/actions/PositionAction.h b/playerbot/strategy/actions/PositionAction.h index 96e3da784..e7deeea93 100644 --- a/playerbot/strategy/actions/PositionAction.h +++ b/playerbot/strategy/actions/PositionAction.h @@ -53,4 +53,11 @@ namespace ai virtual bool isUseful(); }; + class ReturnToStayPositionAction : public MoveToPositionAction + { + public: + ReturnToStayPositionAction(PlayerbotAI* ai) : MoveToPositionAction(ai, "move to position", "stay position") {} + + virtual bool isPossible(); + }; } diff --git a/playerbot/strategy/actions/StayActions.h b/playerbot/strategy/actions/StayActions.h index 49e85551f..49878fe83 100644 --- a/playerbot/strategy/actions/StayActions.h +++ b/playerbot/strategy/actions/StayActions.h @@ -5,7 +5,8 @@ namespace ai { - class StayActionBase : public MovementAction { + class StayActionBase : public MovementAction + { public: StayActionBase(PlayerbotAI* ai, string name) : MovementAction(ai, name) {} @@ -13,18 +14,19 @@ namespace ai bool Stay(); }; - class StayAction : public StayActionBase { + class StayAction : public StayActionBase + { public: StayAction(PlayerbotAI* ai) : StayActionBase(ai, "stay") {} virtual bool Execute(Event& event); virtual bool isUseful(); }; - class SitAction : public StayActionBase { + class SitAction : public StayActionBase + { public: SitAction(PlayerbotAI* ai) : StayActionBase(ai, "sit") {} virtual bool Execute(Event& event); virtual bool isUseful(); }; - } diff --git a/playerbot/strategy/generic/StayStrategy.cpp b/playerbot/strategy/generic/StayStrategy.cpp index 2c052cdc9..dc8cf5ebf 100644 --- a/playerbot/strategy/generic/StayStrategy.cpp +++ b/playerbot/strategy/generic/StayStrategy.cpp @@ -1,5 +1,6 @@ #include "botpch.h" #include "../../playerbot.h" +#include "../values/PositionValue.h" #include "StayStrategy.h" using namespace ai; @@ -9,6 +10,38 @@ NextAction** StayStrategy::getDefaultActions() return NextAction::array(0, new NextAction("stay", 1.0f), NULL); } +void StayStrategy::InitTriggers(std::list& triggers) +{ + triggers.push_back(new TriggerNode( + "return to stay position", + NextAction::array(0, new NextAction("return to stay position", 1.5f), NULL))); +} + +void StayStrategy::OnStrategyAdded() +{ + // Set the stay position to current position + AiObjectContext* context = ai->GetAiObjectContext(); + + Player* bot = ai->GetBot(); + PositionEntry stayPosition = AI_VALUE(PositionMap&, "position")["stay position"]; + stayPosition.Set(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()); + + PositionMap& posMap = AI_VALUE(PositionMap&, "position"); + posMap["stay position"] = stayPosition; +} + +void StayStrategy::OnStrategyRemoved() +{ + // Remove the saved stay position + AiObjectContext* context = ai->GetAiObjectContext(); + PositionEntry stayPosition = AI_VALUE(PositionMap&, "position")["stay position"]; + if (stayPosition.isSet()) + { + PositionMap& posMap = AI_VALUE(PositionMap&, "position"); + posMap.erase("stay position"); + } +} + void SitStrategy::InitTriggers(std::list &triggers) { triggers.push_back(new TriggerNode( diff --git a/playerbot/strategy/generic/StayStrategy.h b/playerbot/strategy/generic/StayStrategy.h index a65cc086e..6ffa9ba0b 100644 --- a/playerbot/strategy/generic/StayStrategy.h +++ b/playerbot/strategy/generic/StayStrategy.h @@ -3,12 +3,16 @@ namespace ai { - class StayStrategy : public NonCombatStrategy + class StayStrategy : public Strategy { public: - StayStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {} + StayStrategy(PlayerbotAI* ai) : Strategy(ai) {} virtual string getName() { return "stay"; } + virtual void InitTriggers(std::list& triggers); virtual NextAction** getDefaultActions(); + + void OnStrategyAdded() override; + void OnStrategyRemoved() override; }; class SitStrategy : public NonCombatStrategy @@ -18,5 +22,4 @@ namespace ai virtual string getName() { return "sit"; } virtual void InitTriggers(std::list &triggers); }; - } diff --git a/playerbot/strategy/triggers/GenericTriggers.cpp b/playerbot/strategy/triggers/GenericTriggers.cpp index e88ccab74..75c2d4a2f 100644 --- a/playerbot/strategy/triggers/GenericTriggers.cpp +++ b/playerbot/strategy/triggers/GenericTriggers.cpp @@ -3,6 +3,7 @@ #include "GenericTriggers.h" #include "../../LootObjectStack.h" #include "../../PlayerbotAIConfig.h" +#include "../values/PositionValue.h" using namespace ai; @@ -494,4 +495,16 @@ bool IsFallingFarTrigger::IsActive() bool HasAreaDebuffTrigger::IsActive() { return AI_VALUE2(bool, "has area debuff", "self target"); -} \ No newline at end of file +} + +bool ReturnToStayPositionTrigger::IsActive() +{ + PositionEntry stayPosition = context->GetValue("position")->Get()["stay position"]; + if (stayPosition.isSet()) + { + const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z); + return distance > sPlayerbotAIConfig.followDistance; + } + + return false; +} diff --git a/playerbot/strategy/triggers/GenericTriggers.h b/playerbot/strategy/triggers/GenericTriggers.h index 5cb89f755..a9da05c1d 100644 --- a/playerbot/strategy/triggers/GenericTriggers.h +++ b/playerbot/strategy/triggers/GenericTriggers.h @@ -735,6 +735,14 @@ namespace ai ReturnTrigger(PlayerbotAI* ai) : StayTimeTrigger(ai, sPlayerbotAIConfig.returnDelay, "return") {} }; + class ReturnToStayPositionTrigger : public Trigger + { + public: + ReturnToStayPositionTrigger(PlayerbotAI* ai) : Trigger(ai, "return to stay position", 2) {} + + virtual bool IsActive(); + }; + class GiveItemTrigger : public Trigger { public: diff --git a/playerbot/strategy/triggers/TriggerContext.h b/playerbot/strategy/triggers/TriggerContext.h index 3e8e3d064..a7b1b3e2b 100644 --- a/playerbot/strategy/triggers/TriggerContext.h +++ b/playerbot/strategy/triggers/TriggerContext.h @@ -24,6 +24,7 @@ namespace ai { creators["return"] = &TriggerContext::_return; creators["sit"] = &TriggerContext::sit; + creators["return to stay position"] = &TriggerContext::return_to_stay_position; creators["collision"] = &TriggerContext::collision; creators["timer"] = &TriggerContext::Timer; @@ -252,6 +253,7 @@ namespace ai static Trigger* give_water(PlayerbotAI* ai) { return new GiveWaterTrigger(ai); } static Trigger* no_rti(PlayerbotAI* ai) { return new NoRtiTrigger(ai); } static Trigger* _return(PlayerbotAI* ai) { return new ReturnTrigger(ai); } + static Trigger* return_to_stay_position(PlayerbotAI* ai) { return new ReturnToStayPositionTrigger(ai); } static Trigger* sit(PlayerbotAI* ai) { return new SitTrigger(ai); } static Trigger* far_from_rpg_target(PlayerbotAI* ai) { return new FarFromRpgTargetTrigger(ai); } static Trigger* near_rpg_target(PlayerbotAI* ai) { return new NearRpgTargetTrigger(ai); }