Generalise dragon flanking action

This commit is contained in:
Bobblybook
2024-10-12 23:51:00 +11:00
parent 161a29657b
commit b526a07303
3 changed files with 67 additions and 0 deletions

View File

@@ -94,6 +94,7 @@ public:
creators["avoid aoe"] = &ActionContext::avoid_aoe;
creators["combat formation move"] = &ActionContext::combat_formation_move;
creators["tank face"] = &ActionContext::tank_face;
creators["rear flank"] = &ActionContext::rear_flank;
creators["disperse set"] = &ActionContext::disperse_set;
creators["gift of the naaru"] = &ActionContext::gift_of_the_naaru;
creators["shoot"] = &ActionContext::shoot;
@@ -278,6 +279,7 @@ private:
static Action* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeAction(botAI); }
static Action* combat_formation_move(PlayerbotAI* botAI) { return new CombatFormationMoveAction(botAI); }
static Action* tank_face(PlayerbotAI* botAI) { return new TankFaceAction(botAI); }
static Action* rear_flank(PlayerbotAI* botAI) { return new RearFlankAction(botAI); }
static Action* disperse_set(PlayerbotAI* botAI) { return new DisperseSetAction(botAI); }
static Action* gift_of_the_naaru(PlayerbotAI* botAI) { return new CastGiftOfTheNaaruAction(botAI); }
static Action* lifeblood(PlayerbotAI* botAI) { return new CastLifeBloodAction(botAI); }

View File

@@ -2372,6 +2372,46 @@ bool TankFaceAction::Execute(Event event)
return MoveTo(bot->GetMapId(), nearest.GetPositionX(), nearest.GetPositionY(), nearest.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT);
}
bool RearFlankAction::isUseful()
{
Unit* target = AI_VALUE(Unit*, "current target");
if (!target) { return false; }
// Need to double the front angle check to account for mirrored angle.
bool inFront = target->HasInArc(2.f * minAngle, bot);
// Rear check does not need to double this angle as the logic is inverted
// and we are subtracting from 2pi.
bool inRear = !target->HasInArc((2.f * M_PI) - maxAngle, bot);
return inFront || inRear;
}
bool RearFlankAction::Execute(Event event)
{
Unit* target = AI_VALUE(Unit*, "current target");
if (!target) { return false; }
float angle = frand(minAngle, maxAngle);
float baseDistance = bot->GetMeleeRange(target) * 0.5f;
Position leftFlank = target->GetPosition();
Position rightFlank = target->GetPosition();
Position* destination = nullptr;
leftFlank.RelocatePolarOffset(angle, baseDistance + distance);
rightFlank.RelocatePolarOffset(-angle, baseDistance + distance);
if (bot->GetExactDist2d(leftFlank) < bot->GetExactDist2d(rightFlank))
{
destination = &leftFlank;
}
else
{
destination = &rightFlank;
}
return MoveTo(bot->GetMapId(), destination->GetPositionX(), destination->GetPositionY(), destination->GetPositionZ(),
false, false, false, true, MovementPriority::MOVEMENT_COMBAT);
}
bool DisperseSetAction::Execute(Event event)
{
std::string const text = event.getParam();

View File

@@ -18,6 +18,9 @@ class Unit;
class WorldObject;
class Position;
#define ANGLE_45_DEG (static_cast<float>(M_PI) / 4.f)
#define ANGLE_90_DEG M_PI_2
#define ANGLE_120_DEG (2.f * static_cast<float>(M_PI) / 3.f)
class MovementAction : public Action
{
@@ -144,6 +147,27 @@ public:
bool Execute(Event event) override;
};
class RearFlankAction : public MovementAction
{
// 90 degree minimum angle prevents any frontal cleaves/breaths and avoids parry-hasting the boss.
// 120 degree maximum angle leaves a 120 degree symmetrical cone at the tail end which is usually enough to avoid tail swipes.
// Some dragons or mobs may have different danger zone angles, override if needed.
public:
RearFlankAction(PlayerbotAI* botAI, float distance = 0.0f, float minAngle = ANGLE_90_DEG, float maxAngle = ANGLE_120_DEG)
: MovementAction(botAI, "rear flank")
{
this->distance = distance;
this->minAngle = minAngle;
this->maxAngle = maxAngle;
}
bool Execute(Event event) override;
bool isUseful() override;
protected:
float distance, minAngle, maxAngle;
};
class DisperseSetAction : public Action
{
public:
@@ -268,4 +292,5 @@ public:
bool Execute(Event event) override;
};
#endif