Implement safe AdventureBot group travel and formations
clang PCH / build (push) Canceled after 0s
GCC PCH / build (push) Canceled after 0s

This commit is contained in:
Nico committed 2026-10-28 23:30:28 +01:00
1 parent a758239da9
commit cac4142ec1
26 files changed
+1482 -79

No files matched your search

+21 -3
View File
@@ -58,7 +58,7 @@ struct Position {
float GetPositionX()const{return x;}float GetPositionY()const{return y;}float GetPositionZ()const{return z;}float GetOrientation()const{return o;}
float GetExactDist(Position const*p)const{return std::sqrt((x-p->x)*(x-p->x)+(y-p->y)*(y-p->y)+(z-p->z)*(z-p->z));}
};
constexpr int MOVE_RUN=0;
constexpr int MOVE_RUN=0,SPELL_AURA_MOUNTED=1;
struct TransportDockState {uint32 Progress=0,Period=0,RemainingPause=0;bool Stopped=false;};
class Player; class GameObject;
class TransportBase {
@@ -86,6 +86,9 @@ class Player:public Position {
public:
TransportBase* transport=nullptr;uint32 map=0;GameObject* object=nullptr;Motion motion{this};bool pending=false;
struct {struct {Position pos;ObjectGuid guid;uint32 time=0;void Reset(){pos={};guid={};time=0;}}transport;}m_movementInfo;
int teleports=0;bool falling=false;
bool IsFalling()const{return falling;}bool IsMounted(){return false;}void Dismount(){}void UpdateSpeed(int){}void RemoveAurasByType(int){}
bool TeleportTo(uint32 m,float a,float b,float c,float d){++teleports;map=m;Relocate(a,b,c,d);falling=false;return true;}
bool IsAlive()const{return true;}bool IsFlying()const{return false;}bool IsInFlight()const{return false;}
bool IsInWorld()const{return true;}bool IsInPhase(GameObject*)const{return true;}
bool IsBeingTeleported()const{return pending;}TransportBase* GetTransport()const{return transport;}
@@ -98,7 +101,11 @@ void TransportBase::CalculatePassengerOffset(float&x,float&y,float&z,float*o)con
void TransportBase::AddPassenger(Player*p){p->transport=this;p->m_movementInfo.transport.guid=go->GetGUID();}
void TransportBase::RemovePassenger(Player*p){p->transport=nullptr;p->m_movementInfo.transport.Reset();}
void Motion::MoveSmoothPath(int,Position* path,int,bool){p->Relocate(path[1]);if(p->transport){Position pos=*p;p->transport->CalculatePassengerOffset(pos.x,pos.y,pos.z,&pos.o);p->m_movementInfo.transport.pos=pos;}}
struct Travel {void CancelTravel(uint32){}}travel;
enum class ClientlessTravelState{Moving,Arrived,Stuck,PathRejected};
struct ClientlessPathDiagnostics{bool Complete=true,Suspicious=false;float PathLength=50;};
struct Travel{bool path=false,present=false;int starts=0;struct Status{ClientlessTravelState State=ClientlessTravelState::Moving;}status;
auto GetStatus(uint32)->Status*{return present?&status:nullptr;}bool AnalyzePath(Player*,Position const&,ClientlessPathDiagnostics&){return path;}
bool StartTravel(Player*p,Position const&point,bool){++starts;present=true;p->Relocate(point);return true;}void CancelTravel(uint32){present=false;}}travel;
auto sClientlessTravelMgr=&travel;
// Model the real Field API's strict debug type checks for SMALLINT versus INT.
struct Field {
@@ -120,7 +127,7 @@ methods = '\n'.join(function(source, marker) for marker in [
'bool ClientlessTransportMgr::HasConnection(', 'bool ClientlessTransportMgr::AtDock(',
'bool ClientlessTransportMgr::Sample(', 'bool ClientlessTransportMgr::Start(',
'void ClientlessTransportMgr::SetPhase(', 'void ClientlessTransportMgr::Cancel(',
'void ClientlessTransportMgr::UpdateRide('
'void ClientlessTransportMgr::RecoverPassenger(', 'void ClientlessTransportMgr::UpdateRide('
])
stubs = r'''
void PublishPassengerState(Player*){}
@@ -203,6 +210,17 @@ int main(){
run(ships,sailor,crossing);assert(crossing.Status.Phase==Phase::Riding&&sailor.transport==&destination.base);
destination.x=100;sailor.x=101;
run(ships,sailor,crossing);assert(crossing.Status.Phase==Phase::Arrived&&!sailor.transport&&sailor.x==104&&sailor.map==0);
// A lost, previously boarded passenger returns to the recorded departure,
// never to the moving leader or the destination harbor.
Player lost;lost.object=&go;lost.x=50;auto recovery=mgr._rides.at(26);
recovery.Status.Phase=Phase::Riding;recovery.Status.Recovering=false;recovery.Abort=false;
travel.path=false;mgr.UpdateRide(&lost,recovery,100);
assert(recovery.Status.Recovering && lost.teleports==1 && lost.x==0);
mgr.UpdateRide(&lost,recovery,100);assert(!recovery.Status.Recovering && recovery.Status.Phase==Phase::Waiting);
// A valid walking return uses native point travel, without teleporting.
lost.x=50;lost.teleports=0;travel.path=true;recovery.Status.Phase=Phase::Riding;
mgr.UpdateRide(&lost,recovery,100);assert(lost.teleports==0 && travel.starts==1);
mgr.UpdateRide(&lost,recovery,100);assert(!recovery.Status.Recovering);
std::cout<<"Transport dock, frame, recorder, cross-map copy and ride regressions passed\n";
}
'''