From 7b0bb20078c5411a61f7342d18d0a7dd9553b863 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 14 Aug 2024 18:23:24 +0800 Subject: [PATCH] Movement priority --- src/strategy/Value.h | 9 +- src/strategy/actions/AttackAction.cpp | 23 ++- src/strategy/actions/ChatShortcutActions.cpp | 6 +- .../actions/CheckMountStateAction.cpp | 79 +++++------ src/strategy/actions/FollowActions.cpp | 20 +-- .../actions/MoveToRpgTargetAction.cpp | 4 +- src/strategy/actions/MovementActions.cpp | 132 ++++++++++-------- src/strategy/actions/MovementActions.h | 18 +-- .../actions/UseMeetingStoneAction.cpp | 4 +- .../raids/naxxramas/RaidNaxxActions.cpp | 85 +++++------ src/strategy/values/LastMovementValue.cpp | 5 +- src/strategy/values/LastMovementValue.h | 14 +- 12 files changed, 216 insertions(+), 183 deletions(-) diff --git a/src/strategy/Value.h b/src/strategy/Value.h index 2ea60de7..a4189f78 100644 --- a/src/strategy/Value.h +++ b/src/strategy/Value.h @@ -405,14 +405,15 @@ public: } }; -class RecentlyFleeInfo : public ManualSetValue> +class RecentlyFleeInfo : public ManualSetValue&> { public: - RecentlyFleeInfo(PlayerbotAI* botAI, std::list defaultValue = {}, - std::string const name = "recently flee info") - : ManualSetValue>(botAI, defaultValue, name) + RecentlyFleeInfo(PlayerbotAI* botAI, std::string const name = "recently flee info") + : ManualSetValue&>(botAI, data, name) { } +private: + std::list data = {}; }; #endif diff --git a/src/strategy/actions/AttackAction.cpp b/src/strategy/actions/AttackAction.cpp index 1dc98984..d1dd232b 100644 --- a/src/strategy/actions/AttackAction.cpp +++ b/src/strategy/actions/AttackAction.cpp @@ -7,9 +7,12 @@ #include "CreatureAI.h" #include "Event.h" +#include "LastMovementValue.h" #include "LootObjectStack.h" +#include "PlayerbotAI.h" #include "Playerbots.h" #include "ServerFacade.h" +#include "SharedDefines.h" #include "Unit.h" bool AttackAction::Execute(Event event) @@ -109,24 +112,32 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/) bot->SetSelection(target->GetGUID()); Unit* oldTarget = context->GetValue("current target")->Get(); + + if (oldTarget == target && botAI->GetState() == BOT_STATE_COMBAT && bot->GetVictim() == target) + return false; + context->GetValue("old target")->Set(oldTarget); context->GetValue("current target")->Set(target); context->GetValue("available loot")->Get()->Add(guid); + LastMovement& lastMovement = AI_VALUE(LastMovement&, "last movement"); + if (lastMovement.priority < MovementPriority::MOVEMENT_COMBAT && bot->isMoving()) + { + AI_VALUE(LastMovement&, "last movement").clear(); + bot->GetMotionMaster()->Clear(false); + bot->StopMoving(); + } + bool melee = bot->IsWithinMeleeRange(target) || botAI->IsMelee(bot); - bot->Attack(target, melee); if (IsMovingAllowed() && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target)) { sServerFacade->SetFacingTo(bot, target); } botAI->ChangeEngine(BOT_STATE_COMBAT); - - if (!bot->GetVictim()) - { - return false; - } + + bot->Attack(target, melee); /* prevent pet dead immediately in group */ // if (bot->GetMap()->IsDungeon() && bot->GetGroup() && !target->IsInCombat()) { // with_pet = false; diff --git a/src/strategy/actions/ChatShortcutActions.cpp b/src/strategy/actions/ChatShortcutActions.cpp index 85304a87..00a89483 100644 --- a/src/strategy/actions/ChatShortcutActions.cpp +++ b/src/strategy/actions/ChatShortcutActions.cpp @@ -32,7 +32,7 @@ bool FollowChatShortcutAction::Execute(Event event) if (!master) return false; - botAI->Reset(); + // botAI->Reset(); botAI->ChangeStrategy("+follow,-passive,-grind", BOT_STATE_NON_COMBAT); botAI->ChangeStrategy("-follow,-passive,-grind", BOT_STATE_COMBAT); botAI->GetAiObjectContext()->GetValue("prioritized targets")->Set({}); @@ -57,7 +57,9 @@ bool FollowChatShortcutAction::Execute(Event event) if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1) return false; - moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ()); + MovementPriority priority = botAI->GetState() == BOT_STATE_COMBAT ? MovementPriority::MOVEMENT_COMBAT : MovementPriority::MOVEMENT_NORMAL; + moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), false, false, false, + true, priority); } if (moved) diff --git a/src/strategy/actions/CheckMountStateAction.cpp b/src/strategy/actions/CheckMountStateAction.cpp index 6a51fd92..d85f51b5 100644 --- a/src/strategy/actions/CheckMountStateAction.cpp +++ b/src/strategy/actions/CheckMountStateAction.cpp @@ -8,6 +8,7 @@ #include "BattlegroundWS.h" #include "Event.h" #include "PlayerbotAI.h" +#include "PlayerbotAIConfig.h" #include "Playerbots.h" #include "ServerFacade.h" #include "SpellAuraEffects.h" @@ -17,35 +18,46 @@ bool CheckMountStateAction::Execute(Event event) bool noattackers = AI_VALUE2(bool, "combat", "self target") ? (AI_VALUE(uint8, "attacker count") > 0 ? false : true) : true; bool enemy = AI_VALUE(Unit*, "enemy player target"); - // ignore grind target in BG or bots will dismount near any creature (eg: the rams in AV) bool dps = AI_VALUE(Unit*, "dps target"); - // bool fartarget = (enemy && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "enemy player - // target"), 40.0f)) || - // (dps && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "dps target"), 50.0f)); - bool attackdistance = false; + bool shouldDismount = false; + bool shouldMount = false; // bool chasedistance = false; - float attack_distance = 35.0f; + float attack_distance; + float mount_distance; if (PlayerbotAI::IsMelee(bot)) { - attack_distance = 5.0f; + attack_distance = sPlayerbotAIConfig->meleeDistance + 2.0f; + mount_distance = sPlayerbotAIConfig->meleeDistance + 10.0f; } else { - attack_distance = 30.0f; + attack_distance = sPlayerbotAIConfig->spellDistance + 2.0f; + mount_distance = sPlayerbotAIConfig->spellDistance + 10.0f; } - // if (enemy) - // attack_distance /= 2; + Unit* currentTarget = AI_VALUE(Unit*, "current target"); - if (dps || enemy) + if (currentTarget) { - Unit* currentTarget = AI_VALUE(Unit*, "current target"); - attackdistance = - (enemy || dps) && currentTarget && - sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "current target"), attack_distance); + float combatReach = bot->GetCombatReach() + currentTarget->GetCombatReach(); + attack_distance += combatReach; + float disToTarget = bot->GetExactDist(currentTarget); + shouldDismount = disToTarget <= attack_distance; } + else + shouldDismount = false; - if (bot->IsMounted() && attackdistance) + if (currentTarget) + { + float combatReach = bot->GetCombatReach() + currentTarget->GetCombatReach(); + mount_distance += combatReach; + float disToTarget = bot->GetExactDist(currentTarget); + shouldMount = disToTarget > mount_distance; + } + else + shouldMount = true; + + if (bot->IsMounted() && shouldDismount) { WorldPacket emptyPacket; bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket); @@ -59,7 +71,7 @@ bool CheckMountStateAction::Execute(Event event) return false; // bool farFromMaster = sServerFacade->GetDistance2d(bot, master) > sPlayerbotAIConfig->sightDistance; - if (master->IsMounted() && !bot->IsMounted() && noattackers && !attackdistance && !bot->IsInCombat() && + if (master->IsMounted() && !bot->IsMounted() && noattackers && shouldMount && !bot->IsInCombat() && botAI->GetState() != BOT_STATE_COMBAT) { return Mount(); @@ -71,16 +83,6 @@ bool CheckMountStateAction::Execute(Event event) bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket); return true; } - // if (!bot->IsMounted() && (chasedistance || (farFromMaster && botAI->HasStrategy("follow", - // BOT_STATE_NON_COMBAT))) && !bot->IsInCombat() && !dps) - // return Mount(); - - // if (!bot->IsFlying() && ((!farFromMaster && !master->IsMounted()) || attackdistance) && bot->IsMounted()) - // { - // WorldPacket emptyPacket; - // bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket); - // return true; - // } return false; } @@ -88,13 +90,13 @@ bool CheckMountStateAction::Execute(Event event) // For random bots if (!bot->InBattleground() && !master) { - if (!bot->IsMounted() && noattackers && !attackdistance && !bot->IsInCombat()) + if (!bot->IsMounted() && noattackers && shouldMount && !bot->IsInCombat()) { return Mount(); } } - if (bot->InBattleground() && !attackdistance && noattackers && !bot->IsInCombat() && !bot->IsMounted()) + if (bot->InBattleground() && shouldMount && noattackers && !bot->IsInCombat() && !bot->IsMounted()) { if (bot->GetBattlegroundTypeId() == BATTLEGROUND_WS) { @@ -108,24 +110,7 @@ bool CheckMountStateAction::Execute(Event event) return Mount(); } - // if (!bot->InBattleground()) - // { - // if (AI_VALUE(GuidPosition, "rpg target")) - // { - // if (sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "rpg target"), - // sPlayerbotAIConfig->farDistance) && noattackers && !dps && !enemy) - // return Mount(); - // } - - // if (((!AI_VALUE(GuidVector, "possible rpg targets").empty()) && noattackers && !dps && !enemy) && urand(0, - // 100) > 50) - // return Mount(); - // } - - // if (!bot->IsMounted() && !attackdistance && (fartarget || chasedistance)) - // return Mount(); - - if (!bot->IsFlying() && attackdistance && bot->IsMounted() && (enemy || dps || (!noattackers && bot->IsInCombat()))) + if (!bot->IsFlying() && shouldDismount && bot->IsMounted() && (enemy || dps || (!noattackers && bot->IsInCombat()))) { WorldPacket emptyPacket; bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket); diff --git a/src/strategy/actions/FollowActions.cpp b/src/strategy/actions/FollowActions.cpp index 81be99a6..10d15933 100644 --- a/src/strategy/actions/FollowActions.cpp +++ b/src/strategy/actions/FollowActions.cpp @@ -9,6 +9,8 @@ #include "Event.h" #include "Formations.h" +#include "LastMovementValue.h" +#include "PlayerbotAI.h" #include "Playerbots.h" #include "ServerFacade.h" #include "SharedDefines.h" @@ -28,25 +30,15 @@ bool FollowAction::Execute(Event event) WorldLocation loc = formation->GetLocation(); if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1) return false; - + + MovementPriority priority = botAI->GetState() == BOT_STATE_COMBAT ? MovementPriority::MOVEMENT_COMBAT : MovementPriority::MOVEMENT_NORMAL; moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), false, false, false, - true); + true, priority); } 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()); - // pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); - // pet->GetCharmInfo()->SetIsFollowing(true); - // pet->AttackStop(); - // pet->GetCharmInfo()->IsReturning(); - // pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle()); - } + botAI->PetFollow(); } // if (moved) // botAI->SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); diff --git a/src/strategy/actions/MoveToRpgTargetAction.cpp b/src/strategy/actions/MoveToRpgTargetAction.cpp index 9640fc5c..4facc600 100644 --- a/src/strategy/actions/MoveToRpgTargetAction.cpp +++ b/src/strategy/actions/MoveToRpgTargetAction.cpp @@ -94,12 +94,14 @@ bool MoveToRpgTargetAction::Execute(Event event) x += cos(angle) * INTERACTION_DISTANCE * distance; y += sin(angle) * INTERACTION_DISTANCE * distance; + bool exact = true; if (!wo->GetMap()->CheckCollisionAndGetValidCoords(wo, wo->GetPositionX(), wo->GetPositionY(), wo->GetPositionZ(), x, y, z)) { x = wo->GetPositionX(); y = wo->GetPositionY(); z = wo->GetPositionZ(); + exact = false; } // WaitForReach(distance); @@ -108,7 +110,7 @@ bool MoveToRpgTargetAction::Execute(Event event) // if (bot->IsWithinLOS(x, y, z)) // couldMove = MoveNear(mapId, x, y, z, 0); // else - couldMove = MoveTo(mapId, x, y, z, false, false, false, true); + couldMove = MoveTo(mapId, x, y, z, false, false, false, exact); if (!couldMove && WorldPosition(mapId, x, y, z).distance(bot) > INTERACTION_DISTANCE) { diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index ea460bc1..641b9cfc 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -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("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, "recently flee info"); + std::list& infoList = AI_VALUE(std::list&, "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, "recently flee info"); + std::list& infoList = AI_VALUE(std::list&, "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, "recently flee info"); + std::list& infoList = AI_VALUE(std::list&, "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; diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index 2b8a82fe..5b0f3c7a 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -9,6 +9,7 @@ #include #include "Action.h" +#include "LastMovementValue.h" #include "PlayerbotAIConfig.h" class Player; @@ -17,19 +18,20 @@ class Unit; class WorldObject; class Position; + class MovementAction : public Action { public: MovementAction(PlayerbotAI* botAI, std::string const name); protected: - void JumpTo(uint32 mapId, float x, float y, float z); - bool MoveNear(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->contactDistance); + 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); - bool MoveTo(Unit* target, float distance = 0.0f); - bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig->contactDistance); + bool normal_only = false, bool exact_waypoint = false, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL); + bool MoveTo(Unit* 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); @@ -40,13 +42,13 @@ protected: bool IsMovingAllowed(Unit* target); bool IsMovingAllowed(uint32 mapId, float x, float y, float z); bool IsDuplicateMove(uint32 mapId, float x, float y, float z); - bool IsWaitingForLastMove(); + bool IsWaitingForLastMove(MovementPriority priority); bool IsMovingAllowed(); bool Flee(Unit* target); void ClearIdleState(); void UpdateMovementState(); bool MoveAway(Unit* target); - bool MoveInside(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->followDistance); + 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); @@ -94,7 +96,7 @@ class AvoidAoeAction : public MovementAction { public: AvoidAoeAction(PlayerbotAI* botAI, int moveInterval = 1000) - : MovementAction(botAI, "avoid aoe"), moveInterval(moveInterval) + : MovementAction(botAI, "aaoe"), moveInterval(moveInterval) { } diff --git a/src/strategy/actions/UseMeetingStoneAction.cpp b/src/strategy/actions/UseMeetingStoneAction.cpp index f3eb79fe..ad09b486 100644 --- a/src/strategy/actions/UseMeetingStoneAction.cpp +++ b/src/strategy/actions/UseMeetingStoneAction.cpp @@ -87,7 +87,7 @@ bool SummonAction::Execute(Event event) if (master->GetSession()->GetSecurity() >= SEC_PLAYER) { // botAI->GetAiObjectContext()->GetValue("prioritized targets")->Set({}); - SET_AI_VALUE(std::list, "recently flee info", {}); + AI_VALUE(std::list&, "recently flee info").clear(); return Teleport(master, bot); } @@ -215,10 +215,12 @@ bool SummonAction::Teleport(Player* summoner, Player* player) bool revive = sPlayerbotAIConfig->reviveBotWhenSummoned == 2 || (sPlayerbotAIConfig->reviveBotWhenSummoned == 1 && !master->IsInCombat() && master->IsAlive()); + if (bot->isDead() && revive) { bot->ResurrectPlayer(1.0f, false); botAI->TellMasterNoFacing("I live, again!"); + botAI->GetAiObjectContext()->GetValue("prioritized targets")->Set({}); } player->GetMotionMaster()->Clear(); diff --git a/src/strategy/raids/naxxramas/RaidNaxxActions.cpp b/src/strategy/raids/naxxramas/RaidNaxxActions.cpp index 5d75e31a..a1019d9b 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxActions.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxActions.cpp @@ -1,6 +1,7 @@ #include "RaidNaxxActions.h" +#include "LastMovementValue.h" #include "ObjectGuid.h" #include "PlayerbotAIConfig.h" #include "Playerbots.h" @@ -23,7 +24,7 @@ bool GrobbulusGoBehindAction::Execute(Event event) float z = boss->GetPositionZ(); float rx = x + cos(orientation) * distance; float ry = y + sin(orientation) * distance; - return MoveTo(bot->GetMapId(), rx, ry, z); + return MoveTo(bot->GetMapId(), rx, ry, z, false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } uint32 RotateAroundTheCenterPointAction::FindNearestWaypoint() @@ -91,7 +92,7 @@ bool HeiganDanceMeleeAction::Execute(Event event) } assert(curr_safe >= 0 && curr_safe <= 3); return MoveInside(bot->GetMapId(), waypoints[curr_safe].first, waypoints[curr_safe].second, bot->GetPositionZ(), - botAI->IsMainTank(bot) ? 0 : 0); + botAI->IsMainTank(bot) ? 0 : 0, MovementPriority::MOVEMENT_COMBAT); } bool HeiganDanceRangedAction::Execute(Event event) @@ -99,10 +100,10 @@ bool HeiganDanceRangedAction::Execute(Event event) CalculateSafe(); if (prev_phase != 1) { - return MoveTo(bot->GetMapId(), platform.first, platform.second, 276.54f); + return MoveTo(bot->GetMapId(), platform.first, platform.second, 276.54f, false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } botAI->InterruptSpell(); - return MoveInside(bot->GetMapId(), waypoints[curr_safe].first, waypoints[curr_safe].second, bot->GetPositionZ(), 0); + return MoveInside(bot->GetMapId(), waypoints[curr_safe].first, waypoints[curr_safe].second, bot->GetPositionZ(), 0, MovementPriority::MOVEMENT_COMBAT); } bool ThaddiusAttackNearestPetAction::isUseful() @@ -128,7 +129,7 @@ bool ThaddiusAttackNearestPetAction::Execute(Event event) Unit* target = helper.GetNearestPet(); if (!bot->IsWithinLOSInMap(target)) { - return MoveTo(target); + return MoveTo(target, 0, MovementPriority::MOVEMENT_COMBAT); } if (AI_VALUE(Unit*, "current target") != target) { @@ -137,12 +138,12 @@ bool ThaddiusAttackNearestPetAction::Execute(Event event) if (botAI->IsTank(bot) && AI_VALUE2(bool, "has aggro", "current target")) { std::pair posForTank = helper.PetPhaseGetPosForTank(); - return MoveTo(533, posForTank.first, posForTank.second, helper.tankPosZ); + return MoveTo(533, posForTank.first, posForTank.second, helper.tankPosZ, false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } if (botAI->IsRanged(bot)) { std::pair posForRanged = helper.PetPhaseGetPosForRanged(); - return MoveTo(533, posForRanged.first, posForRanged.second, helper.tankPosZ); + return MoveTo(533, posForRanged.first, posForRanged.second, helper.tankPosZ, false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } return false; } @@ -170,22 +171,28 @@ bool ThaddiusMoveToPlatformAction::Execute(Event event) { if (is_left) { - if (!MoveTo(bot->GetMapId(), position[0].first, position[0].second, high_z)) + if (!MoveTo(bot->GetMapId(), position[0].first, position[0].second, high_z, false, false, false, false, MovementPriority::MOVEMENT_COMBAT)) { - bot->TeleportTo(bot->GetMapId(), position[2].first, position[2].second, low_z, bot->GetOrientation()); + float distance = bot->GetExactDist2d(position[0].first, position[0].second); + if (distance < sPlayerbotAIConfig->contactDistance) + JumpTo(bot->GetMapId(), position[2].first, position[2].second, low_z, MovementPriority::MOVEMENT_COMBAT); + // bot->TeleportTo(bot->GetMapId(), position[2].first, position[2].second, low_z, bot->GetOrientation()); } } else { - if (!MoveTo(bot->GetMapId(), position[1].first, position[1].second, high_z)) + if (!MoveTo(bot->GetMapId(), position[1].first, position[1].second, high_z, false, false, false, false, MovementPriority::MOVEMENT_COMBAT)) { - bot->TeleportTo(bot->GetMapId(), position[3].first, position[3].second, low_z, bot->GetOrientation()); + float distance = bot->GetExactDist2d(position[1].first, position[1].second); + if (distance < sPlayerbotAIConfig->contactDistance) + JumpTo(bot->GetMapId(), position[3].first, position[3].second, low_z, MovementPriority::MOVEMENT_COMBAT); + // bot->TeleportTo(bot->GetMapId(), position[3].first, position[3].second, low_z, bot->GetOrientation()); } } } else { - return MoveTo(bot->GetMapId(), position[4].first, position[4].second, low_z); + return MoveTo(bot->GetMapId(), position[4].first, position[4].second, low_z, false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } return true; } @@ -225,7 +232,7 @@ bool ThaddiusMovePolarityAction::Execute(Event event) idx = 2; } idx = idx * 2 + botAI->IsRanged(bot); - return MoveTo(bot->GetMapId(), position[idx].first, position[idx].second, bot->GetPositionZ()); + return MoveTo(bot->GetMapId(), position[idx].first, position[idx].second, bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } bool RazuviousUseObedienceCrystalAction::Execute(Event event) @@ -322,7 +329,7 @@ bool RazuviousUseObedienceCrystalAction::Execute(Event event) { continue; } - if (MoveTo(unit)) + if (MoveTo(unit, 0.0f, MovementPriority::MOVEMENT_COMBAT)) { return true; } @@ -352,7 +359,7 @@ bool RazuviousUseObedienceCrystalAction::Execute(Event event) { if (bot->GetDistance2d(target) > sPlayerbotAIConfig->spellDistance) { - return MoveNear(target, sPlayerbotAIConfig->spellDistance); + return MoveNear(target, sPlayerbotAIConfig->spellDistance, MovementPriority::MOVEMENT_COMBAT); } else { @@ -396,7 +403,7 @@ bool HorsemanAttractAlternativelyAction::Execute(Event event) } helper.CalculatePosToGo(bot); auto [posX, posY] = helper.CurrentAttractPos(); - if (MoveTo(bot->GetMapId(), posX, posY, helper.posZ)) + if (MoveTo(bot->GetMapId(), posX, posY, helper.posZ, false, false, false, false, MovementPriority::MOVEMENT_COMBAT)) { return true; } @@ -444,7 +451,7 @@ bool HorsemanAttactInOrderAction::Execute(Event event) } if (!bot->IsWithinLOSInMap(target)) { - return MoveNear(target, 22.0f); + return MoveNear(target, 22.0f, MovementPriority::MOVEMENT_COMBAT); } return Attack(target); } @@ -461,7 +468,7 @@ bool SapphironGroundPositionAction::Execute(Event event) { if (AI_VALUE2(bool, "has aggro", "current target")) { - return MoveTo(NAXX_MAP_ID, helper.mainTankPos.first, helper.mainTankPos.second, helper.GENERIC_HEIGHT); + return MoveTo(NAXX_MAP_ID, helper.mainTankPos.first, helper.mainTankPos.second, helper.GENERIC_HEIGHT, false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } return false; } @@ -485,14 +492,14 @@ bool SapphironGroundPositionAction::Execute(Event event) distance = 5.0f; } return MoveTo(NAXX_MAP_ID, helper.center.first + cos(angle) * distance, - helper.center.second + sin(angle) * distance, helper.GENERIC_HEIGHT); + helper.center.second + sin(angle) * distance, helper.GENERIC_HEIGHT, false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } else { std::vector dest; if (helper.FindPosToAvoidChill(dest)) { - return MoveTo(NAXX_MAP_ID, dest[0], dest[1], dest[2]); + return MoveTo(NAXX_MAP_ID, dest[0], dest[1], dest[2], false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } } return false; @@ -513,7 +520,7 @@ bool SapphironFlightPositionAction::Execute(Event event) std::vector dest; if (helper.FindPosToAvoidChill(dest)) { - return MoveTo(NAXX_MAP_ID, dest[0], dest[1], dest[2]); + return MoveTo(NAXX_MAP_ID, dest[0], dest[1], dest[2], false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } } return false; @@ -548,7 +555,7 @@ bool SapphironFlightPositionAction::MoveToNearestIcebolt() { float angle = boss->GetAngle(playerWithIcebolt); return MoveTo(NAXX_MAP_ID, playerWithIcebolt->GetPositionX() + cos(angle) * 3.0f, - playerWithIcebolt->GetPositionY() + sin(angle) * 3.0f, helper.GENERIC_HEIGHT); + playerWithIcebolt->GetPositionY() + sin(angle) * 3.0f, helper.GENERIC_HEIGHT, false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } } return false; @@ -679,7 +686,7 @@ bool KelthuzadPositionAction::Execute(Event event) { if (AI_VALUE(Unit*, "current target") == nullptr) { - return MoveInside(NAXX_MAP_ID, helper.center.first, helper.center.second, bot->GetPositionZ(), 3.0f); + return MoveInside(NAXX_MAP_ID, helper.center.first, helper.center.second, bot->GetPositionZ(), 3.0f, MovementPriority::MOVEMENT_COMBAT); } } else if (helper.IsPhaseTwo()) @@ -692,7 +699,7 @@ bool KelthuzadPositionAction::Execute(Event event) { if (AI_VALUE2(bool, "has aggro", "current target")) { - return MoveTo(NAXX_MAP_ID, helper.tank_pos.first, helper.tank_pos.second, bot->GetPositionZ()); + return MoveTo(NAXX_MAP_ID, helper.tank_pos.first, helper.tank_pos.second, bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } else { @@ -715,7 +722,7 @@ bool KelthuzadPositionAction::Execute(Event event) float dx, dy; dx = helper.center.first + cos(angle) * distance; dy = helper.center.second + sin(angle) * distance; - return MoveTo(NAXX_MAP_ID, dx, dy, bot->GetPositionZ()); + return MoveTo(NAXX_MAP_ID, dx, dy, bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } else if (botAI->IsTank(bot)) { @@ -725,7 +732,7 @@ bool KelthuzadPositionAction::Execute(Event event) botAI->IsAssistTank(cur_tar->GetVictim()->ToPlayer())) { return MoveTo(NAXX_MAP_ID, helper.assist_tank_pos.first, helper.assist_tank_pos.second, - bot->GetPositionZ()); + bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } else { @@ -747,7 +754,7 @@ bool KelthuzadPositionAction::Execute(Event event) } dx = shadow_fissure->GetPositionX() + cos(angle) * 10.0f; dy = shadow_fissure->GetPositionY() + sin(angle) * 10.0f; - return MoveTo(NAXX_MAP_ID, dx, dy, bot->GetPositionZ()); + return MoveTo(NAXX_MAP_ID, dx, dy, bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } } return false; @@ -846,11 +853,11 @@ bool AnubrekhanPositionAction::Execute(Event event) next_point = nearest; } return MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, - bot->GetPositionZ()); + bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } else { - return MoveInside(533, 3272.49f, -3476.27f, bot->GetPositionZ(), 3.0f); + return MoveInside(533, 3272.49f, -3476.27f, bot->GetPositionZ(), 3.0f, MovementPriority::MOVEMENT_COMBAT); } } return false; @@ -964,12 +971,12 @@ bool GluthPositionAction::Execute(Event event) if (raid25) { return MoveTo(NAXX_MAP_ID, helper.mainTankPos25.first, helper.mainTankPos25.second, - bot->GetPositionZ()); + bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } else { return MoveTo(NAXX_MAP_ID, helper.mainTankPos10.first, helper.mainTankPos10.second, - bot->GetPositionZ()); + bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } } } @@ -978,7 +985,7 @@ bool GluthPositionAction::Execute(Event event) if (helper.BeforeDecimate()) { return MoveTo(bot->GetMapId(), helper.beforeDecimatePos.first, helper.beforeDecimatePos.second, - bot->GetPositionZ()); + bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } else { @@ -987,7 +994,7 @@ bool GluthPositionAction::Execute(Event event) uint32 nearest = FindNearestWaypoint(); uint32 next_point = (nearest + 1) % intervals; return MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, - bot->GetPositionZ()); + bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } } } @@ -998,19 +1005,19 @@ bool GluthPositionAction::Execute(Event event) if (botAI->GetClassIndex(bot, CLASS_HUNTER) == 0) { return MoveInside(NAXX_MAP_ID, helper.leftSlowDownPos.first, helper.leftSlowDownPos.second, - bot->GetPositionZ(), 0.0f); + bot->GetPositionZ(), 0.0f, MovementPriority::MOVEMENT_COMBAT); } if (botAI->GetClassIndex(bot, CLASS_HUNTER) == 1) { return MoveInside(NAXX_MAP_ID, helper.rightSlowDownPos.first, helper.rightSlowDownPos.second, - bot->GetPositionZ(), 0.0f); + bot->GetPositionZ(), 0.0f, MovementPriority::MOVEMENT_COMBAT); } } - return MoveInside(NAXX_MAP_ID, helper.rangedPos.first, helper.rangedPos.second, bot->GetPositionZ(), 3.0f); + return MoveInside(NAXX_MAP_ID, helper.rangedPos.first, helper.rangedPos.second, bot->GetPositionZ(), 3.0f, MovementPriority::MOVEMENT_COMBAT); } else if (botAI->IsHeal(bot)) { - return MoveInside(NAXX_MAP_ID, helper.healPos.first, helper.healPos.second, bot->GetPositionZ(), 0.0f); + return MoveInside(NAXX_MAP_ID, helper.healPos.first, helper.healPos.second, bot->GetPositionZ(), 0.0f, MovementPriority::MOVEMENT_COMBAT); } return false; } @@ -1051,12 +1058,12 @@ bool LoathebPositionAction::Execute(Event event) { if (AI_VALUE2(bool, "has aggro", "boss target")) { - return MoveTo(533, helper.mainTankPos.first, helper.mainTankPos.second, bot->GetPositionZ()); + return MoveTo(533, helper.mainTankPos.first, helper.mainTankPos.second, bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } } else if (botAI->IsRanged(bot)) { - return MoveInside(533, helper.rangePos.first, helper.rangePos.second, bot->GetPositionZ(), 1.0f); + return MoveInside(533, helper.rangePos.first, helper.rangePos.second, bot->GetPositionZ(), 1.0f, MovementPriority::MOVEMENT_COMBAT); } return false; } diff --git a/src/strategy/values/LastMovementValue.cpp b/src/strategy/values/LastMovementValue.cpp index f7b5488e..72acfee4 100644 --- a/src/strategy/values/LastMovementValue.cpp +++ b/src/strategy/values/LastMovementValue.cpp @@ -24,6 +24,7 @@ LastMovement::LastMovement(LastMovement& other) lastMoveShort = other.lastMoveShort; nextTeleport = other.nextTeleport; lastPath = other.lastPath; + priority = other.priority; } void LastMovement::clear() @@ -41,6 +42,7 @@ void LastMovement::clear() nextTeleport = 0; msTime = 0; lastdelayTime = 0; + priority = MovementPriority::MOVEMENT_NORMAL; } void LastMovement::Set(Unit* follow) @@ -51,7 +53,7 @@ void LastMovement::Set(Unit* follow) lastFollow = follow; } -void LastMovement::Set(uint32 mapId, float x, float y, float z, float ori, float delayTime) +void LastMovement::Set(uint32 mapId, float x, float y, float z, float ori, float delayTime, MovementPriority pri) { lastMoveToMapId = mapId; lastMoveToX = x; @@ -62,6 +64,7 @@ void LastMovement::Set(uint32 mapId, float x, float y, float z, float ori, float lastMoveShort = WorldPosition(mapId, x, y, z, ori); msTime = getMSTime(); lastdelayTime = delayTime; + priority = pri; } void LastMovement::setShort(WorldPosition point) diff --git a/src/strategy/values/LastMovementValue.h b/src/strategy/values/LastMovementValue.h index fc073a2a..a22debb5 100644 --- a/src/strategy/values/LastMovementValue.h +++ b/src/strategy/values/LastMovementValue.h @@ -13,6 +13,15 @@ class PlayerbotAI; class Unit; +// High priority movement can override the previous low priority one +enum class MovementPriority +{ + MOVEMENT_IDLE, + MOVEMENT_NORMAL, + MOVEMENT_COMBAT, + MOVEMENT_FORCED +}; + class LastMovement { public: @@ -28,14 +37,14 @@ public: lastMoveShort = other.lastMoveShort; lastPath = other.lastPath; nextTeleport = other.nextTeleport; - + priority = other.priority; return *this; }; void clear(); void Set(Unit* follow); - void Set(uint32 mapId, float x, float y, float z, float ori, float delayTime); + void Set(uint32 mapId, float x, float y, float z, float ori, float delayTime, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL); void setShort(WorldPosition point); void setPath(TravelPath path); @@ -53,6 +62,7 @@ public: float lastdelayTime; WorldPosition lastMoveShort; uint32 msTime; + MovementPriority priority; TravelPath lastPath; time_t nextTeleport; std::future future;