Add AdventureBot groups, raid preparation and shared travel
clang PCH / build (push) Canceled after 0s
GCC PCH / build (push) Canceled after 0s

Implement native bot recruitment and player admission, leader-owned destinations, intent-specific capacities, preparation scheduling and shared graph and flight travel. Support native group instance visits and separate raid entrances.

Include pending personality-driven faction PvP and solo fleeing, preserving the absolute group fleeing exclusion. Add regression fixtures, migration, documentation and test-server evidence.
This commit is contained in:
Nico committed 2026-10-28 15:00:41 +01:00
1 parent 04aa87fcfc
commit d6fea6ee68
46 files changed
+3031 -59

No files matched your search

@@ -16,6 +16,7 @@
#include "MoveSpline.h"
#include "PhasingHandler.h"
#include "Player.h"
#include "Group.h"
#include "PathGenerator.h"
#include "Random.h"
#include "SpellInfo.h"
@@ -139,6 +140,8 @@ ClientlessFlightStatus const * ClientlessFlightMgr::GetStatus(uint32 guid) const
void ClientlessFlightMgr::Clear(uint32 guid)
{
auto it=_records.find(guid);
if(it!=_records.end() && it->second.Status.State!=ClientlessFlightState::Arrived)it->second.Published->Aborted=true;
_records.erase(guid);
}
@@ -270,6 +273,16 @@ bool ClientlessFlightMgr::Start(Player * player, Position const & target, std::s
record.Status.State = ClientlessFlightState::Mounting;
record.Status.MountSpell = spell;
record.Status.Detail = "waiting for native flying mount";
if(auto group=player->GetGroup())if(group->GetLeaderGUID()!=player->GetGUID())
{
auto source=_records.find(group->GetLeaderGUID().GetCounter());
if(source!=_records.end() && source->second.Status.MapId==player->GetMapId() &&
source->second.Status.Target.GetExactDist(target)<1 && !source->second.Published->Aborted)
{
record.Following=source->second.Published;record.Status.Landing=source->second.Status.Landing;
TC_LOG_INFO("server.adventurebot.navigation","FLIGHT_SHARED_TRAIL guid=%u leader=%u",player->GetGUID().GetCounter(),group->GetLeaderGUID().GetCounter());
}
}
_records[player->GetGUID().GetCounter()] = std::move(record);
if (player->CastSpell(player, spell, false) != SPELL_CAST_OK)
{
@@ -283,6 +296,7 @@ bool ClientlessFlightMgr::Start(Player * player, Position const & target, std::s
void ClientlessFlightMgr::Fail(Player * player, Record & record, std::string const & reason)
{
record.Published->Aborted=true;
player->StopMoving();
record.Moving = false;
if (record.Status.State == ClientlessFlightState::Mounting) player->InterruptNonMeleeSpells(false);
@@ -338,6 +352,13 @@ bool ClientlessFlightMgr::Advance(Player * player, Record & record, bool handoff
back, Corridor(current, back, goal, record.Settings, sample, ray, true), true, false
};
}
else if(record.Following)
{
auto shared=FollowTrail(current,goal,record.Settings,*record.Following,record.SharedIndex,sample,ray);
if(shared.Waiting)return true;
next=shared.Step;
if(handoff && next.Valid && Distance(next.Next,PointOf(record.Segment))<1)return true;
}
else
{
auto const memory = record.Memory;
@@ -368,6 +389,7 @@ bool ClientlessFlightMgr::Advance(Player * player, Record & record, bool handoff
Fail(player, record, "flight spline rejected");
return false;
}
record.Published->Points.push_back(next.Next);
record.Moving = true;
record.SegmentElapsed = 0;
++ record.Status.Segments;