mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge pull request #495 from fuzzdeveloper/move-from-group-and-baron-geddon
new "move from group" action/strat/shortcut-action and molten core (baron geddon) strats
This commit is contained in:
@@ -1504,6 +1504,9 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
|
|||||||
case 469:
|
case 469:
|
||||||
strategyName = "bwl";
|
strategyName = "bwl";
|
||||||
break;
|
break;
|
||||||
|
case 409:
|
||||||
|
strategyName = "mc";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
#include "raids/RaidTriggerContext.h"
|
#include "raids/RaidTriggerContext.h"
|
||||||
#include "raids/naxxramas/RaidNaxxActionContext.h"
|
#include "raids/naxxramas/RaidNaxxActionContext.h"
|
||||||
#include "raids/naxxramas/RaidNaxxTriggerContext.h"
|
#include "raids/naxxramas/RaidNaxxTriggerContext.h"
|
||||||
|
#include "raids/moltencore/RaidMcActionContext.h"
|
||||||
|
#include "raids/moltencore/RaidMcTriggerContext.h"
|
||||||
|
|
||||||
AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
|
AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
|
||||||
{
|
{
|
||||||
@@ -37,6 +39,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
|
|||||||
actionContexts.Add(new RaidActionContext());
|
actionContexts.Add(new RaidActionContext());
|
||||||
actionContexts.Add(new RaidNaxxActionContext());
|
actionContexts.Add(new RaidNaxxActionContext());
|
||||||
actionContexts.Add(new RaidUlduarActionContext());
|
actionContexts.Add(new RaidUlduarActionContext());
|
||||||
|
actionContexts.Add(new RaidMcActionContext());
|
||||||
|
|
||||||
triggerContexts.Add(new TriggerContext());
|
triggerContexts.Add(new TriggerContext());
|
||||||
triggerContexts.Add(new ChatTriggerContext());
|
triggerContexts.Add(new ChatTriggerContext());
|
||||||
@@ -44,6 +47,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
|
|||||||
triggerContexts.Add(new RaidTriggerContext());
|
triggerContexts.Add(new RaidTriggerContext());
|
||||||
triggerContexts.Add(new RaidNaxxTriggerContext());
|
triggerContexts.Add(new RaidNaxxTriggerContext());
|
||||||
triggerContexts.Add(new RaidUlduarTriggerContext());
|
triggerContexts.Add(new RaidUlduarTriggerContext());
|
||||||
|
triggerContexts.Add(new RaidMcTriggerContext());
|
||||||
|
|
||||||
valueContexts.Add(new ValueContext());
|
valueContexts.Add(new ValueContext());
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ PassiveMultiplier::PassiveMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "pa
|
|||||||
if (allowedParts.empty())
|
if (allowedParts.empty())
|
||||||
{
|
{
|
||||||
allowedParts.push_back("follow");
|
allowedParts.push_back("follow");
|
||||||
|
allowedParts.push_back("move from group");
|
||||||
allowedParts.push_back("stay");
|
allowedParts.push_back("stay");
|
||||||
allowedParts.push_back("chat shortcut");
|
allowedParts.push_back("chat shortcut");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "MaintenanceStrategy.h"
|
#include "MaintenanceStrategy.h"
|
||||||
#include "MarkRtiStrategy.h"
|
#include "MarkRtiStrategy.h"
|
||||||
#include "MeleeCombatStrategy.h"
|
#include "MeleeCombatStrategy.h"
|
||||||
|
#include "MoveFromGroupStrategy.h"
|
||||||
#include "NamedObjectContext.h"
|
#include "NamedObjectContext.h"
|
||||||
#include "NonCombatStrategy.h"
|
#include "NonCombatStrategy.h"
|
||||||
#include "PassiveStrategy.h"
|
#include "PassiveStrategy.h"
|
||||||
@@ -115,6 +116,7 @@ public:
|
|||||||
creators["aaoe"] = &StrategyContext::avoid_aoe;
|
creators["aaoe"] = &StrategyContext::avoid_aoe;
|
||||||
creators["move random"] = &StrategyContext::move_random;
|
creators["move random"] = &StrategyContext::move_random;
|
||||||
creators["formation"] = &StrategyContext::combat_formation;
|
creators["formation"] = &StrategyContext::combat_formation;
|
||||||
|
creators["move from group"] = &StrategyContext::move_from_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -179,6 +181,7 @@ private:
|
|||||||
static Strategy* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeStrategy(botAI); }
|
static Strategy* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeStrategy(botAI); }
|
||||||
static Strategy* move_random(PlayerbotAI* ai) { return new MoveRandomStrategy(ai); }
|
static Strategy* move_random(PlayerbotAI* ai) { return new MoveRandomStrategy(ai); }
|
||||||
static Strategy* combat_formation(PlayerbotAI* ai) { return new CombatFormationStrategy(ai); }
|
static Strategy* combat_formation(PlayerbotAI* ai) { return new CombatFormationStrategy(ai); }
|
||||||
|
static Strategy* move_from_group(PlayerbotAI* botAI) { return new MoveFromGroupStrategy(botAI); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MovementStrategyContext : public NamedObjectContext<Strategy>
|
class MovementStrategyContext : public NamedObjectContext<Strategy>
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ public:
|
|||||||
creators["release loot"] = &ActionContext::release_loot;
|
creators["release loot"] = &ActionContext::release_loot;
|
||||||
creators["shoot"] = &ActionContext::shoot;
|
creators["shoot"] = &ActionContext::shoot;
|
||||||
creators["follow"] = &ActionContext::follow;
|
creators["follow"] = &ActionContext::follow;
|
||||||
|
creators["move from group"] = &ActionContext::move_from_group;
|
||||||
creators["flee to master"] = &ActionContext::flee_to_master;
|
creators["flee to master"] = &ActionContext::flee_to_master;
|
||||||
creators["runaway"] = &ActionContext::runaway;
|
creators["runaway"] = &ActionContext::runaway;
|
||||||
creators["stay"] = &ActionContext::stay;
|
creators["stay"] = &ActionContext::stay;
|
||||||
@@ -294,6 +295,7 @@ private:
|
|||||||
static Action* sit(PlayerbotAI* botAI) { return new SitAction(botAI); }
|
static Action* sit(PlayerbotAI* botAI) { return new SitAction(botAI); }
|
||||||
static Action* runaway(PlayerbotAI* botAI) { return new RunAwayAction(botAI); }
|
static Action* runaway(PlayerbotAI* botAI) { return new RunAwayAction(botAI); }
|
||||||
static Action* follow(PlayerbotAI* botAI) { return new FollowAction(botAI); }
|
static Action* follow(PlayerbotAI* botAI) { return new FollowAction(botAI); }
|
||||||
|
static Action* move_from_group(PlayerbotAI* botAI) { return new MoveFromGroupAction(botAI); }
|
||||||
static Action* flee_to_master(PlayerbotAI* botAI) { return new FleeToMasterAction(botAI); }
|
static Action* flee_to_master(PlayerbotAI* botAI) { return new FleeToMasterAction(botAI); }
|
||||||
static Action* add_gathering_loot(PlayerbotAI* botAI) { return new AddGatheringLootAction(botAI); }
|
static Action* add_gathering_loot(PlayerbotAI* botAI) { return new AddGatheringLootAction(botAI); }
|
||||||
static Action* add_loot(PlayerbotAI* botAI) { return new AddLootAction(botAI); }
|
static Action* add_loot(PlayerbotAI* botAI) { return new AddLootAction(botAI); }
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ public:
|
|||||||
creators["stay chat shortcut"] = &ChatActionContext::stay_chat_shortcut;
|
creators["stay chat shortcut"] = &ChatActionContext::stay_chat_shortcut;
|
||||||
creators["flee chat shortcut"] = &ChatActionContext::flee_chat_shortcut;
|
creators["flee chat shortcut"] = &ChatActionContext::flee_chat_shortcut;
|
||||||
creators["runaway chat shortcut"] = &ChatActionContext::runaway_chat_shortcut;
|
creators["runaway chat shortcut"] = &ChatActionContext::runaway_chat_shortcut;
|
||||||
|
creators["move from group chat shortcut"] = &ChatActionContext::move_from_group_chat_shortcut;
|
||||||
creators["grind chat shortcut"] = &ChatActionContext::grind_chat_shortcut;
|
creators["grind chat shortcut"] = &ChatActionContext::grind_chat_shortcut;
|
||||||
creators["tank attack chat shortcut"] = &ChatActionContext::tank_attack_chat_shortcut;
|
creators["tank attack chat shortcut"] = &ChatActionContext::tank_attack_chat_shortcut;
|
||||||
creators["gossip hello"] = &ChatActionContext::gossip_hello;
|
creators["gossip hello"] = &ChatActionContext::gossip_hello;
|
||||||
@@ -208,6 +209,7 @@ private:
|
|||||||
static Action* runaway_chat_shortcut(PlayerbotAI* botAI) { return new GoawayChatShortcutAction(botAI); }
|
static Action* runaway_chat_shortcut(PlayerbotAI* botAI) { return new GoawayChatShortcutAction(botAI); }
|
||||||
static Action* stay_chat_shortcut(PlayerbotAI* botAI) { return new StayChatShortcutAction(botAI); }
|
static Action* stay_chat_shortcut(PlayerbotAI* botAI) { return new StayChatShortcutAction(botAI); }
|
||||||
static Action* follow_chat_shortcut(PlayerbotAI* botAI) { return new FollowChatShortcutAction(botAI); }
|
static Action* follow_chat_shortcut(PlayerbotAI* botAI) { return new FollowChatShortcutAction(botAI); }
|
||||||
|
static Action* move_from_group_chat_shortcut(PlayerbotAI* botAI) { return new MoveFromGroupChatShortcutAction(botAI); }
|
||||||
static Action* gb(PlayerbotAI* botAI) { return new GuildBankAction(botAI); }
|
static Action* gb(PlayerbotAI* botAI) { return new GuildBankAction(botAI); }
|
||||||
static Action* bank(PlayerbotAI* botAI) { return new BankAction(botAI); }
|
static Action* bank(PlayerbotAI* botAI) { return new BankAction(botAI); }
|
||||||
static Action* help(PlayerbotAI* botAI) { return new HelpAction(botAI); }
|
static Action* help(PlayerbotAI* botAI) { return new HelpAction(botAI); }
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ bool FollowChatShortcutAction::Execute(Event event)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// botAI->Reset();
|
// botAI->Reset();
|
||||||
botAI->ChangeStrategy("+follow,-passive,-grind", BOT_STATE_NON_COMBAT);
|
botAI->ChangeStrategy("+follow,-passive,-grind,-move from group", BOT_STATE_NON_COMBAT);
|
||||||
botAI->ChangeStrategy("-follow,-passive,-grind", BOT_STATE_COMBAT);
|
botAI->ChangeStrategy("-follow,-passive,-grind,-move from group", BOT_STATE_COMBAT);
|
||||||
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Set({});
|
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Set({});
|
||||||
|
|
||||||
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
|
||||||
@@ -102,8 +102,8 @@ bool StayChatShortcutAction::Execute(Event event)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
botAI->Reset();
|
botAI->Reset();
|
||||||
botAI->ChangeStrategy("+stay,-passive", BOT_STATE_NON_COMBAT);
|
botAI->ChangeStrategy("+stay,-passive,-move from group", BOT_STATE_NON_COMBAT);
|
||||||
botAI->ChangeStrategy("-follow,-passive", BOT_STATE_COMBAT);
|
botAI->ChangeStrategy("-follow,-passive,-move from group", BOT_STATE_COMBAT);
|
||||||
|
|
||||||
SetReturnPosition(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ());
|
SetReturnPosition(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ());
|
||||||
|
|
||||||
@@ -111,6 +111,21 @@ bool StayChatShortcutAction::Execute(Event event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MoveFromGroupChatShortcutAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
Player* master = GetMaster();
|
||||||
|
if (!master)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// dont need to remove stay or follow, move from group takes priority over both
|
||||||
|
// (see their isUseful() methods)
|
||||||
|
botAI->ChangeStrategy("+move from group", BOT_STATE_NON_COMBAT);
|
||||||
|
botAI->ChangeStrategy("+move from group", BOT_STATE_COMBAT);
|
||||||
|
|
||||||
|
botAI->TellMaster("Moving away from group");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool FleeChatShortcutAction::Execute(Event event)
|
bool FleeChatShortcutAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
Player* master = GetMaster();
|
Player* master = GetMaster();
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ public:
|
|||||||
bool Execute(Event event) override;
|
bool Execute(Event event) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MoveFromGroupChatShortcutAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MoveFromGroupChatShortcutAction(PlayerbotAI* botAI) : Action(botAI, "move from group chat shortcut") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
class FleeChatShortcutAction : public ReturnPositionResetAction
|
class FleeChatShortcutAction : public ReturnPositionResetAction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -48,15 +48,19 @@ bool FollowAction::Execute(Event event)
|
|||||||
|
|
||||||
bool FollowAction::isUseful()
|
bool FollowAction::isUseful()
|
||||||
{
|
{
|
||||||
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr)
|
// move from group takes priority over follow as it's added and removed automatically
|
||||||
{
|
// (without removing/adding follow)
|
||||||
|
if (botAI->HasStrategy("move from group", BOT_STATE_COMBAT) ||
|
||||||
|
botAI->HasStrategy("move from group", BOT_STATE_NON_COMBAT))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
Formation* formation = AI_VALUE(Formation*, "formation");
|
Formation* formation = AI_VALUE(Formation*, "formation");
|
||||||
if (!formation)
|
if (!formation)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
std::string const target = formation->GetTargetName();
|
std::string const target = formation->GetTargetName();
|
||||||
|
|
||||||
Unit* fTarget = nullptr;
|
Unit* fTarget = nullptr;
|
||||||
|
|||||||
@@ -1501,7 +1501,7 @@ void MovementAction::ClearIdleState()
|
|||||||
context->GetValue<PositionMap&>("position")->Get()["random"].Reset();
|
context->GetValue<PositionMap&>("position")->Get()["random"].Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MovementAction::MoveAway(Unit* target)
|
bool MovementAction::MoveAway(Unit* target, float distance)
|
||||||
{
|
{
|
||||||
if (!target)
|
if (!target)
|
||||||
{
|
{
|
||||||
@@ -1511,16 +1511,16 @@ bool MovementAction::MoveAway(Unit* target)
|
|||||||
for (float delta = 0; delta <= M_PI / 2; delta += M_PI / 8)
|
for (float delta = 0; delta <= M_PI / 2; delta += M_PI / 8)
|
||||||
{
|
{
|
||||||
float angle = init_angle + delta;
|
float angle = init_angle + delta;
|
||||||
float dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
|
float dx = bot->GetPositionX() + cos(angle) * distance;
|
||||||
float dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
|
float dy = bot->GetPositionY() + sin(angle) * distance;
|
||||||
float dz = bot->GetPositionZ();
|
float dz = bot->GetPositionZ();
|
||||||
bool exact = true;
|
bool exact = true;
|
||||||
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||||
bot->GetPositionZ(), dx, dy, dz))
|
bot->GetPositionZ(), dx, dy, dz))
|
||||||
{
|
{
|
||||||
// disable prediction if position is invalid
|
// disable prediction if position is invalid
|
||||||
dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
|
dx = bot->GetPositionX() + cos(angle) * distance;
|
||||||
dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
|
dy = bot->GetPositionY() + sin(angle) * distance;
|
||||||
dz = bot->GetPositionZ();
|
dz = bot->GetPositionZ();
|
||||||
exact = false;
|
exact = false;
|
||||||
}
|
}
|
||||||
@@ -1534,15 +1534,15 @@ bool MovementAction::MoveAway(Unit* target)
|
|||||||
}
|
}
|
||||||
exact = true;
|
exact = true;
|
||||||
angle = init_angle - delta;
|
angle = init_angle - delta;
|
||||||
dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
|
dx = bot->GetPositionX() + cos(angle) * distance;
|
||||||
dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
|
dy = bot->GetPositionY() + sin(angle) * distance;
|
||||||
dz = bot->GetPositionZ();
|
dz = bot->GetPositionZ();
|
||||||
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||||
bot->GetPositionZ(), dx, dy, dz))
|
bot->GetPositionZ(), dx, dy, dz))
|
||||||
{
|
{
|
||||||
// disable prediction if position is invalid
|
// disable prediction if position is invalid
|
||||||
dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
|
dx = bot->GetPositionX() + cos(angle) * distance;
|
||||||
dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
|
dy = bot->GetPositionY() + sin(angle) * distance;
|
||||||
dz = bot->GetPositionZ();
|
dz = bot->GetPositionZ();
|
||||||
exact = false;
|
exact = false;
|
||||||
}
|
}
|
||||||
@@ -1554,6 +1554,63 @@ bool MovementAction::MoveAway(Unit* target)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// just calculates average position of group and runs away from that position
|
||||||
|
bool MovementAction::MoveFromGroup(float distance)
|
||||||
|
{
|
||||||
|
LOG_ERROR("playerbots", "MovementAction::MoveFromGroup");
|
||||||
|
//if (Player* master = botAI->GetMaster())
|
||||||
|
//{
|
||||||
|
// return MoveAway(master);
|
||||||
|
//}
|
||||||
|
if (Group* group = bot->GetGroup())
|
||||||
|
{
|
||||||
|
uint32 mapId = bot->GetMapId();
|
||||||
|
float closestDist = FLT_MAX;
|
||||||
|
float x = 0.0f;
|
||||||
|
float y = 0.0f;
|
||||||
|
uint32 count = 0;
|
||||||
|
|
||||||
|
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||||
|
{
|
||||||
|
Player* player = gref->GetSource();
|
||||||
|
if (!player || player == bot || !player->IsAlive() || player->GetMapId() != mapId)
|
||||||
|
continue;
|
||||||
|
float dist = bot->GetDistance2d(player);
|
||||||
|
if (closestDist > dist)
|
||||||
|
closestDist = dist;
|
||||||
|
x += player->GetPositionX();
|
||||||
|
y += player->GetPositionY();
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count && closestDist < distance)
|
||||||
|
{
|
||||||
|
x /= count;
|
||||||
|
y /= count;
|
||||||
|
// x and y are now average position of the group members
|
||||||
|
float angle = bot->GetAngle(x, y) + M_PI;
|
||||||
|
return Move(angle, distance - closestDist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MovementAction::Move(float angle, float distance)
|
||||||
|
{
|
||||||
|
float x = bot->GetPositionX() + cos(angle) * distance;
|
||||||
|
float y = bot->GetPositionY() + sin(angle) * distance;
|
||||||
|
|
||||||
|
//TODO do we need GetMapWaterOrGroundLevel() if we're using CheckCollisionAndGetValidCoords() ?
|
||||||
|
float z = bot->GetMapWaterOrGroundLevel(x, y, bot->GetPositionZ());
|
||||||
|
if (z == -100000.0f || z == -200000.0f)
|
||||||
|
z = bot->GetPositionZ();
|
||||||
|
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||||
|
bot->GetPositionZ(), x, y, z, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return MoveTo(bot->GetMapId(), x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float distance, MovementPriority priority)
|
bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float distance, MovementPriority priority)
|
||||||
{
|
{
|
||||||
if (bot->GetDistance2d(x, y) <= distance)
|
if (bot->GetDistance2d(x, y) <= distance)
|
||||||
@@ -2411,3 +2468,11 @@ bool RotateAroundTheCenterPointAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MoveFromGroupAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
float distance = atoi(event.getParam().c_str());
|
||||||
|
if (!distance)
|
||||||
|
distance = 20.0f; // flee distance from config is too small for this
|
||||||
|
return MoveFromGroup(distance);
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ protected:
|
|||||||
bool Flee(Unit* target);
|
bool Flee(Unit* target);
|
||||||
void ClearIdleState();
|
void ClearIdleState();
|
||||||
void UpdateMovementState();
|
void UpdateMovementState();
|
||||||
bool MoveAway(Unit* target);
|
bool MoveAway(Unit* target, float distance = sPlayerbotAIConfig -> fleeDistance);
|
||||||
|
bool MoveFromGroup(float distance);
|
||||||
|
bool Move(float angle, float distance);
|
||||||
bool MoveInside(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->followDistance, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
bool MoveInside(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->followDistance, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
||||||
void CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important = false);
|
void CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important = false);
|
||||||
Position BestPositionForMeleeToFlee(Position pos, float radius);
|
Position BestPositionForMeleeToFlee(Position pos, float radius);
|
||||||
@@ -248,4 +250,12 @@ protected:
|
|||||||
bool clockwise;
|
bool clockwise;
|
||||||
std::vector<std::pair<float, float>> waypoints;
|
std::vector<std::pair<float, float>> waypoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MoveFromGroupAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MoveFromGroupAction(PlayerbotAI* botAI, std::string const name = "move from group") : MovementAction(botAI, name) {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ bool StayAction::Execute(Event event) { return Stay(); }
|
|||||||
|
|
||||||
bool StayAction::isUseful()
|
bool StayAction::isUseful()
|
||||||
{
|
{
|
||||||
|
// 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) ||
|
||||||
|
botAI->HasStrategy("move from group", BOT_STATE_NON_COMBAT))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Only useful if the bot is currently moving
|
// Only useful if the bot is currently moving
|
||||||
return AI_VALUE2(bool, "moving", "self target");
|
return AI_VALUE2(bool, "moving", "self target");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
|||||||
new TriggerNode("follow", NextAction::array(0, new NextAction("follow chat shortcut", relevance), nullptr)));
|
new TriggerNode("follow", NextAction::array(0, new NextAction("follow chat shortcut", relevance), nullptr)));
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
new TriggerNode("stay", NextAction::array(0, new NextAction("stay chat shortcut", relevance), nullptr)));
|
new TriggerNode("stay", NextAction::array(0, new NextAction("stay chat shortcut", relevance), nullptr)));
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("move from group", NextAction::array(0, new NextAction("move from group chat shortcut", relevance), nullptr)));
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
new TriggerNode("flee", NextAction::array(0, new NextAction("flee chat shortcut", relevance), nullptr)));
|
new TriggerNode("flee", NextAction::array(0, new NextAction("flee chat shortcut", relevance), nullptr)));
|
||||||
triggers.push_back(new TriggerNode(
|
triggers.push_back(new TriggerNode(
|
||||||
|
|||||||
18
src/strategy/generic/MoveFromGroupStrategy.cpp
Normal file
18
src/strategy/generic/MoveFromGroupStrategy.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
|
||||||
|
* and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MoveFromGroupStrategy.h"
|
||||||
|
#include "PassiveMultiplier.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
|
||||||
|
NextAction** MoveFromGroupStrategy::getDefaultActions()
|
||||||
|
{
|
||||||
|
return NextAction::array(0, new NextAction("move from group", 1.0f), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveFromGroupStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||||
|
{
|
||||||
|
multipliers.push_back(new PassiveMultiplier(botAI));
|
||||||
|
}
|
||||||
23
src/strategy/generic/MoveFromGroupStrategy.h
Normal file
23
src/strategy/generic/MoveFromGroupStrategy.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
|
||||||
|
* and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAYERBOT_MOVEFROMGROUPSTRATEGY_H
|
||||||
|
#define _PLAYERBOT_MOVEFROMGROUPSTRATEGY_H
|
||||||
|
|
||||||
|
#include "Strategy.h"
|
||||||
|
|
||||||
|
class PlayerbotAI;
|
||||||
|
|
||||||
|
class MoveFromGroupStrategy : public Strategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MoveFromGroupStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||||
|
|
||||||
|
std::string const getName() override { return "move from group"; }
|
||||||
|
NextAction** getDefaultActions() override;
|
||||||
|
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,21 +5,27 @@
|
|||||||
#include "Strategy.h"
|
#include "Strategy.h"
|
||||||
#include "RaidBwlStrategy.h"
|
#include "RaidBwlStrategy.h"
|
||||||
#include "RaidNaxxStrategy.h"
|
#include "RaidNaxxStrategy.h"
|
||||||
|
#include "RaidMcStrategy.h"
|
||||||
|
|
||||||
class RaidStrategyContext : public NamedObjectContext<Strategy>
|
class RaidStrategyContext : public NamedObjectContext<Strategy>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RaidStrategyContext() : NamedObjectContext<Strategy>(false, true)
|
RaidStrategyContext() : NamedObjectContext<Strategy>(false, true)
|
||||||
{
|
{
|
||||||
|
// TODO should we give these prefixes (eg: "naxx" -> "raid naxx")? because if we don't it's going to end up
|
||||||
|
// very crowded (with possible conflicts) once we have strats for all raids and some dungeons
|
||||||
|
// (mc already very similiar to nc)
|
||||||
creators["naxx"] = &RaidStrategyContext::naxx;
|
creators["naxx"] = &RaidStrategyContext::naxx;
|
||||||
creators["bwl"] = &RaidStrategyContext::bwl;
|
creators["bwl"] = &RaidStrategyContext::bwl;
|
||||||
creators["uld"] = &RaidStrategyContext::uld;
|
creators["uld"] = &RaidStrategyContext::uld;
|
||||||
|
creators["mc"] = &RaidStrategyContext::mc;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); }
|
static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); }
|
||||||
static Strategy* bwl(PlayerbotAI* botAI) { return new RaidBwlStrategy(botAI); }
|
static Strategy* bwl(PlayerbotAI* botAI) { return new RaidBwlStrategy(botAI); }
|
||||||
static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); }
|
static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); }
|
||||||
|
static Strategy* mc(PlayerbotAI* botAI) { return new RaidMcStrategy(botAI); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
22
src/strategy/raids/moltencore/RaidMcActionContext.h
Normal file
22
src/strategy/raids/moltencore/RaidMcActionContext.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _PLAYERBOT_RAIDMCACTIONCONTEXT_H
|
||||||
|
#define _PLAYERBOT_RAIDMCACTIONCONTEXT_H
|
||||||
|
|
||||||
|
#include "Action.h"
|
||||||
|
#include "NamedObjectContext.h"
|
||||||
|
#include "RaidMcActions.h"
|
||||||
|
|
||||||
|
class RaidMcActionContext : public NamedObjectContext<Action>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RaidMcActionContext()
|
||||||
|
{
|
||||||
|
creators["mc check should move from group"] = &RaidMcActionContext::check_should_move_from_group;
|
||||||
|
creators["mc move from baron geddon"] = &RaidMcActionContext::move_from_baron_geddon;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Action* check_should_move_from_group(PlayerbotAI* ai) { return new McCheckShouldMoveFromGroupAction(ai); }
|
||||||
|
static Action* move_from_baron_geddon(PlayerbotAI* ai) { return new McMoveFromBaronGeddonAction(ai); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
43
src/strategy/raids/moltencore/RaidMcActions.cpp
Normal file
43
src/strategy/raids/moltencore/RaidMcActions.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include "RaidMcActions.h"
|
||||||
|
|
||||||
|
#include "Playerbots.h"
|
||||||
|
|
||||||
|
bool McCheckShouldMoveFromGroupAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
if (bot->HasAura(20475)) // barron geddon's living bomb
|
||||||
|
{
|
||||||
|
if (!botAI->HasStrategy("move from group", BotState::BOT_STATE_COMBAT))
|
||||||
|
{
|
||||||
|
// add/remove from both for now as it will make it more obvious to
|
||||||
|
// player if this strat remains on after fight somehow
|
||||||
|
botAI->ChangeStrategy("+move from group", BOT_STATE_NON_COMBAT);
|
||||||
|
botAI->ChangeStrategy("+move from group", BOT_STATE_COMBAT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (botAI->HasStrategy("move from group", BotState::BOT_STATE_COMBAT))
|
||||||
|
{
|
||||||
|
// add/remove from both for now as it will make it more obvious to
|
||||||
|
// player if this strat remains on after fight somehow
|
||||||
|
botAI->ChangeStrategy("-move from group", BOT_STATE_NON_COMBAT);
|
||||||
|
botAI->ChangeStrategy("-move from group", BOT_STATE_COMBAT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool McMoveFromBaronGeddonAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
const float radius = 25.0f; // more than should be needed but bots keep trying to run back in
|
||||||
|
if (Unit* boss = AI_VALUE2(Unit*, "find target", "baron geddon"))
|
||||||
|
{
|
||||||
|
long distToTravel = radius - bot->GetDistance(boss);
|
||||||
|
if (distToTravel > 0)
|
||||||
|
{
|
||||||
|
// float angle = bot->GetAngle(boss) + M_PI;
|
||||||
|
// return Move(angle, distToTravel);
|
||||||
|
return MoveAway(boss, distToTravel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
24
src/strategy/raids/moltencore/RaidMcActions.h
Normal file
24
src/strategy/raids/moltencore/RaidMcActions.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef _PLAYERBOT_RAIDMCACTIONS_H
|
||||||
|
#define _PLAYERBOT_RAIDMCACTIONS_H
|
||||||
|
|
||||||
|
#include "MovementActions.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
|
||||||
|
class McCheckShouldMoveFromGroupAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
McCheckShouldMoveFromGroupAction(PlayerbotAI* botAI, std::string const name = "mc check should move from group")
|
||||||
|
: Action(botAI, name) {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class McMoveFromBaronGeddonAction : public MovementAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
McMoveFromBaronGeddonAction(PlayerbotAI* botAI, std::string const name = "mc move from baron geddon")
|
||||||
|
: MovementAction(botAI, name) {}
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
13
src/strategy/raids/moltencore/RaidMcStrategy.cpp
Normal file
13
src/strategy/raids/moltencore/RaidMcStrategy.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "RaidMcStrategy.h"
|
||||||
|
|
||||||
|
#include "Strategy.h"
|
||||||
|
|
||||||
|
void RaidMcStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
|
{
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("mc living bomb debuff",
|
||||||
|
NextAction::array(0, new NextAction("mc check should move from group", ACTION_RAID), nullptr)));
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("mc baron geddon inferno",
|
||||||
|
NextAction::array(0, new NextAction("mc move from baron geddon", ACTION_RAID), nullptr)));
|
||||||
|
}
|
||||||
17
src/strategy/raids/moltencore/RaidMcStrategy.h
Normal file
17
src/strategy/raids/moltencore/RaidMcStrategy.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef _PLAYERBOT_RAIDMCSTRATEGY_H
|
||||||
|
#define _PLAYERBOT_RAIDMCSTRATEGY_H
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "Multiplier.h"
|
||||||
|
#include "Strategy.h"
|
||||||
|
|
||||||
|
class RaidMcStrategy : public Strategy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RaidMcStrategy(PlayerbotAI* ai) : Strategy(ai) {}
|
||||||
|
virtual std::string const getName() override { return "mc"; }
|
||||||
|
virtual void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||||
|
// virtual void InitMultipliers(std::vector<Multiplier*> &multipliers) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
22
src/strategy/raids/moltencore/RaidMcTriggerContext.h
Normal file
22
src/strategy/raids/moltencore/RaidMcTriggerContext.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _PLAYERBOT_RAIDMCTRIGGERCONTEXT_H
|
||||||
|
#define _PLAYERBOT_RAIDMCTRIGGERCONTEXT_H
|
||||||
|
|
||||||
|
#include "AiObjectContext.h"
|
||||||
|
#include "NamedObjectContext.h"
|
||||||
|
#include "RaidMcTriggers.h"
|
||||||
|
|
||||||
|
class RaidMcTriggerContext : public NamedObjectContext<Trigger>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RaidMcTriggerContext()
|
||||||
|
{
|
||||||
|
creators["mc living bomb debuff"] = &RaidMcTriggerContext::living_bomb_debuff;
|
||||||
|
creators["mc baron geddon inferno"] = &RaidMcTriggerContext::baron_geddon_inferno;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Trigger* living_bomb_debuff(PlayerbotAI* ai) { return new McLivingBombDebuffTrigger(ai); }
|
||||||
|
static Trigger* baron_geddon_inferno(PlayerbotAI* ai) { return new McBaronGeddonInfernoTrigger(ai); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
22
src/strategy/raids/moltencore/RaidMcTriggers.cpp
Normal file
22
src/strategy/raids/moltencore/RaidMcTriggers.cpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "RaidMcTriggers.h"
|
||||||
|
|
||||||
|
#include "SharedDefines.h"
|
||||||
|
|
||||||
|
bool McLivingBombDebuffTrigger::IsActive()
|
||||||
|
{
|
||||||
|
// if bot has barron geddon's living bomb, we need to add strat, otherwise we need to remove
|
||||||
|
// only do when fighting baron geddon (to avoid modifying strat set by player outside this fight)
|
||||||
|
if (Unit* boss = AI_VALUE2(Unit*, "find target", "baron geddon"))
|
||||||
|
{
|
||||||
|
if (boss->IsInCombat())
|
||||||
|
return bot->HasAura(20475) != botAI->HasStrategy("move from group", BotState::BOT_STATE_COMBAT);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool McBaronGeddonInfernoTrigger::IsActive()
|
||||||
|
{
|
||||||
|
if (Unit* boss = AI_VALUE2(Unit*, "find target", "baron geddon"))
|
||||||
|
return boss->HasAura(19695);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
22
src/strategy/raids/moltencore/RaidMcTriggers.h
Normal file
22
src/strategy/raids/moltencore/RaidMcTriggers.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _PLAYERBOT_RAIDMCTRIGGERS_H
|
||||||
|
#define _PLAYERBOT_RAIDMCTRIGGERS_H
|
||||||
|
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "Playerbots.h"
|
||||||
|
#include "Trigger.h"
|
||||||
|
|
||||||
|
class McLivingBombDebuffTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
McLivingBombDebuffTrigger(PlayerbotAI* botAI) : Trigger(botAI, "mc living bomb debuff") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class McBaronGeddonInfernoTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
McBaronGeddonInfernoTrigger(PlayerbotAI* botAI) : Trigger(botAI, "mc baron geddon inferno") {}
|
||||||
|
bool IsActive() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -72,6 +72,7 @@ public:
|
|||||||
creators["gbank"] = &ChatTriggerContext::gb;
|
creators["gbank"] = &ChatTriggerContext::gb;
|
||||||
creators["bank"] = &ChatTriggerContext::bank;
|
creators["bank"] = &ChatTriggerContext::bank;
|
||||||
creators["follow"] = &ChatTriggerContext::follow;
|
creators["follow"] = &ChatTriggerContext::follow;
|
||||||
|
creators["move from group"] = &ChatTriggerContext::move_from_group;
|
||||||
creators["stay"] = &ChatTriggerContext::stay;
|
creators["stay"] = &ChatTriggerContext::stay;
|
||||||
creators["flee"] = &ChatTriggerContext::flee;
|
creators["flee"] = &ChatTriggerContext::flee;
|
||||||
creators["grind"] = &ChatTriggerContext::grind;
|
creators["grind"] = &ChatTriggerContext::grind;
|
||||||
@@ -164,6 +165,7 @@ private:
|
|||||||
static Trigger* tank_attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "tank attack"); }
|
static Trigger* tank_attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "tank attack"); }
|
||||||
static Trigger* stay(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "stay"); }
|
static Trigger* stay(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "stay"); }
|
||||||
static Trigger* follow(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "follow"); }
|
static Trigger* follow(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "follow"); }
|
||||||
|
static Trigger* move_from_group(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "move from group"); }
|
||||||
static Trigger* gb(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "gb"); }
|
static Trigger* gb(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "gb"); }
|
||||||
static Trigger* bank(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "bank"); }
|
static Trigger* bank(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "bank"); }
|
||||||
static Trigger* help(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "help"); }
|
static Trigger* help(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "help"); }
|
||||||
|
|||||||
Reference in New Issue
Block a user