Files
RP412/RP/RPDIRECT.cpp
T
CydandClaude Opus 5 a5c1e0291c The camera bring-up says how far it got
A Live Cam station is selected entirely by egg data - hostType=1 on that
host's entry plus vehicle=camera - so no code path announces itself and a
station that fails to come up leaves a log that simply stops. RP412CAMLOG=1
traces the sequence: the stand-alone host and its type, the local player
node and game model, the interest-arena and interest-manager loads, the
registry choosing a director, the director making its camera ship, and the
launch handshake it waits on. Off by default.

What it found immediately: a camera host wedges inside
InterestManager::LoadMission - the map-entity load - and never returns.
Everything upstream is correct (the egg parses, hostType 1 is adopted,
gameModel reads 'camera'), and the same call with a racing egg passes
straight through to making the player and launching. Same map both times,
so it is the local host's TYPE that the map load cannot digest, not the
map. That is a defect to fix before a lobby has anything to switch on.

Also recorded while chasing it: a racing -egg run sits in application
state 11 with the low-priority queue never empty for its whole life, and
still simulates - so CheckLoad's no-console self-launch is not what
starts a stand-alone race. Worth knowing before trusting that path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 14:04:26 -05:00

214 lines
5.5 KiB
C++

#include "rp.h"
#pragma hdrstop
#include "rpdirect.h"
#include "..\munga\mission.h"
#include "..\munga\app.h"
#include "..\munga\nttmgr.h"
#include "rpplayer.h"
//#############################################################################
// Shared Data support
//
Derivation* RPCameraDirector::GetClassDerivations()
{ static Derivation classDerivations(CameraDirector::GetClassDerivations(), "RPCameraDirector");
return &classDerivations;
}
RPCameraDirector::SharedData
RPCameraDirector::DefaultData(
RPCameraDirector::GetClassDerivations(),
RPCameraDirector::MessageHandlers,
RPCameraDirector::GetAttributeIndex(),
RPCameraDirector::StateCount,
(CameraDirector::MakeHandler) RPCameraDirector::Make
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
RPCameraDirector::BeARPDirector(Scalar time_slice)
{
Check(this);
Player::PlayerSimulation(time_slice);
UpdateHUD(time_slice);
Logical force_target = False;
//
//--------------------------------------------------------------
// Time To Cut To a new Player? (Don't stay on a burning mech!)
//--------------------------------------------------------------
//
if (timeLeftOnPlayer > 0.0f && application->GetApplicationState() == Application::RunningMission)
{
timeLeftOnPlayer -= time_slice;
return;
}
else if (application->GetApplicationState() == Application::EndingMission)
{
force_target = True;
}
//
//--------------------------------------------------------------------
// Look for out target. If we are not in football, follow the leader.
// If we are in martian football, follow the losing runner
//--------------------------------------------------------------------
//
Player *top_dog;
Scalar new_time;
if (!martianFootball || application->GetSecondsRemainingInGame() < 30.0f)
{
top_dog = FindPlayerByRank(0);
new_time = 0.0f;
}
else
{
Check(application);
EntityManager *entity_mgr = application->GetEntityManager();
EntityGroup *player_group = entity_mgr->FindGroup("Players");
top_dog = NULL;
new_time = 20.0f;
if (player_group)
{
RPPlayer
*player,
*first_player=NULL;
ChainIteratorOf<Node*> iterator(player_group->groupMembers);
while ((player = (RPPlayer*)iterator.ReadAndNext()) != NULL)
{
Check(player);
if (player->playerType == RPPlayer::RunnerPlayerType)
{
if (!first_player)
{
first_player = player;
}
if (player->GetPlayerVehicle() == GetGoalEntity())
{
while ((player = (RPPlayer*)iterator.ReadAndNext()) != NULL)
{
Check(player);
if (player->playerType == RPPlayer::RunnerPlayerType)
{
top_dog = player;
break;
}
}
}
}
}
if (!top_dog && first_player)
{
top_dog = first_player;
}
}
}
//
//-------------------------------------------------------------------
// If we have a goal, and it is different from the last one, tell the
// cameras
//-------------------------------------------------------------------
//
if (top_dog)
{
Check(top_dog);
Entity *vehicle = top_dog->GetPlayerVehicle();
if (vehicle)
{
Check(vehicle);
Entity *goalEntity = GetGoalEntity();
if (goalEntity != vehicle || force_target)
{
SetGoalEntity(vehicle);
timeLeftOnPlayer = new_time;
Check(cameraShip);
CameraShip::DirectionMessage direction_message(
CameraShip::DirectionMessageID,
sizeof(CameraShip::DirectionMessage),
GetGoalEntity()->GetEntityID(),
0.0f,
Point3D::Identity
);
Check(cameraShip);
cameraShip->Dispatch(&direction_message);
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
RPCameraDirector::CreateRPCameraShip(Scalar time_slice)
{
Check(this);
if (RPCameraLog())
{
DEBUG_STREAM << "CamLog: CreateRPCameraShip - making the camera ship\n"
<< std::flush;
}
CameraDirector::CreateCameraShip(time_slice);
SetPerformance(&RPCameraDirector::BeARPDirector);
if (RPCameraLog())
{
DEBUG_STREAM << "CamLog: camera ship up, now directing\n" << std::flush;
}
}
//#############################################################################
// Construction and Destruction Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RPCameraDirector::RPCameraDirector(
RPCameraDirector::MakeMessage *creation_message,
RPCameraDirector::SharedData &virtual_data
) :
CameraDirector(creation_message, virtual_data)
{
Check_Pointer(creation_message);
currentWatchedPlayer = NULL;
Check(application);
CString scenarion_name = application->GetCurrentMission()->GetScenarioName();
martianFootball = !scenarion_name.Compare("football");
if (GetInstance() != ReplicantInstance)
{
SetPerformance(&RPCameraDirector::CreateRPCameraShip);
}
if (RPCameraLog())
{
DEBUG_STREAM << "CamLog: RPCameraDirector built, football="
<< (int) (martianFootball ? 1 : 0)
<< " replicant=" << (int) (GetInstance() == ReplicantInstance ? 1 : 0)
<< "\n" << std::flush;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RPCameraDirector*
RPCameraDirector::Make(MakeMessage *creation_message)
{
return new RPCameraDirector(creation_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RPCameraDirector::~RPCameraDirector()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
RPCameraDirector::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}