feat(rails): answer RequestRailActivatorState

The client's rail activator sends RequestRailActivatorState (1479, no
payload) when it is added to the world (LWORailActivatorComponent::
SendMessage 0x00c00da0) and live answered with
NotifyRailActivatorStateChange (1478, bActive) to that client; the client
stores rail_activator_active and updates the rail's pick type (usable or
not). Live: 152 requests, 413 answers, every one bActive = true. DLU
dropped the request and never answered.

RailActivatorComponent keeps the level key rail_activator_active
(default true; every rail in the live levels sets it to 1) and the
request is answered with it.

Check in game: in Ninjago Monastery and Nimbus Station, rails (spinjitzu
posts, the Nexus Tower rails) show as usable and work as before when
first loading the world and after zone changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 03:23:47 -05:00
parent e9ff5f402d
commit 3672b64dec
6 changed files with 68 additions and 0 deletions

View File

@@ -4,6 +4,8 @@
#include "CDComponentsRegistryTable.h"
#include "CDRailActivatorComponent.h"
#include "Entity.h"
#include "MovementMessages.h"
#include "dGameMessagesTests/GameMessageTestUtils.h"
#include "RailActivatorComponent.h"
#include <gtest/gtest.h>
@@ -57,3 +59,26 @@ TEST_F(RailActivatorComponentTests, NoRowAndNoKeysIsNotImmune) {
EXPECT_FALSE(rail->GetDamageImmune());
EXPECT_FALSE(rail->GetNoAggro());
}
// Live answered the client's RequestRailActivatorState (1479, no payload; 152 packets) with
// NotifyRailActivatorStateChange (1478) to that client: every one of the 413 live packets was bActive = true (80).
TEST_F(RailActivatorComponentTests, RequestRailActivatorStateIsAnswered) {
using namespace GameMessageTestUtils;
entity->AddComponent<RailActivatorComponent>(COMPONENT_ID);
GameMessages::RequestRailActivatorState request;
const auto packets = Capture([&] { request.Handle(*entity, ClientAddress()); });
ASSERT_EQ(packets.size(), 1u);
EXPECT_EQ(packets[0].sysAddr, ClientAddress());
EXPECT_FALSE(packets[0].broadcast);
EXPECT_PACKET_EQ(FromHex("53 05 00 0c 00 00 00 00 01 00 00 00 00 00 00 00 c6 05 80", 145), FromCapture(packets[0]));
}
TEST_F(RailActivatorComponentTests, InactiveRailIsReportedInactive) {
using namespace GameMessageTestUtils;
entity->SetVar<bool>(u"rail_activator_active", false);
const auto* const rail = entity->AddComponent<RailActivatorComponent>(COMPONENT_ID);
EXPECT_FALSE(rail->GetActive());
GameMessages::NotifyRailActivatorStateChange notify;
notify.bActive = false;
EXPECT_FALSE(RoundTrip(notify).bActive);
}