The script of the platforms a spinner moves once: a simple mover (or a
mover on a two point path) in the spinner's group_deactivated_event
group goes to its waypoint 1 when the spinner fires the event named in
the platform's name_deactivated_event. The NJ spinner script already
fires those events at its groups.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
A simple mover is a LWOPlatform like a mover: made stopped at its
waypoint (12) and, unless startPathingOnLoad is false, waiting there (9)
for the shortest wait before it leaves for its other end
(ResumeTravelling 0x00c86b90, SetWaitingTime 0x00bdc860, RunPlatform
0x00c86e10). Live showed it on the NJ counterweights, which wait for
their quick build first; one without a quick build was left waiting for
a script here.
The client only reads startPathingOnLoad (LWOMovingPlatformComponent::
LoadConfigData 0x00d0f690) and never starts a platform by itself, so the
rule is the server's, taken from what live did with movers (12 with the
setting false, else 9 and off) and from the scripts: L_NJ_SPINNER_SERVER
stops its platform when it starts up, simple movers included, and the
simple movers that wait for an event without that script all have
startPathingOnLoad 0 in the maps.
The wait now runs in the component for both, in place of the timer a
built counterweight got, and a simple mover with startPathingOnLoad
false is constructed stopped (12).
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Live serialized a mover leaving a waypoint not where the waypoint is but
past it: the GF shooting gallery subs 2 units on (speed 15), the FV
dragons 5.33 (speed 40), each along the stretch they came by, and a
dragon met 2.2 s into its 5 s wait was 88 units past its waypoint (1.219
of the next stretch). At either end of a path they left from the
waypoint itself.
It is the client's LWOPlatform at work, which the server ran too:
- SetWaitingTime (0x00bdc860) takes the object's velocities away only
when the platform has stopped or is at an end of its path, so through a
wait in between the object goes on as it came;
- the percent is how far the object is from the waypoint
(CalculatePercentTravelledToWaypoint 0x00be9050);
- UpdateVelocities (0x00bd4330) on leaving turns it the next stretch's
way from where it is, and it arrives when it passes the next waypoint
(CloseToNextWaypoint 0x00bd4140), where ProcessStateChange (0x00cce380)
puts it at the waypoint;
- a platform that has not stopped looks whether it arrived while it waits
too (HandleStoppedLogic 0x00bd16a0): the dragons were at waypoint 5
without having left 4.
The server's mover now moves by its velocity in the same way, so the
state it sends on leaving carries the place and percent live sent.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
LWOPlatformRotator on a path does not move: while it travels it turns at
the angular velocity SetAngularVelocity (0x00bfa380) works out, never
waits (IncrementWaitingTime 0x004a0390) and never arrives
(HandleStoppedLogic 0x00bdc660). The velocity is the one that turns from
no rotation to NiMatrix3::FromEulerAnglesXYZ (0x0116c3a0) of rotX, rotY
and rotZ (half turns in the level config, LoadConfigData 0x00c33e10) in
half the rate, as hkpKeyFrameUtility's
setUsingPositionOrientationPair (0x012a4050) gives it: the shortest
way, the axis times the angle over the time, none for whole turns. In
reverse it is the other way round.
The server's object now turns with it, without a serialization of its
physics (each client turns its own once the rotator is sent travelling),
and is put at its waypoint as SetupPath does. A quick build's rotator
waits for the build like a mover.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Only a rotater on a path runs (LWOMovingPlatformComponent::SetupPlatform 0x00ccea50), and the client reads a platform that is not at a waypoint from its path's waypoints (LWOPlatform::Deserialize 0x00c870e0), which a rotater without a path does not have. It was sent travelling (2) whenever startPathingOnLoad was not false. No object in the client's maps is a rotater.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Live (the Frakjaw battle captures, LOT 16141): when its quick build completes the simple mover is serialized waiting at waypoint 0 (9) and about 0.1 s later travelling (2); it stops at its end without a serialization. That is the client's LWOPlatform, active once the quick build is complete (SendMessage 0x00bdc930), waiting the shortest wait and setting off (RunPlatform 0x00c86e10). L_CAVE_PRISON_CAGE and L_MONASTERY_BOSS_INSTANCE_SERVER never send it: they ask to be told of its PlatformAtLastWaypoint, and act then.
So the simple mover sets off when it is built, the cave prison's button goes down when the counterweight arrives instead of when it is built, and Frakjaw is hit when it arrives (0.1 s and the row's 1 s after the build) instead of on a 0.5 s timer with a counterweight that never moved.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LWOMovingPlatformComponent::SetCurrentPath (0x00d0f570, the SetCurrentPath game message of 0x00d0f5d0): the path, its starting waypoint and direction, then the subcomponents are made anew (SetupPlatform 0x00ccea50) and the mover takes the path at that waypoint. The path is written to the clients once more, whose component sets it the same way (Deserialize 0x00c88000), and the reverse flag of the path is no longer always written false.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LWOPlatform moves its object with SetPosition and SetRotation ignoring the dirty flags (ProcessStateChange 0x00cce380), turned between the two waypoints' rotations, and live serialized a moving platform's mover data without its physics. The server's object stayed where it spawned, so anything that asks where a platform is (the lightning orbs' knockback of issue 1352, phantoms riding a platform) had the start of its path.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The state bits were named the wrong way round: 1 is waiting and 4 is stopped (LWOPlatform::StartTravelling 0x0058b170, StopTravelling 0x0058b1d0), and the client only stops on 4 (LWOPlatform::Deserialize 0x00c870e0), so a mover stopped on its way kept moving on the client. The mover now runs as LWOPlatform::RunPlatform 0x00c86e10, ArrivedAtWaypoint 0x00c86c30, HandleWaypointArrived 0x00c17bc0 and ResumeTravelling 0x00c86b90, which gives the states of the live captures: 12 until started, 9 waiting at a waypoint (25 at an end), 2 on its way, 28 stopped at an end of a path run once. A GoToWaypoint at a waypoint waits there first with the desired waypoint, as the NJ falling tiles did, and a mover that stops is not serialized for it. A quick build's mover does not run until it is built.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PlatformSubComponent (LWOPlatform: the state between waypoints and its
serialization) is the base of MoverSubComponent (4), SimpleMoverSubComponent
(5) and the new RotatorSubComponent (6), as LWOPlatformMover,
LWOPlatformSimpleMover and LWOPlatformRotator are built on LWOPlatform. The
platform keeps one subcomponent per type the client makes
(LWOMovingPlatformComponent::SetupPlatform: one per platformIs* setting that
is true) and sends them all; the first is the one the server runs. Same bytes
for every platform with one subcomponent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Components get the client's per-component functions: LoadDataFromTemplate,
PrepareConfigData, LoadConfigData, LoadFromSaveData, Startup, Run,
OnEnterScope, OnLeaveScope, Preshutdown and Shutdown, called by the entity in
the client's order. Update is renamed Run, LoadFromXml LoadFromSaveData and
UpdateXml WriteSaveData. Nothing sent changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LWOPlatform::ResumeTravelling: not travelling at a waypoint it waits the waypoint's wait; the AG monument elevator rose at once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The client's LWOPlatform logic (ArrivedAtWaypoint 0x00c86c30, ProcessStateChange 0x00cce380, GetNextWaypoint, the waypoint speeds) runs on the server: stopped at a waypoint (25 at an end) for its wait, then travelling (2), serialized on arrival and departure as in the NT mover captures; constructions carry the path and the mover state; RequestPlatformResync gets the current state, percent and position. The LOT 9483 timers are gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>