Movement priority

This commit is contained in:
Yunfan Li
2024-08-14 18:23:24 +08:00
parent 765d0305ef
commit 7b0bb20078
12 changed files with 216 additions and 183 deletions

View File

@@ -61,23 +61,37 @@ void MovementAction::CreateWp(Player* wpOwner, float x, float y, float z, float
wpCreature->SetObjectScale(0.5f);
}
void MovementAction::JumpTo(uint32 mapId, float x, float y, float z)
bool MovementAction::JumpTo(uint32 mapId, float x, float y, float z, MovementPriority priority)
{
UpdateMovementState();
if (!IsMovingAllowed(mapId, x, y, z))
{
return false;
}
if (IsDuplicateMove(mapId, x, y, z))
{
return false;
}
if (IsWaitingForLastMove(priority))
{
return false;
}
float botZ = bot->GetPositionZ();
float speed = bot->GetSpeed(MOVE_RUN);
MotionMaster& mm = *bot->GetMotionMaster();
mm.Clear();
mm.MoveJump(x, y, z, speed, speed, 1);
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), 1000);
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), 1000, priority);
return true;
}
bool MovementAction::MoveNear(uint32 mapId, float x, float y, float z, float distance)
bool MovementAction::MoveNear(uint32 mapId, float x, float y, float z, float distance, MovementPriority priority)
{
float angle = GetFollowAngle();
return MoveTo(mapId, x + cos(angle) * distance, y + sin(angle) * distance, z);
return MoveTo(mapId, x + cos(angle) * distance, y + sin(angle) * distance, z, false, false, false, false, priority);
}
bool MovementAction::MoveNear(WorldObject* target, float distance)
bool MovementAction::MoveNear(WorldObject* target, float distance, MovementPriority priority)
{
if (!target)
return false;
@@ -99,7 +113,7 @@ bool MovementAction::MoveNear(WorldObject* target, float distance)
if (!bot->IsWithinLOS(x, y, z))
continue;
bool moved = MoveTo(target->GetMapId(), x, y, z);
bool moved = MoveTo(target->GetMapId(), x, y, z, false, false, false, false, priority);
if (moved)
return true;
}
@@ -161,7 +175,7 @@ bool MovementAction::MoveToLOS(WorldObject* target, bool ranged)
}
bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react, bool normal_only,
bool exact_waypoint)
bool exact_waypoint, MovementPriority priority)
{
UpdateMovementState();
if (!IsMovingAllowed(mapId, x, y, z))
@@ -172,21 +186,10 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
{
return false;
}
if (IsWaitingForLastMove())
if (IsWaitingForLastMove(priority))
{
return false;
}
// if (bot->Unit::IsFalling()) {
// bot->Say("I'm falling!, flag:" + std::to_string(bot->m_movementInfo.GetMovementFlags()), LANG_UNIVERSAL);
// return false;
// }
// if (bot->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_SWIMMING)) {
// bot->Say("I'm swimming", LANG_UNIVERSAL);
// }
// if (bot->Unit::IsFalling()) {
// bot->Say("I'm falling", LANG_UNIVERSAL);
// }
bool generatePath = !bot->IsFlying() && !bot->isSwimming();
bool disableMoveSplinePath = sPlayerbotAIConfig->disableMoveSplinePath >= 2 ||
(sPlayerbotAIConfig->disableMoveSplinePath == 1 && bot->InBattleground());
@@ -202,11 +205,11 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
{
MotionMaster& mm = *vehicleBase->GetMotionMaster(); // need to move vehicle, not bot
mm.Clear();
mm.MovePoint(mapId, x, y, z, generatePath);
float delay = 1000.0f * (distance / vehicleBase->GetSpeed(MOVE_RUN)) - sPlayerbotAIConfig->reactDelay;
mm.MovePoint(0, x, y, z, generatePath);
float delay = 1000.0f * (distance / vehicleBase->GetSpeed(MOVE_RUN));
delay = std::max(.0f, delay);
delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay);
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay);
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay, priority);
return true;
}
}
@@ -225,11 +228,11 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
}
MotionMaster& mm = *bot->GetMotionMaster();
mm.Clear();
mm.MovePoint(mapId, x, y, z, generatePath);
float delay = 1000.0f * MoveDelay(distance) - sPlayerbotAIConfig->reactDelay;
mm.MovePoint(0, x, y, z, generatePath);
float delay = 1000.0f * MoveDelay(distance);
delay = std::max(.0f, delay);
delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay);
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay);
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay, priority);
return true;
}
}
@@ -254,14 +257,13 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
botAI->InterruptSpell();
}
MotionMaster& mm = *bot->GetMotionMaster();
G3D::Vector3 endP = path.back();
mm.Clear();
mm.MoveSplinePath(&path);
// mm.MoveSplinePath(&path);
float delay = 1000.0f * MoveDelay(distance) - sPlayerbotAIConfig->reactDelay;
mm.MovePoint(0, endP.x, endP.y, endP.z, generatePath);
float delay = 1000.0f * MoveDelay(distance);
delay = std::max(.0f, delay);
delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay);
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay);
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay, priority);
return true;
}
}
@@ -759,7 +761,7 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
// return true;
}
bool MovementAction::MoveTo(Unit* target, float distance)
bool MovementAction::MoveTo(Unit* target, float distance, MovementPriority priority)
{
if (!IsMovingAllowed(target))
return false;
@@ -793,7 +795,7 @@ bool MovementAction::MoveTo(Unit* target, float distance)
{
dz = tz;
}
return MoveTo(target->GetMapId(), dx, dy, dz);
return MoveTo(target->GetMapId(), dx, dy, dz, false, false, false, false, priority);
}
bool MovementAction::ReachCombatTo(Unit* target, float distance)
@@ -813,6 +815,7 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance)
if (target->HasUnitMovementFlag(MOVEMENTFLAG_FORWARD)) // target is moving forward, predict the position
{
float needToGo = bot->GetExactDist(target) - distance;
float timeToGo = MoveDelay(abs(needToGo)) + sPlayerbotAIConfig->reactDelay / 1000.0f;
float targetMoveDist = timeToGo * target->GetSpeed(MOVE_RUN);
@@ -845,7 +848,7 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance)
return false;
path.ShortenPathUntilDist(G3D::Vector3(tx, ty, tz), distance);
G3D::Vector3 endPos = path.GetPath().back();
return MoveTo(target->GetMapId(), endPos.x, endPos.y, endPos.z);
return MoveTo(target->GetMapId(), endPos.x, endPos.y, endPos.z, false, false, false, false, MovementPriority::MOVEMENT_COMBAT);
}
float MovementAction::GetFollowAngle()
@@ -909,10 +912,13 @@ bool MovementAction::IsDuplicateMove(uint32 mapId, float x, float y, float z)
return true;
}
bool MovementAction::IsWaitingForLastMove()
bool MovementAction::IsWaitingForLastMove(MovementPriority priority)
{
LastMovement& lastMove = *context->GetValue<LastMovement&>("last movement");
if (priority > lastMove.priority)
return false;
// heuristic 5s
if (lastMove.lastdelayTime + lastMove.msTime > getMSTime())
return true;
@@ -1216,7 +1222,7 @@ bool MovementAction::Follow(Unit* target, float distance, float angle)
botAI->InterruptSpell();
}
AI_VALUE(LastMovement&, "last movement").Set(target);
// AI_VALUE(LastMovement&, "last movement").Set(target);
ClearIdleState();
if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE)
@@ -1506,7 +1512,17 @@ bool MovementAction::MoveAway(Unit* target)
float dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
float dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
float dz = bot->GetPositionZ();
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true))
bool exact = true;
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
bot->GetPositionZ(), dx, dy, dz))
{
// disable prediction if position is invalid
dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
dz = bot->GetPositionZ();
exact = false;
}
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true, exact, MovementPriority::MOVEMENT_COMBAT))
{
return true;
}
@@ -1514,11 +1530,21 @@ bool MovementAction::MoveAway(Unit* target)
{
continue;
}
exact = true;
angle = init_angle - delta;
dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
dz = bot->GetPositionZ();
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true))
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
bot->GetPositionZ(), dx, dy, dz))
{
// disable prediction if position is invalid
dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance;
dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance;
dz = bot->GetPositionZ();
exact = false;
}
if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true, exact, MovementPriority::MOVEMENT_COMBAT))
{
return true;
}
@@ -1526,13 +1552,13 @@ bool MovementAction::MoveAway(Unit* target)
return false;
}
bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float distance)
bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float distance, MovementPriority priority)
{
if (bot->GetDistance2d(x, y) <= distance)
{
return false;
}
return MoveNear(mapId, x, y, z, distance);
return MoveNear(mapId, x, y, z, distance, priority);
}
// float MovementAction::SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range, bool
@@ -1678,13 +1704,7 @@ bool FleeWithPetAction::Execute(Event event)
{
if (Pet* pet = bot->GetPet())
{
if (CreatureAI* creatureAI = ((Creature*)pet)->AI())
{
pet->SetReactState(REACT_PASSIVE);
pet->GetCharmInfo()->SetIsCommandFollow(true);
pet->GetCharmInfo()->IsReturning();
pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle());
}
botAI->PetFollow();
}
return Flee(AI_VALUE(Unit*, "current target"));
@@ -1929,7 +1949,7 @@ Position MovementAction::BestPositionForMeleeToFlee(Position pos, float radius)
for (CheckAngle& checkAngle : possibleAngles)
{
float angle = checkAngle.angle;
auto& infoList = AI_VALUE_REF(std::list<FleeInfo>, "recently flee info");
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
if (!CheckLastFlee(angle, infoList))
{
continue;
@@ -1985,7 +2005,7 @@ Position MovementAction::BestPositionForRangedToFlee(Position pos, float radius)
for (CheckAngle& checkAngle : possibleAngles)
{
float angle = checkAngle.angle;
auto& infoList = AI_VALUE_REF(std::list<FleeInfo>, "recently flee info");
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
if (!CheckLastFlee(angle, infoList))
{
continue;
@@ -2032,9 +2052,9 @@ bool MovementAction::FleePosition(Position pos, float radius)
if (bestPos != Position())
{
if (MoveTo(bot->GetMapId(), bestPos.GetPositionX(), bestPos.GetPositionY(), bestPos.GetPositionZ(), false,
false, true))
false, true, false, MovementPriority::MOVEMENT_COMBAT))
{
auto& infoList = AI_VALUE_REF(std::list<FleeInfo>, "recently flee info");
std::list<FleeInfo>& infoList = AI_VALUE(std::list<FleeInfo>&, "recently flee info");
uint32 curTS = getMSTime();
while (!infoList.empty())
{
@@ -2346,10 +2366,10 @@ bool MoveOutOfCollisionAction::isUseful()
bool MoveRandomAction::Execute(Event event)
{
float distance = sPlayerbotAIConfig->tooCloseDistance + sPlayerbotAIConfig->grindDistance * urand(3, 10) / 10.0f;
float distance = sPlayerbotAIConfig->tooCloseDistance + urand(10, 30);
Map* map = bot->GetMap();
for (int i = 0; i < 10; ++i)
for (int i = 0; i < 3; ++i)
{
float x = bot->GetPositionX();
float y = bot->GetPositionY();
@@ -2362,11 +2382,7 @@ bool MoveRandomAction::Execute(Event event)
float oz = z;
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
bot->GetPositionZ(), x, y, z))
{
x = ox;
y = oy;
z = oz;
}
continue;
if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight()))
continue;
@@ -2385,7 +2401,7 @@ bool MoveInsideAction::Execute(Event event) { return MoveInside(bot->GetMapId(),
bool RotateAroundTheCenterPointAction::Execute(Event event)
{
uint32 next_point = GetCurrWaypoint();
if (MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ()))
if (MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT))
{
call_counters += 1;
return true;