Fix T6 newcomer join eligibility after setup spawns
This commit is contained in:
@@ -118,6 +118,25 @@ at link time. The other four TWS modules can run without telemetry.
|
||||
|
||||
## Checks
|
||||
|
||||
### Newcomer eligibility
|
||||
|
||||
The stock [`_zm_gametype::onspawnplayer`](https://github.com/plutoniummod/t6-scripts/blob/2d8440321602f22f63f5335817110d60ddf223d5/ZM/Core/maps/mp/gametypes_zm/_zm_gametype.gsc)
|
||||
can schedule `spawnspectator` after 0.05 seconds while
|
||||
[`_globallogic_spawn::spawnplayer`](https://github.com/plutoniummod/t6-scripts/blob/2d8440321602f22f63f5335817110d60ddf223d5/ZM/Core/maps/mp/gametypes_zm/_globallogic_spawn.gsc)
|
||||
emits `spawned_player` at frame end. That event alone does not prove gameplay.
|
||||
Join `1.0.1` waits 0.1 seconds before checking session state and keeps listening
|
||||
after setup spectator spawns. `killed_player` also consumes eligibility so a
|
||||
death during that interval cannot restore newcomer access. The common dispatcher
|
||||
still starts each registered module once per connection.
|
||||
|
||||
Run `node tools/check_join.mjs` for portable lifecycle and request fixtures.
|
||||
These execute the join script with engine shims, not a GSC VM. Live validation:
|
||||
join Farm Survival during round 3 and remain spectating, use `.join` once, then
|
||||
try repeated requests, death, and subsequent rounds. On a fresh connection,
|
||||
wait for a normal round-start spawn, die, and verify `.join` is rejected.
|
||||
Also check a round-1 participant, reconnecting, disconnect during setup, and
|
||||
game over. Repeat on another T6 map; compile with the checker below first.
|
||||
|
||||
Local: `tools/check.ps1` compiles all seven files for T6 PC and checks shared
|
||||
references and entry points. It requires PowerShell and gsc-tool. The `.help`
|
||||
change passed the static entry-point/reference checks, but compilation and live
|
||||
|
||||
@@ -20,9 +20,44 @@ init()
|
||||
level thread join_chat_listener();
|
||||
}
|
||||
|
||||
// Never reset this on death or round change. Spectator spawns do not count.
|
||||
// T6 first emits spawned_player during setup, then moves late connectors
|
||||
// into spectator mode after 0.05 seconds. Observe the settled state instead.
|
||||
// The common spawn dispatcher runs only once, so keep listening ourselves.
|
||||
join_spawn()
|
||||
{
|
||||
self endon("disconnect");
|
||||
level endon("end_game");
|
||||
level endon("game_ended");
|
||||
level endon("intermission");
|
||||
|
||||
self thread join_track_death();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
self.tws_join_spawn_pending = true;
|
||||
wait 0.1;
|
||||
|
||||
if (isDefined(self.sessionstate) && self.sessionstate == "playing")
|
||||
self.tws_join_has_played = true;
|
||||
|
||||
self.tws_join_spawn_pending = false;
|
||||
if (is_true(self.tws_join_has_played))
|
||||
return;
|
||||
|
||||
self waittill("spawned_player");
|
||||
}
|
||||
}
|
||||
|
||||
// A real death during the settling window still consumes newcomer eligibility.
|
||||
// Never clear this flag on death, a round change, or a subsequent spawn.
|
||||
join_track_death()
|
||||
{
|
||||
self endon("disconnect");
|
||||
level endon("end_game");
|
||||
level endon("game_ended");
|
||||
level endon("intermission");
|
||||
|
||||
self waittill("killed_player");
|
||||
self.tws_join_has_played = true;
|
||||
}
|
||||
|
||||
@@ -51,8 +86,7 @@ join_request()
|
||||
level endon("game_ended");
|
||||
level endon("intermission");
|
||||
|
||||
// The spawn handler flag is set on first playable spawn only; spectator
|
||||
// spawns do not trigger it. Belt-and-suspenders against re-triggering.
|
||||
// Setup spawns do not consume eligibility; actual play and .join do.
|
||||
if (is_true(self.tws_join_has_played) || is_true(self.tws_join_used))
|
||||
{
|
||||
self iPrintLnBold("^3.join is only for newcomers who have not played yet");
|
||||
@@ -62,7 +96,8 @@ join_request()
|
||||
// Fail closed while the stock connection setup is still in progress.
|
||||
// T6 stock does not populate self.initialized the way T5 SP zombiemode
|
||||
// does; use sessionstate as the readiness signal.
|
||||
if (!isDefined(self.sessionstate) || self.sessionstate != "spectator")
|
||||
if (is_true(self.tws_join_spawn_pending) ||
|
||||
!isDefined(self.sessionstate) || self.sessionstate != "spectator")
|
||||
{
|
||||
self iPrintLnBold("^3.join is only available while waiting to enter the game");
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user