Merge pull request 'Playerbot: bots hold position while owner rides a vehicle; re-summon to owner's location+phase on vehicle exit' (#1) from fix/bot-vehicle-follow into main
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
@@ -14,6 +14,8 @@
|
|||||||
#include "Services.h"
|
#include "Services.h"
|
||||||
#include "Travel/UnifiedTravelGraph.h"
|
#include "Travel/UnifiedTravelGraph.h"
|
||||||
#include "SharedDefines.h"
|
#include "SharedDefines.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "ObjectAccessor.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
@@ -843,6 +845,13 @@ void DispatchInGroup(BotAI& ai,
|
|||||||
if (!in_active_bg && !dungeon_run_owns_movement && !detour_leased &&
|
if (!in_active_bg && !dungeon_run_owns_movement && !detour_leased &&
|
||||||
dist > kRecallSlack && !snapshot.is_rooted())
|
dist > kRecallSlack && !snapshot.is_rooted())
|
||||||
{
|
{
|
||||||
|
// Vehicle rides (boar ride, cannons, ...): while the leader is on a
|
||||||
|
// vehicle, hold position instead of chasing the moving vehicle (bots
|
||||||
|
// would otherwise trail hopelessly behind an on-rails ride). The bots
|
||||||
|
// are re-summoned to the leader once the ride ends (vehicle dismount).
|
||||||
|
if (Player* anchor_player = ObjectAccessor::FindConnectedPlayer(anchor->guid))
|
||||||
|
if (anchor_player->GetVehicle())
|
||||||
|
return;
|
||||||
// Follow uses MotionMaster MoveFollow, which silently re-emits forever
|
// Follow uses MotionMaster MoveFollow, which silently re-emits forever
|
||||||
// when the leader is unreachable (across a gap / closed door) — and
|
// when the leader is unreachable (across a gap / closed door) — and
|
||||||
// grouped bots are exempt from GlobalStuckRescue, so they have no other
|
// grouped bots are exempt from GlobalStuckRescue, so they have no other
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ void OnPlayerLogout(Player* p) { V2::Module::instance().OnPlayerLogout(p); }
|
|||||||
void OnLevelUp(Player* p, uint8 new_level) { V2::Module::instance().OnLevelUp(p, new_level); }
|
void OnLevelUp(Player* p, uint8 new_level) { V2::Module::instance().OnLevelUp(p, new_level); }
|
||||||
void OnPlayerMounted(Player* p) { V2::Module::instance().OnMounted(p); }
|
void OnPlayerMounted(Player* p) { V2::Module::instance().OnMounted(p); }
|
||||||
void OnPlayerDismounted(Player* p) { V2::Module::instance().OnDismounted(p); }
|
void OnPlayerDismounted(Player* p) { V2::Module::instance().OnDismounted(p); }
|
||||||
|
void OnPlayerVehicleExit(Player* p) { V2::Module::instance().OnVehicleExit(p); }
|
||||||
void OnDeath(Unit* victim, Unit* killer) { V2::Module::instance().OnDeath(victim, killer); }
|
void OnDeath(Unit* victim, Unit* killer) { V2::Module::instance().OnDeath(victim, killer); }
|
||||||
void OnResurrect(Player* p) { V2::Module::instance().OnResurrect(p); }
|
void OnResurrect(Player* p) { V2::Module::instance().OnResurrect(p); }
|
||||||
void OnSpecChanged(Player* p, uint8 new_spec) { V2::Module::instance().OnSpecChanged(p, new_spec); }
|
void OnSpecChanged(Player* p, uint8 new_spec) { V2::Module::instance().OnSpecChanged(p, new_spec); }
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ void OnPlayerLogout(Player* p);
|
|||||||
void OnLevelUp(Player* p, uint8 new_level);
|
void OnLevelUp(Player* p, uint8 new_level);
|
||||||
void OnPlayerMounted(Player* p);
|
void OnPlayerMounted(Player* p);
|
||||||
void OnPlayerDismounted(Player* p);
|
void OnPlayerDismounted(Player* p);
|
||||||
|
void OnPlayerVehicleExit(Player* p);
|
||||||
void OnDeath(Unit* victim, Unit* killer);
|
void OnDeath(Unit* victim, Unit* killer);
|
||||||
void OnResurrect(Player* p);
|
void OnResurrect(Player* p);
|
||||||
void OnSpecChanged(Player* p, uint8 new_spec);
|
void OnSpecChanged(Player* p, uint8 new_spec);
|
||||||
|
|||||||
@@ -2944,6 +2944,33 @@ void Module::OnDismounted(Player* owner)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Module::OnVehicleExit(Player* owner)
|
||||||
|
{
|
||||||
|
// After an on-rails vehicle ride (Exile's Reach boar ride, ...) the bots
|
||||||
|
// held position instead of following the moving vehicle. Now that the
|
||||||
|
// player is off, summon them back to the player's location and phase so
|
||||||
|
// they actually appear (bots were spawning at coords but not in the
|
||||||
|
// player's phase shift).
|
||||||
|
if (!initialized_ || !owner) return;
|
||||||
|
WorldSession* sess = owner->GetSession();
|
||||||
|
if (!sess || sess->IsBot()) return;
|
||||||
|
uint32 const account_id = sess->GetAccountId();
|
||||||
|
if (account_id == 0) return;
|
||||||
|
|
||||||
|
auto bots = Services::Altbots().AltsOfAccount(account_id);
|
||||||
|
for (BotId id : bots)
|
||||||
|
{
|
||||||
|
Player* bot = ObjectAccessor::FindConnectedPlayer(
|
||||||
|
ObjectGuid::Create<HighGuid::Player>(id));
|
||||||
|
if (!bot || !bot->IsInWorld()) continue;
|
||||||
|
if (bot->IsInCombat() || !bot->IsAlive()) continue;
|
||||||
|
|
||||||
|
PhasingHandler::InheritPhaseShift(bot, owner);
|
||||||
|
BotMovement::SafeNearTeleport(bot, owner->GetPositionX(),
|
||||||
|
owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Module::OnDeath(Unit* victim, Unit* /*killer*/)
|
void Module::OnDeath(Unit* victim, Unit* /*killer*/)
|
||||||
{
|
{
|
||||||
if (!initialized_ || !victim) return;
|
if (!initialized_ || !victim) return;
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public:
|
|||||||
void OnLevelUp(Player* p, uint8 new_level);
|
void OnLevelUp(Player* p, uint8 new_level);
|
||||||
void OnMounted(Player* owner);
|
void OnMounted(Player* owner);
|
||||||
void OnDismounted(Player* owner);
|
void OnDismounted(Player* owner);
|
||||||
|
void OnVehicleExit(Player* owner);
|
||||||
void OnDeath(Unit* victim, Unit* killer);
|
void OnDeath(Unit* victim, Unit* killer);
|
||||||
void OnResurrect(Player* p);
|
void OnResurrect(Player* p);
|
||||||
void OnSpecChanged(Player* p, uint8 new_spec);
|
void OnSpecChanged(Player* p, uint8 new_spec);
|
||||||
|
|||||||
@@ -1451,9 +1451,23 @@ index 1f376653f2..971fb43af8 100644
|
|||||||
+ Playerbot::Hooks::OnDeath(victim, attacker);
|
+ Playerbot::Hooks::OnDeath(victim, attacker);
|
||||||
+#endif
|
+#endif
|
||||||
+
|
+
|
||||||
// find player: owner of controlled `this` or `this` itself maybe
|
// find player: owner of controlled `this` or `this` itself maybe
|
||||||
Player* player = nullptr;
|
Player* player = nullptr;
|
||||||
if (attacker)
|
if (attacker)
|
||||||
|
@@ -13071,5 +13113,13 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
||||||
|
// If the player is on mounted duel and exits the mount, he should immediatly lose the duel
|
||||||
|
if (player && player->duel && player->duel->IsMounted)
|
||||||
|
player->DuelComplete(DUEL_FLED);
|
||||||
|
|
||||||
|
+#if TRINITY_PLAYERBOT_V2
|
||||||
|
+ // PlayerbotV2: a human owner leaving a vehicle (Exile's Reach boar ride,
|
||||||
|
+ // ...) tells owned bots to re-summon to his location + phase (they held
|
||||||
|
+ // position while the vehicle moved).
|
||||||
|
+ if (player && player->GetSession() && !player->GetSession()->IsBot())
|
||||||
|
+ Playerbot::Hooks::OnPlayerVehicleExit(player);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT
|
||||||
diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h
|
diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h
|
||||||
index 58951339b2..7ce860e770 100644
|
index 58951339b2..7ce860e770 100644
|
||||||
--- a/src/server/game/Groups/GroupMgr.h
|
--- a/src/server/game/Groups/GroupMgr.h
|
||||||
|
|||||||
Reference in New Issue
Block a user