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 "Travel/UnifiedTravelGraph.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "Player.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
@@ -843,6 +845,13 @@ void DispatchInGroup(BotAI& ai,
|
||||
if (!in_active_bg && !dungeon_run_owns_movement && !detour_leased &&
|
||||
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
|
||||
// when the leader is unreachable (across a gap / closed door) — and
|
||||
// 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 OnPlayerMounted(Player* p) { V2::Module::instance().OnMounted(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 OnResurrect(Player* p) { V2::Module::instance().OnResurrect(p); }
|
||||
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 OnPlayerMounted(Player* p);
|
||||
void OnPlayerDismounted(Player* p);
|
||||
void OnPlayerVehicleExit(Player* p);
|
||||
void OnDeath(Unit* victim, Unit* killer);
|
||||
void OnResurrect(Player* p);
|
||||
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*/)
|
||||
{
|
||||
if (!initialized_ || !victim) return;
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
void OnLevelUp(Player* p, uint8 new_level);
|
||||
void OnMounted(Player* owner);
|
||||
void OnDismounted(Player* owner);
|
||||
void OnVehicleExit(Player* owner);
|
||||
void OnDeath(Unit* victim, Unit* killer);
|
||||
void OnResurrect(Player* p);
|
||||
void OnSpecChanged(Player* p, uint8 new_spec);
|
||||
|
||||
@@ -1451,9 +1451,23 @@ index 1f376653f2..971fb43af8 100644
|
||||
+ Playerbot::Hooks::OnDeath(victim, attacker);
|
||||
+#endif
|
||||
+
|
||||
// find player: owner of controlled `this` or `this` itself maybe
|
||||
Player* player = nullptr;
|
||||
if (attacker)
|
||||
// find player: owner of controlled `this` or `this` itself maybe
|
||||
Player* player = nullptr;
|
||||
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
|
||||
index 58951339b2..7ce860e770 100644
|
||||
--- a/src/server/game/Groups/GroupMgr.h
|
||||
|
||||
Reference in New Issue
Block a user