mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-13 00:58:33 +00:00
Closer the original solution, i dont wanna drift to much away without really good reason. At this point i still see NPC and bots moving through the levels or even falling out the levels here and there. I verified whether the MovePoint signature changes and related params itself in playerbots has anything todo with it, even when params are hardcoded the behavior remains. It could be deeper problem, but for now it seems core problem. Therefore i dont wanna change to much until the dust has settled a bit in core itself. I havent implemented moveTakeOff or moveLand which are basically responsible for the transitions phases between ground and air visa versa. I have version where i use takeOff for the animation, which means moving vertical. For now i am gonna leave for what it is. PS: also includes additional movement fix for AreaTriggerAction which we missed first time after the core update on movements. @Wishmaster117 Been testing and trying a lot in the background on find solutions and causes. The general solutions remains removed some tweaks, altered code here and there. With the general idea to keep closer to the original code for now at least. Testing: - Class abilities: Slow fall (priest), Flight Form (druid) : Green - BG: Green - Swimming and walking shallow waters: Green - Takeoff and land when following master: Green - Boat and zeppelins: Green - Flymount and ground walking: Green - Water Walking (shaman), Path of Frost (DK): Green - Water Walking (shaman), Path of Frost (DK) transisions; flying, swimming, water walking: Green Skipping pets when group water walking, path of frost, once core pathing changes has settled more i will add it. Which is easy but i dont wanna add more edge cases and code branches for now.
339 lines
11 KiB
C++
339 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
|
*/
|
|
|
|
#ifndef _PLAYERBOT_MOVEMENTACTIONS_H
|
|
#define _PLAYERBOT_MOVEMENTACTIONS_H
|
|
|
|
#include <cmath>
|
|
|
|
#include "Action.h"
|
|
#include "LastMovementValue.h"
|
|
#include "PlayerbotAIConfig.h"
|
|
|
|
class Player;
|
|
class PlayerbotAI;
|
|
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
|
|
{
|
|
public:
|
|
MovementAction(PlayerbotAI* botAI, std::string const name);
|
|
|
|
protected:
|
|
bool JumpTo(uint32 mapId, float x, float y, float z, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
|
bool MoveNear(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->contactDistance,
|
|
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
|
bool MoveToLOS(WorldObject* target, bool ranged = false);
|
|
bool MoveTo(uint32 mapId, float x, float y, float z, bool idle = false, bool react = false,
|
|
bool normal_only = false, bool exact_waypoint = false,
|
|
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL, bool lessDelay = false,
|
|
bool backwards = false);
|
|
bool MoveTo(WorldObject* target, float distance = 0.0f,
|
|
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
|
bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig->contactDistance,
|
|
MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
|
float GetFollowAngle();
|
|
bool Follow(Unit* target, float distance = sPlayerbotAIConfig->followDistance);
|
|
bool Follow(Unit* target, float distance, float angle);
|
|
bool ChaseTo(WorldObject* obj, float distance = 0.0f, float angle = 0.0f);
|
|
bool ReachCombatTo(Unit* target, float distance = 0.0f);
|
|
float MoveDelay(float distance, bool backwards = false);
|
|
void WaitForReach(float distance);
|
|
void SetNextMovementDelay(float delayMillis);
|
|
bool IsMovingAllowed(WorldObject* target);
|
|
bool IsMovingAllowed(uint32 mapId, float x, float y, float z);
|
|
bool IsDuplicateMove(uint32 mapId, float x, float y, float z);
|
|
bool IsWaitingForLastMove(MovementPriority priority);
|
|
bool IsMovingAllowed();
|
|
bool Flee(Unit* target);
|
|
void ClearIdleState();
|
|
void UpdateMovementState();
|
|
bool MoveAway(Unit* target, float distance = sPlayerbotAIConfig->fleeDistance, bool backwards = false);
|
|
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);
|
|
void CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important = false);
|
|
Position BestPositionForMeleeToFlee(Position pos, float radius);
|
|
Position BestPositionForRangedToFlee(Position pos, float radius);
|
|
bool FleePosition(Position pos, float radius, uint32 minInterval = 1000);
|
|
bool CheckLastFlee(float curAngle, std::list<FleeInfo>& infoList);
|
|
|
|
protected:
|
|
struct CheckAngle
|
|
{
|
|
float angle;
|
|
bool strict;
|
|
};
|
|
|
|
private:
|
|
// float SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range = 20.0f, bool
|
|
// normal_only = false, float step = 8.0f);
|
|
const Movement::PointsArray SearchForBestPath(float x, float y, float z, float& modified_z, int maxSearchCount = 5,
|
|
bool normal_only = false, float step = 8.0f);
|
|
bool wasMovementRestricted = false;
|
|
void DoMovePoint(Unit* unit, float x, float y, float z, bool generatePath, bool backwards);
|
|
};
|
|
|
|
class FleeAction : public MovementAction
|
|
{
|
|
public:
|
|
FleeAction(PlayerbotAI* botAI, float distance = sPlayerbotAIConfig->spellDistance)
|
|
: MovementAction(botAI, "flee"), distance(distance)
|
|
{
|
|
}
|
|
|
|
bool Execute(Event event) override;
|
|
bool isUseful() override;
|
|
|
|
private:
|
|
float distance;
|
|
};
|
|
|
|
class FleeWithPetAction : public MovementAction
|
|
{
|
|
public:
|
|
FleeWithPetAction(PlayerbotAI* botAI) : MovementAction(botAI, "flee with pet") {}
|
|
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class AvoidAoeAction : public MovementAction
|
|
{
|
|
public:
|
|
AvoidAoeAction(PlayerbotAI* botAI, int moveInterval = 1000)
|
|
: MovementAction(botAI, "avoid aoe"), moveInterval(moveInterval)
|
|
{
|
|
}
|
|
|
|
bool isUseful() override;
|
|
bool Execute(Event event) override;
|
|
|
|
protected:
|
|
bool AvoidAuraWithDynamicObj();
|
|
bool AvoidGameObjectWithDamage();
|
|
bool AvoidUnitWithDamageAura();
|
|
time_t lastTellTimer = 0;
|
|
int lastMoveTimer = 0;
|
|
int moveInterval;
|
|
};
|
|
|
|
class CombatFormationMoveAction : public MovementAction
|
|
{
|
|
public:
|
|
CombatFormationMoveAction(PlayerbotAI* botAI, std::string name = "combat formation move", int moveInterval = 1000)
|
|
: MovementAction(botAI, name), moveInterval(moveInterval)
|
|
{
|
|
}
|
|
|
|
bool isUseful() override;
|
|
bool Execute(Event event) override;
|
|
|
|
protected:
|
|
Position AverageGroupPos(float dis = sPlayerbotAIConfig->sightDistance, bool ranged = false, bool self = false);
|
|
Player* NearestGroupMember(float dis = sPlayerbotAIConfig->sightDistance);
|
|
float AverageGroupAngle(Unit* from, bool ranged = false, bool self = false);
|
|
Position GetNearestPosition(const std::vector<Position>& positions);
|
|
int lastMoveTimer = 0;
|
|
int moveInterval;
|
|
};
|
|
|
|
class TankFaceAction : public CombatFormationMoveAction
|
|
{
|
|
public:
|
|
TankFaceAction(PlayerbotAI* botAI) : CombatFormationMoveAction(botAI, "tank face") {}
|
|
|
|
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:
|
|
DisperseSetAction(PlayerbotAI* botAI, std::string const name = "disperse set") : Action(botAI, name) {}
|
|
|
|
bool Execute(Event event) override;
|
|
float DEFAULT_DISPERSE_DISTANCE_RANGED = 5.0f;
|
|
float DEFAULT_DISPERSE_DISTANCE_MELEE = 2.0f;
|
|
};
|
|
|
|
class RunAwayAction : public MovementAction
|
|
{
|
|
public:
|
|
RunAwayAction(PlayerbotAI* botAI) : MovementAction(botAI, "runaway") {}
|
|
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class MoveToLootAction : public MovementAction
|
|
{
|
|
public:
|
|
MoveToLootAction(PlayerbotAI* botAI) : MovementAction(botAI, "move to loot") {}
|
|
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class MoveOutOfEnemyContactAction : public MovementAction
|
|
{
|
|
public:
|
|
MoveOutOfEnemyContactAction(PlayerbotAI* botAI) : MovementAction(botAI, "move out of enemy contact") {}
|
|
|
|
bool Execute(Event event) override;
|
|
bool isUseful() override;
|
|
};
|
|
|
|
class SetFacingTargetAction : public Action
|
|
{
|
|
public:
|
|
SetFacingTargetAction(PlayerbotAI* botAI) : Action(botAI, "set facing") {}
|
|
|
|
bool Execute(Event event) override;
|
|
bool isUseful() override;
|
|
bool isPossible() override;
|
|
};
|
|
|
|
class SetBehindTargetAction : public CombatFormationMoveAction
|
|
{
|
|
public:
|
|
SetBehindTargetAction(PlayerbotAI* botAI) : CombatFormationMoveAction(botAI, "set behind") {}
|
|
|
|
bool Execute(Event event) override;
|
|
};
|
|
|
|
class MoveOutOfCollisionAction : public MovementAction
|
|
{
|
|
public:
|
|
MoveOutOfCollisionAction(PlayerbotAI* botAI) : MovementAction(botAI, "move out of collision") {}
|
|
|
|
bool Execute(Event event) override;
|
|
bool isUseful() override;
|
|
};
|
|
|
|
class MoveRandomAction : public MovementAction
|
|
{
|
|
public:
|
|
MoveRandomAction(PlayerbotAI* botAI) : MovementAction(botAI, "move random") {}
|
|
|
|
bool Execute(Event event) override;
|
|
bool isUseful() override;
|
|
};
|
|
|
|
class MoveInsideAction : public MovementAction
|
|
{
|
|
public:
|
|
MoveInsideAction(PlayerbotAI* ai, float x, float y, float distance = 5.0f) : MovementAction(ai, "move inside")
|
|
{
|
|
this->x = x;
|
|
this->y = y;
|
|
this->distance = distance;
|
|
}
|
|
virtual bool Execute(Event event);
|
|
|
|
protected:
|
|
float x, y, distance;
|
|
};
|
|
|
|
class RotateAroundTheCenterPointAction : public MovementAction
|
|
{
|
|
public:
|
|
RotateAroundTheCenterPointAction(PlayerbotAI* ai, std::string name, float center_x, float center_y,
|
|
float radius = 40.0f, uint32 intervals = 16, bool clockwise = true,
|
|
float start_angle = 0)
|
|
: MovementAction(ai, name)
|
|
{
|
|
this->center_x = center_x;
|
|
this->center_y = center_y;
|
|
this->radius = radius;
|
|
this->intervals = intervals;
|
|
this->clockwise = clockwise;
|
|
this->call_counters = 0;
|
|
for (int i = 0; i < intervals; i++)
|
|
{
|
|
float angle = start_angle + 2 * M_PI * i / intervals;
|
|
waypoints.push_back(std::make_pair(center_x + cos(angle) * radius, center_y + sin(angle) * radius));
|
|
}
|
|
}
|
|
virtual bool Execute(Event event);
|
|
|
|
protected:
|
|
virtual uint32 GetCurrWaypoint() { return 0; }
|
|
uint32 FindNearestWaypoint();
|
|
float center_x, center_y, radius;
|
|
uint32 intervals, call_counters;
|
|
bool clockwise;
|
|
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;
|
|
};
|
|
|
|
class MoveAwayFromCreatureAction : public MovementAction
|
|
{
|
|
public:
|
|
MoveAwayFromCreatureAction(PlayerbotAI* botAI, std::string name, uint32 creatureId, float range, bool alive = true)
|
|
: MovementAction(botAI, name), creatureId(creatureId), range(range), alive(alive)
|
|
{
|
|
}
|
|
|
|
bool Execute(Event event) override;
|
|
bool isPossible() override;
|
|
|
|
private:
|
|
uint32 creatureId;
|
|
float range;
|
|
bool alive;
|
|
};
|
|
|
|
class MoveAwayFromPlayerWithDebuffAction : public MovementAction
|
|
{
|
|
public:
|
|
MoveAwayFromPlayerWithDebuffAction(PlayerbotAI* botAI, std::string name, uint32 spellId, float range)
|
|
: MovementAction(botAI, name), spellId(spellId), range(range)
|
|
{
|
|
}
|
|
|
|
bool Execute(Event event) override;
|
|
bool isPossible() override;
|
|
|
|
private:
|
|
uint32 spellId;
|
|
float range;
|
|
bool alive;
|
|
};
|
|
|
|
#endif
|