feat(load): PlayerReady also goes to the zone control object

Live answered PlayerLoaded with PlayerReady to the player and then a
second PlayerReady to the zone control object (0x3FFFFFFFFFFE), both
to the loading client: 235 of 237 captured loads carry exactly that
pair. DLU sent only the first. The zone control object's client-side
zone scripts are what can react to it (inferred: the client's
component handlers only act on the player's own PlayerReady).

Check: load into Avant Gardens, Nimbus Station, a property and an
instance (a survival or dragon battle): the zone plays its intro,
music and UI as before and nothing is stuck waiting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 03:25:56 -05:00
parent e2d6c4124b
commit a25eb34d66
4 changed files with 54 additions and 4 deletions

View File

@@ -35,11 +35,19 @@ namespace GameMessages {
return bitStream.Read(playerID);
}
void SendPlayerReady(const LWOOBJID player, const LWOOBJID zoneControl, const SystemAddress& sysAddr) {
PlayerReady playerReady;
playerReady.target = player;
playerReady.SendToClient(sysAddr);
if (zoneControl == LWOOBJID_EMPTY) return;
playerReady.target = zoneControl;
playerReady.SendToClient(sysAddr);
}
void PlayerLoaded::Handle(Entity& entityRef, const SystemAddress& sysAddr) {
auto* entity = &entityRef;
PlayerReady playerReady;
playerReady.target = entity->GetObjectID();
playerReady.SendToClient(sysAddr);
const auto* const zoneControlEntity = Game::entityManager->GetZoneControlEntity();
SendPlayerReady(entity->GetObjectID(), zoneControlEntity ? zoneControlEntity->GetObjectID() : LWOOBJID_EMPTY, sysAddr);
entity->SetPlayerReadyForUpdates();
auto* ghostComponent = entity->GetComponent<GhostComponent>();