mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Stay strategy improvement (#1072)
* - Stay Strategy work in combat and with RTSC * - Fixed summon with stay strategy * - Added new stay strategy support for chat commands
This commit is contained in:
@@ -1105,9 +1105,9 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet)
|
||||
}
|
||||
}
|
||||
|
||||
QueueChatResponse(
|
||||
ChatQueuedReply{msgtype, guid1.GetCounter(), guid2.GetCounter(), message, chanName,
|
||||
name, time(nullptr) + urand(inCombat ? 10 : 5, inCombat ? 25 : 15)});
|
||||
QueueChatResponse(ChatQueuedReply{msgtype, guid1.GetCounter(), guid2.GetCounter(), message,
|
||||
chanName, name,
|
||||
time(nullptr) + urand(inCombat ? 10 : 5, inCombat ? 25 : 15)});
|
||||
GetAiObjectContext()->GetValue<time_t>("last said", "chat")->Set(time(0) + urand(5, 25));
|
||||
return;
|
||||
}
|
||||
@@ -1244,10 +1244,10 @@ void PlayerbotAI::ChangeEngine(BotState type)
|
||||
switch (type)
|
||||
{
|
||||
case BOT_STATE_COMBAT:
|
||||
// LOG_DEBUG("playerbots", "=== {} COMBAT ===", bot->GetName().c_str());
|
||||
ChangeEngineOnCombat();
|
||||
break;
|
||||
case BOT_STATE_NON_COMBAT:
|
||||
// LOG_DEBUG("playerbots", "=== {} NON-COMBAT ===", bot->GetName().c_str());
|
||||
ChangeEngineOnNonCombat();
|
||||
break;
|
||||
case BOT_STATE_DEAD:
|
||||
// LOG_DEBUG("playerbots", "=== {} DEAD ===", bot->GetName().c_str());
|
||||
@@ -1258,6 +1258,23 @@ void PlayerbotAI::ChangeEngine(BotState type)
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerbotAI::ChangeEngineOnCombat()
|
||||
{
|
||||
if (HasStrategy("stay", BOT_STATE_COMBAT))
|
||||
{
|
||||
aiObjectContext->GetValue<PositionInfo>("pos", "stay")
|
||||
->Set(PositionInfo(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId()));
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerbotAI::ChangeEngineOnNonCombat()
|
||||
{
|
||||
if (HasStrategy("stay", BOT_STATE_NON_COMBAT))
|
||||
{
|
||||
aiObjectContext->GetValue<PositionInfo>("pos", "stay")->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerbotAI::DoNextAction(bool min)
|
||||
{
|
||||
if (!bot->IsInWorld() || bot->IsBeingTeleported() || (GetMaster() && GetMaster()->IsBeingTeleported()))
|
||||
@@ -2848,7 +2865,6 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell,
|
||||
if (!target)
|
||||
target = bot;
|
||||
|
||||
|
||||
if (Pet* pet = bot->GetPet())
|
||||
if (pet->HasSpell(spellid))
|
||||
return true;
|
||||
@@ -3041,8 +3057,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, GameObject* goTarget, bool checkH
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlayerbotAI::CanCastSpell(uint32 spellid, float x, float y, float z, bool checkHasSpell,
|
||||
Item* itemTarget)
|
||||
bool PlayerbotAI::CanCastSpell(uint32 spellid, float x, float y, float z, bool checkHasSpell, Item* itemTarget)
|
||||
{
|
||||
if (!spellid)
|
||||
return false;
|
||||
@@ -3070,7 +3085,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, float x, float y, float z, bool c
|
||||
Spell* spell = new Spell(bot, spellInfo, TRIGGERED_NONE);
|
||||
|
||||
spell->m_targets.SetDst(x, y, z, 0.f);
|
||||
|
||||
|
||||
Item* item = itemTarget ? itemTarget : aiObjectContext->GetValue<Item*>("item for spell", spellid)->Get();
|
||||
spell->m_targets.SetItemTarget(item);
|
||||
|
||||
@@ -4296,8 +4311,8 @@ bool PlayerbotAI::AllowActive(ActivityType activityType)
|
||||
mod = AutoScaleActivity(mod);
|
||||
}
|
||||
|
||||
uint32 ActivityNumber = GetFixedBotNumer(100,
|
||||
sPlayerbotAIConfig->botActiveAlone * static_cast<float>(mod) / 100 * 0.01f);
|
||||
uint32 ActivityNumber =
|
||||
GetFixedBotNumer(100, sPlayerbotAIConfig->botActiveAlone * static_cast<float>(mod) / 100 * 0.01f);
|
||||
|
||||
return ActivityNumber <=
|
||||
(sPlayerbotAIConfig->botActiveAlone * mod) /
|
||||
@@ -4356,7 +4371,8 @@ void PlayerbotAI::RemoveShapeshift()
|
||||
RemoveAura("moonkin form");
|
||||
RemoveAura("travel form");
|
||||
RemoveAura("cat form");
|
||||
RemoveAura("flight form"); bot->RemoveAura(33943); // The latter added for now as RemoveAura("flight form") currently does not work.
|
||||
RemoveAura("flight form");
|
||||
bot->RemoveAura(33943); // The latter added for now as RemoveAura("flight form") currently does not work.
|
||||
RemoveAura("swift flight form");
|
||||
RemoveAura("aquatic form");
|
||||
RemoveAura("ghost wolf");
|
||||
@@ -4943,11 +4959,9 @@ Item* PlayerbotAI::FindAmmo() const
|
||||
}
|
||||
|
||||
// Search inventory for the correct ammo type
|
||||
return FindItemInInventory([requiredAmmoType](ItemTemplate const* pItemProto) -> bool
|
||||
{
|
||||
return pItemProto->Class == ITEM_CLASS_PROJECTILE &&
|
||||
pItemProto->SubClass == requiredAmmoType;
|
||||
});
|
||||
return FindItemInInventory(
|
||||
[requiredAmmoType](ItemTemplate const* pItemProto) -> bool
|
||||
{ return pItemProto->Class == ITEM_CLASS_PROJECTILE && pItemProto->SubClass == requiredAmmoType; });
|
||||
}
|
||||
|
||||
return nullptr; // No ranged weapon equipped
|
||||
@@ -6178,9 +6192,10 @@ bool PlayerbotAI::IsHealingSpell(uint32 spellFamilyName, flag96 spellFalimyFlags
|
||||
return spellFalimyFlags & healingFlags;
|
||||
}
|
||||
|
||||
|
||||
SpellFamilyNames PlayerbotAI::Class2SpellFamilyName(uint8 cls) {
|
||||
switch (cls) {
|
||||
SpellFamilyNames PlayerbotAI::Class2SpellFamilyName(uint8 cls)
|
||||
{
|
||||
switch (cls)
|
||||
{
|
||||
case CLASS_WARRIOR:
|
||||
return SPELLFAMILY_WARRIOR;
|
||||
case CLASS_PALADIN:
|
||||
|
||||
@@ -392,6 +392,8 @@ public:
|
||||
void HandleMasterOutgoingPacket(WorldPacket const& packet);
|
||||
void HandleTeleportAck();
|
||||
void ChangeEngine(BotState type);
|
||||
void ChangeEngineOnCombat();
|
||||
void ChangeEngineOnNonCombat();
|
||||
void DoNextAction(bool minimal = false);
|
||||
virtual bool DoSpecificAction(std::string const name, Event event = Event(), bool silent = false,
|
||||
std::string const qualifier = "");
|
||||
|
||||
@@ -135,6 +135,7 @@ public:
|
||||
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;
|
||||
@@ -271,6 +272,7 @@ private:
|
||||
static Action* drop_target(PlayerbotAI* botAI) { return new DropTargetAction(botAI); }
|
||||
static Action* attack_duel_opponent(PlayerbotAI* botAI) { return new AttackDuelOpponentAction(botAI); }
|
||||
static Action* guard(PlayerbotAI* botAI) { return new GuardAction(botAI); }
|
||||
static Action* return_to_stay_position(PlayerbotAI* botAI) { return new ReturnToStayPositionAction(botAI); }
|
||||
static Action* open_loot(PlayerbotAI* botAI) { return new OpenLootAction(botAI); }
|
||||
static Action* move_to_loot(PlayerbotAI* botAI) { return new MoveToLootAction(botAI); }
|
||||
static Action* _return(PlayerbotAI* botAI) { return new ReturnAction(botAI); }
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "Playerbots.h"
|
||||
#include "PositionValue.h"
|
||||
|
||||
void ReturnPositionResetAction::ResetReturnPosition()
|
||||
void PositionsResetAction::ResetReturnPosition()
|
||||
{
|
||||
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
||||
PositionInfo pos = posMap["return"];
|
||||
@@ -18,7 +18,7 @@ void ReturnPositionResetAction::ResetReturnPosition()
|
||||
posMap["return"] = pos;
|
||||
}
|
||||
|
||||
void ReturnPositionResetAction::SetReturnPosition(float x, float y, float z)
|
||||
void PositionsResetAction::SetReturnPosition(float x, float y, float z)
|
||||
{
|
||||
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
||||
PositionInfo pos = posMap["return"];
|
||||
@@ -26,6 +26,22 @@ void ReturnPositionResetAction::SetReturnPosition(float x, float y, float z)
|
||||
posMap["return"] = pos;
|
||||
}
|
||||
|
||||
void PositionsResetAction::ResetStayPosition()
|
||||
{
|
||||
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
||||
PositionInfo pos = posMap["stay"];
|
||||
pos.Reset();
|
||||
posMap["stay"] = pos;
|
||||
}
|
||||
|
||||
void PositionsResetAction::SetStayPosition(float x, float y, float z)
|
||||
{
|
||||
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
||||
PositionInfo pos = posMap["stay"];
|
||||
pos.Set(x, y, z, botAI->GetBot()->GetMapId());
|
||||
posMap["stay"] = pos;
|
||||
}
|
||||
|
||||
bool FollowChatShortcutAction::Execute(Event event)
|
||||
{
|
||||
Player* master = GetMaster();
|
||||
@@ -34,7 +50,7 @@ bool FollowChatShortcutAction::Execute(Event event)
|
||||
|
||||
// botAI->Reset();
|
||||
botAI->ChangeStrategy("+follow,-passive,-grind,-move from group", BOT_STATE_NON_COMBAT);
|
||||
botAI->ChangeStrategy("-follow,-passive,-grind,-move from group", BOT_STATE_COMBAT);
|
||||
botAI->ChangeStrategy("-stay,-follow,-passive,-grind,-move from group", BOT_STATE_COMBAT);
|
||||
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Reset();
|
||||
|
||||
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
||||
@@ -42,6 +58,10 @@ bool FollowChatShortcutAction::Execute(Event event)
|
||||
pos.Reset();
|
||||
posMap["return"] = pos;
|
||||
|
||||
pos = posMap["stay"];
|
||||
pos.Reset();
|
||||
posMap["stay"] = pos;
|
||||
|
||||
if (bot->IsInCombat())
|
||||
{
|
||||
Formation* formation = AI_VALUE(Formation*, "formation");
|
||||
@@ -103,9 +123,10 @@ bool StayChatShortcutAction::Execute(Event event)
|
||||
|
||||
botAI->Reset();
|
||||
botAI->ChangeStrategy("+stay,-passive,-move from group", BOT_STATE_NON_COMBAT);
|
||||
botAI->ChangeStrategy("-follow,-passive,-move from group", BOT_STATE_COMBAT);
|
||||
botAI->ChangeStrategy("+stay,-follow,-passive,-move from group", BOT_STATE_COMBAT);
|
||||
|
||||
SetReturnPosition(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ());
|
||||
SetStayPosition(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ());
|
||||
|
||||
botAI->TellMaster("Staying");
|
||||
return true;
|
||||
@@ -133,10 +154,11 @@ bool FleeChatShortcutAction::Execute(Event event)
|
||||
return false;
|
||||
|
||||
botAI->Reset();
|
||||
botAI->ChangeStrategy("+follow,+passive", BOT_STATE_NON_COMBAT);
|
||||
botAI->ChangeStrategy("+follow,+passive", BOT_STATE_COMBAT);
|
||||
botAI->ChangeStrategy("+follow,-stay,+passive", BOT_STATE_NON_COMBAT);
|
||||
botAI->ChangeStrategy("+follow,-stay,+passive", BOT_STATE_COMBAT);
|
||||
|
||||
ResetReturnPosition();
|
||||
ResetStayPosition();
|
||||
|
||||
if (bot->GetMapId() != master->GetMapId() || bot->GetDistance(master) > sPlayerbotAIConfig->sightDistance)
|
||||
{
|
||||
@@ -155,10 +177,11 @@ bool GoawayChatShortcutAction::Execute(Event event)
|
||||
return false;
|
||||
|
||||
botAI->Reset();
|
||||
botAI->ChangeStrategy("+runaway", BOT_STATE_NON_COMBAT);
|
||||
botAI->ChangeStrategy("+runaway", BOT_STATE_COMBAT);
|
||||
botAI->ChangeStrategy("+runaway,-stay", BOT_STATE_NON_COMBAT);
|
||||
botAI->ChangeStrategy("+runaway,-stay", BOT_STATE_COMBAT);
|
||||
|
||||
ResetReturnPosition();
|
||||
ResetStayPosition();
|
||||
|
||||
botAI->TellMaster("Running away");
|
||||
return true;
|
||||
@@ -171,9 +194,10 @@ bool GrindChatShortcutAction::Execute(Event event)
|
||||
return false;
|
||||
|
||||
botAI->Reset();
|
||||
botAI->ChangeStrategy("+grind,-passive", BOT_STATE_NON_COMBAT);
|
||||
botAI->ChangeStrategy("+grind,-passive,-stay", BOT_STATE_NON_COMBAT);
|
||||
|
||||
ResetReturnPosition();
|
||||
ResetStayPosition();
|
||||
|
||||
botAI->TellMaster("Grinding");
|
||||
return true;
|
||||
@@ -193,6 +217,7 @@ bool TankAttackChatShortcutAction::Execute(Event event)
|
||||
botAI->ChangeStrategy("-passive", BOT_STATE_COMBAT);
|
||||
|
||||
ResetReturnPosition();
|
||||
ResetStayPosition();
|
||||
|
||||
botAI->TellMaster("Attacking");
|
||||
return true;
|
||||
|
||||
@@ -10,13 +10,15 @@
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class ReturnPositionResetAction : public Action
|
||||
class PositionsResetAction : public Action
|
||||
{
|
||||
public:
|
||||
ReturnPositionResetAction(PlayerbotAI* botAI, std::string const name) : Action(botAI, name) {}
|
||||
PositionsResetAction(PlayerbotAI* botAI, std::string const name) : Action(botAI, name) {}
|
||||
|
||||
void ResetReturnPosition();
|
||||
void SetReturnPosition(float x, float y, float z);
|
||||
void ResetStayPosition();
|
||||
void SetStayPosition(float x, float y, float z);
|
||||
};
|
||||
|
||||
class FollowChatShortcutAction : public MovementAction
|
||||
@@ -27,10 +29,10 @@ public:
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class StayChatShortcutAction : public ReturnPositionResetAction
|
||||
class StayChatShortcutAction : public PositionsResetAction
|
||||
{
|
||||
public:
|
||||
StayChatShortcutAction(PlayerbotAI* botAI) : ReturnPositionResetAction(botAI, "stay chat shortcut") {}
|
||||
StayChatShortcutAction(PlayerbotAI* botAI) : PositionsResetAction(botAI, "stay chat shortcut") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
@@ -43,34 +45,34 @@ public:
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class FleeChatShortcutAction : public ReturnPositionResetAction
|
||||
class FleeChatShortcutAction : public PositionsResetAction
|
||||
{
|
||||
public:
|
||||
FleeChatShortcutAction(PlayerbotAI* botAI) : ReturnPositionResetAction(botAI, "flee chat shortcut") {}
|
||||
FleeChatShortcutAction(PlayerbotAI* botAI) : PositionsResetAction(botAI, "flee chat shortcut") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class GoawayChatShortcutAction : public ReturnPositionResetAction
|
||||
class GoawayChatShortcutAction : public PositionsResetAction
|
||||
{
|
||||
public:
|
||||
GoawayChatShortcutAction(PlayerbotAI* botAI) : ReturnPositionResetAction(botAI, "runaway chat shortcut") {}
|
||||
GoawayChatShortcutAction(PlayerbotAI* botAI) : PositionsResetAction(botAI, "runaway chat shortcut") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class GrindChatShortcutAction : public ReturnPositionResetAction
|
||||
class GrindChatShortcutAction : public PositionsResetAction
|
||||
{
|
||||
public:
|
||||
GrindChatShortcutAction(PlayerbotAI* botAI) : ReturnPositionResetAction(botAI, "grind chat shortcut") {}
|
||||
GrindChatShortcutAction(PlayerbotAI* botAI) : PositionsResetAction(botAI, "grind chat shortcut") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class TankAttackChatShortcutAction : public ReturnPositionResetAction
|
||||
class TankAttackChatShortcutAction : public PositionsResetAction
|
||||
{
|
||||
public:
|
||||
TankAttackChatShortcutAction(PlayerbotAI* botAI) : ReturnPositionResetAction(botAI, "tank attack chat shortcut") {}
|
||||
TankAttackChatShortcutAction(PlayerbotAI* botAI) : PositionsResetAction(botAI, "tank attack chat shortcut") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
@@ -159,3 +159,25 @@ bool ReturnAction::isUseful()
|
||||
PositionInfo pos = context->GetValue<PositionMap&>("position")->Get()[qualifier];
|
||||
return pos.isSet() && AI_VALUE2(float, "distance", "position_random") > sPlayerbotAIConfig->followDistance;
|
||||
}
|
||||
|
||||
bool ReturnToStayPositionAction::isPossible()
|
||||
{
|
||||
PositionMap& posMap = AI_VALUE(PositionMap&, "position");
|
||||
PositionInfo stayPosition = posMap["stay"];
|
||||
if (stayPosition.isSet())
|
||||
{
|
||||
const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z);
|
||||
if (distance > sPlayerbotAIConfig->reactDistance)
|
||||
{
|
||||
botAI->TellMaster("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());
|
||||
posMap["stay"] = stayPosition;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,13 @@ public:
|
||||
GuardAction(PlayerbotAI* botAI) : MoveToPositionAction(botAI, "move to position", "guard") {}
|
||||
};
|
||||
|
||||
class ReturnToStayPositionAction : public MoveToPositionAction
|
||||
{
|
||||
public:
|
||||
ReturnToStayPositionAction(PlayerbotAI* ai) : MoveToPositionAction(ai, "move to position", "stay") {}
|
||||
virtual bool isPossible();
|
||||
};
|
||||
|
||||
class SetReturnPositionAction : public Action
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -14,6 +14,12 @@ bool ReachTargetAction::Execute(Event event) { return ReachCombatTo(AI_VALUE(Uni
|
||||
|
||||
bool ReachTargetAction::isUseful()
|
||||
{
|
||||
// do not move while staying
|
||||
if (botAI->HasStrategy("stay", botAI->GetState()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// do not move while casting
|
||||
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr)
|
||||
{
|
||||
@@ -30,6 +36,12 @@ std::string const ReachTargetAction::GetTargetName() { return "current target";
|
||||
|
||||
bool CastReachTargetSpellAction::isUseful()
|
||||
{
|
||||
// do not move while staying
|
||||
if (botAI->HasStrategy("stay", botAI->GetState()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "current target"),
|
||||
(distance + sPlayerbotAIConfig->contactDistance));
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Playerbots.h"
|
||||
#include "RTSCValues.h"
|
||||
#include "RtscAction.h"
|
||||
#include "PositionValue.h"
|
||||
|
||||
Creature* SeeSpellAction::CreateWps(Player* wpOwner, float x, float y, float z, float o, uint32 entry, Creature* lastWp,
|
||||
bool important)
|
||||
@@ -123,6 +124,15 @@ bool SeeSpellAction::MoveToSpell(WorldPosition& spellPosition, bool inFormation)
|
||||
if (inFormation)
|
||||
SetFormationOffset(spellPosition);
|
||||
|
||||
if (botAI->HasStrategy("stay", botAI->GetState()))
|
||||
{
|
||||
PositionMap& posMap = AI_VALUE(PositionMap&, "position");
|
||||
PositionInfo stayPosition = posMap["stay"];
|
||||
|
||||
stayPosition.Set(spellPosition.getX(), spellPosition.getY(), spellPosition.getZ(), spellPosition.getMapId());
|
||||
posMap["stay"] = stayPosition;
|
||||
}
|
||||
|
||||
if (bot->IsWithinLOS(spellPosition.getX(), spellPosition.getY(), spellPosition.getZ()))
|
||||
return MoveNear(spellPosition.getMapId(), spellPosition.getX(), spellPosition.getY(), spellPosition.getZ(), 0);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Event.h"
|
||||
#include "LastMovementValue.h"
|
||||
#include "Playerbots.h"
|
||||
#include "PositionValue.h"
|
||||
|
||||
bool StayActionBase::Stay()
|
||||
{
|
||||
@@ -42,6 +43,17 @@ bool StayAction::Execute(Event event) { return Stay(); }
|
||||
|
||||
bool StayAction::isUseful()
|
||||
{
|
||||
// Check if the bots is in stay position
|
||||
PositionInfo stayPosition = AI_VALUE(PositionMap&, "position")["stay"];
|
||||
if (stayPosition.isSet())
|
||||
{
|
||||
const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z);
|
||||
if (sPlayerbotAIConfig->followDistance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// move from group takes priority over stay as it's added and removed automatically
|
||||
// (without removing/adding stay)
|
||||
if (botAI->HasStrategy("move from group", BOT_STATE_COMBAT) ||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Playerbots.h"
|
||||
#include "PositionValue.h"
|
||||
|
||||
bool UseMeetingStoneAction::Execute(Event event)
|
||||
{
|
||||
@@ -224,6 +225,16 @@ bool SummonAction::Teleport(Player* summoner, Player* player)
|
||||
player->GetMotionMaster()->Clear();
|
||||
AI_VALUE(LastMovement&, "last movement").clear();
|
||||
player->TeleportTo(mapId, x, y, z, 0);
|
||||
|
||||
if (botAI->HasStrategy("stay", botAI->GetState()))
|
||||
{
|
||||
PositionMap& posMap = AI_VALUE(PositionMap&, "position");
|
||||
PositionInfo stayPosition = posMap["stay"];
|
||||
|
||||
stayPosition.Set(x,y, z, mapId);
|
||||
posMap["stay"] = stayPosition;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,13 @@
|
||||
|
||||
#include "Playerbots.h"
|
||||
|
||||
void StayStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode(
|
||||
"return to stay position",
|
||||
NextAction::array(0, new NextAction("return to stay position", ACTION_MOVE), nullptr)));
|
||||
}
|
||||
|
||||
NextAction** StayStrategy::getDefaultActions() { return NextAction::array(0, new NextAction("stay", 1.0f), nullptr); }
|
||||
|
||||
void SitStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
class StayStrategy : public NonCombatStrategy
|
||||
class StayStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
StayStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) {}
|
||||
StayStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "stay"; }
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
NextAction** getDefaultActions() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "ObjectGuid.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Playerbots.h"
|
||||
#include "PositionValue.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "ThreatMgr.h"
|
||||
@@ -507,11 +508,22 @@ bool IsBehindTargetTrigger::IsActive()
|
||||
|
||||
bool IsNotBehindTargetTrigger::IsActive()
|
||||
{
|
||||
if (botAI->HasStrategy("stay", botAI->GetState()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
return target && !AI_VALUE2(bool, "behind", "current target");
|
||||
}
|
||||
|
||||
bool IsNotFacingTargetTrigger::IsActive() { return !AI_VALUE2(bool, "facing", "current target"); }
|
||||
bool IsNotFacingTargetTrigger::IsActive()
|
||||
{
|
||||
if (botAI->HasStrategy("stay", botAI->GetState()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !AI_VALUE2(bool, "facing", "current target");
|
||||
}
|
||||
|
||||
bool HasCcTargetTrigger::IsActive()
|
||||
{
|
||||
@@ -599,6 +611,18 @@ bool NewPlayerNearbyTrigger::IsActive() { return AI_VALUE(ObjectGuid, "new playe
|
||||
|
||||
bool CollisionTrigger::IsActive() { return AI_VALUE2(bool, "collision", "self target"); }
|
||||
|
||||
bool ReturnToStayPositionTrigger::IsActive()
|
||||
{
|
||||
PositionInfo stayPosition = AI_VALUE(PositionMap&, "position")["stay"];
|
||||
if (stayPosition.isSet())
|
||||
{
|
||||
const float distance = bot->GetDistance(stayPosition.x, stayPosition.y, stayPosition.z);
|
||||
return distance > sPlayerbotAIConfig->followDistance;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GiveItemTrigger::IsActive()
|
||||
{
|
||||
return AI_VALUE2(Unit*, "party member without item", item) && AI_VALUE2(uint32, "item count", item);
|
||||
|
||||
@@ -827,6 +827,14 @@ public:
|
||||
SitTrigger(PlayerbotAI* botAI) : StayTimeTrigger(botAI, sPlayerbotAIConfig->sitDelay, "sit") {}
|
||||
};
|
||||
|
||||
class ReturnToStayPositionTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
ReturnToStayPositionTrigger(PlayerbotAI* ai) : Trigger(ai, "return to stay position", 2) {}
|
||||
|
||||
virtual bool IsActive() override;
|
||||
};
|
||||
|
||||
class ReturnTrigger : public StayTimeTrigger
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
{
|
||||
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;
|
||||
@@ -228,6 +229,7 @@ private:
|
||||
static Trigger* give_water(PlayerbotAI* botAI) { return new GiveWaterTrigger(botAI); }
|
||||
static Trigger* no_rti(PlayerbotAI* botAI) { return new NoRtiTrigger(botAI); }
|
||||
static Trigger* _return(PlayerbotAI* botAI) { return new ReturnTrigger(botAI); }
|
||||
static Trigger* return_to_stay_position(PlayerbotAI* ai) { return new ReturnToStayPositionTrigger(ai); }
|
||||
static Trigger* sit(PlayerbotAI* botAI) { return new SitTrigger(botAI); }
|
||||
static Trigger* far_from_rpg_target(PlayerbotAI* botAI) { return new FarFromRpgTargetTrigger(botAI); }
|
||||
static Trigger* near_rpg_target(PlayerbotAI* botAI) { return new NearRpgTargetTrigger(botAI); }
|
||||
|
||||
@@ -63,3 +63,25 @@ bool PositionValue::Load(std::string const text)
|
||||
}
|
||||
|
||||
WorldPosition CurrentPositionValue::Calculate() { return WorldPosition(bot); }
|
||||
|
||||
PositionInfo SinglePositionValue::Calculate()
|
||||
{
|
||||
PositionMap& posMap = AI_VALUE(PositionMap&, "position");
|
||||
return posMap[getQualifier()];
|
||||
}
|
||||
|
||||
void SinglePositionValue::Set(PositionInfo value)
|
||||
{
|
||||
PositionMap& posMap = AI_VALUE(PositionMap&, "position");
|
||||
PositionInfo pos = posMap[getQualifier()];
|
||||
pos = value;
|
||||
posMap[getQualifier()] = pos;
|
||||
}
|
||||
|
||||
void SinglePositionValue::Reset()
|
||||
{
|
||||
PositionMap& posMap = AI_VALUE(PositionMap&, "position");
|
||||
PositionInfo pos = posMap[getQualifier()];
|
||||
pos.Reset();
|
||||
posMap[getQualifier()] = pos;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef _PLAYERBOT_POSITIONVALUE_H
|
||||
#define _PLAYERBOT_POSITIONVALUE_H
|
||||
|
||||
#include "NamedObjectContext.h"
|
||||
#include "TravelMgr.h"
|
||||
#include "Value.h"
|
||||
|
||||
@@ -15,6 +16,10 @@ class PositionInfo
|
||||
{
|
||||
public:
|
||||
PositionInfo() : valueSet(false), x(0), y(0), z(0), mapId(0) {}
|
||||
PositionInfo(float x, float y, float z, uint32 mapId, bool valueSet = true)
|
||||
: valueSet(valueSet), x(x), y(y), z(z), mapId(mapId)
|
||||
{
|
||||
}
|
||||
PositionInfo(PositionInfo const& other)
|
||||
: valueSet(other.valueSet), x(other.x), y(other.y), z(other.z), mapId(other.mapId)
|
||||
{
|
||||
@@ -72,4 +77,13 @@ public:
|
||||
WorldPosition Calculate() override;
|
||||
};
|
||||
|
||||
class SinglePositionValue : public CalculatedValue<PositionInfo>, public Qualified
|
||||
{
|
||||
public:
|
||||
SinglePositionValue(PlayerbotAI* ai, std::string name = "pos") : CalculatedValue(ai, name), Qualified() {};
|
||||
virtual PositionInfo Calculate() override;
|
||||
virtual void Set(PositionInfo value) override;
|
||||
virtual void Reset() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -194,6 +194,7 @@ public:
|
||||
creators["rti cc"] = &ValueContext::rti_cc;
|
||||
creators["rti"] = &ValueContext::rti;
|
||||
creators["position"] = &ValueContext::position;
|
||||
creators["pos"] = &ValueContext::pos;
|
||||
creators["current position"] = &ValueContext::current_position;
|
||||
creators["threat"] = &ValueContext::threat;
|
||||
|
||||
@@ -342,6 +343,7 @@ private:
|
||||
static UntypedValue* attackers(PlayerbotAI* botAI) { return new AttackersValue(botAI); }
|
||||
|
||||
static UntypedValue* position(PlayerbotAI* botAI) { return new PositionValue(botAI); }
|
||||
static UntypedValue* pos(PlayerbotAI* ai) { return new SinglePositionValue(ai); }
|
||||
static UntypedValue* current_position(PlayerbotAI* botAI) { return new CurrentPositionValue(botAI); }
|
||||
static UntypedValue* rti(PlayerbotAI* botAI) { return new RtiValue(botAI); }
|
||||
static UntypedValue* rti_cc(PlayerbotAI* botAI) { return new RtiCcValue(botAI); }
|
||||
|
||||
Reference in New Issue
Block a user