Files
tws-zombies-scripts/t6/scripts/NOTES.md
T

229 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# T6 port notes
T6 is ported from T5. Both source trees contain common, HUD, AFK, join, lock,
telemetry, leaderboard and bank modules; neither includes direct-database modules.
## Differences retained for T6 and requested fixes
| Area | Difference from T5 | Reason |
| --- | --- | --- |
| Paths | `maps/mp/_utility`, `scripts/zm/tws_t6_common` | T6 namespaces and requested filenames |
| Loading | No T5 `zombiemode` dvar gate; each module has `main()` and `init()` | Zombies-only folder loading; avoid r5346 missing-main warnings |
| HUD positioning | Fullscreen X/Y anchors, direct normalized `640 × 480` coordinates, unboxed core and service area | Bypass safe-area insets; validate Plutonium tag clearance and font fit at each aspect ratio |
| HUD rendering | Precached white shader, local max-health fallback, floating-point ratio, `getPlayers()` | T6 rendering/state handling without changing player max health |
| Enemy count | Stock `_zm_utility::get_current_zombie_count()` plus queued zombies | Uses the map's zombie team and enemy filters |
| Timers | Seed elapsed time for late joiners; stop round watcher/reset on game over | T6 timer behavior; keep frozen timers frozen |
| AFK | Maintain control freeze, disable guns/grenades, guard player state and stale grace threads | Requested movement/shooting fix; retain `.afk` / `.back` and two-second grace |
| Telemetry | Global `httpPost(url, options)`; T5-parity queue + heartbeat + game_start/end + watchdog + log-level dvar; per-player `guid` comes from the persistent `player.guid` field (T5 uses `player getGuid()` directly); per-match `kills`/`headshots`/`downs`/`revives` read from `player.pers[]`, with missing or negative values reported as `0` | Stock T6 connection initialization populates `.guid` before notifying `connected`; stock `initpersstat` / `incpersstat` maintain match counters in `player.pers[]`, whereas T5 uses `player.stats[]`. Payload keys match T5 for downstream shape parity |
| Join | Port of T5 `tws_t5_join.gsc`; uses `level.spawnplayer` / `level.custom_spawnplayer` (lowercase) and `maps\mp\zombies\_zm::spectator_respawn`; readiness gated on `self.sessionstate == "spectator"` instead of T5's `self.initialized` | T6 stock spectator respawn hook lives in `_zm.gsc`; `self.initialized` is a T5 SP zombiemode marker that T6 stock does not populate the same way |
Common provides matching T5/T6 HUD layout constants, helpers and first-spawn dispatcher.
HUD again owns the `hud_game_over` notification fan-out. Lock again waits on HUD
notifications, applies T5's random password, and clears it on startup/game over.
The added password-preservation dvars and independent lock watcher are gone.
Common also listens for `.help` through the native `say` notification, independent
of first-spawn initialization so newcomers can view commands while spectating.
Each loaded command module registers its command and description with
`register_help_command()` during `init()`. Lazy registry initialization preserves
registrations regardless of module initialization order. Common owns one
unboxed upper-right service area. Help shows all nine installed commands in
explicit command/description rows; extra registered commands use pages of nine
rows. Pages last 12 seconds, with automatic dismissal after the final page and
a counter only for multi-page lists. `.help` / `.commands` restart at page one.
Help pauses record page time, and a `.leaders` request during help replaces
the pending replay from page one. Service state prevents old requests from
closing newer displays. Disconnect and game-end cleanup are independent of
page timing. Command handlers retain their existing listeners, and help/records
work without the HUD module.
Both engines use explicit help rows; T5 no longer relies on newline rendering,
and T6 has the same row geometry. Common allocates only the active service
view: 19 nonarchived elements for nine-command help (20 with a multi-page
counter), or four for records (five with a multi-page counter). Closing the
service or switching kinds destroys the view; idle holds no elements. Pages
reuse the active elements, separately from controller and pending-request state.
Core + AFK use 11 + 1 archived elements. Hidden elements still occupy slots.
The [T6 player HUD structure](https://github.com/skiff/t6-gsc-helper/blob/50ff6cb7397c9376894a195f48118d1743812d1d/src/game/structs.hpp#L184)
has 31 slots in each bucket; it does not establish current Plutonium stock HUD
usage. Keep the live overlap/element-budget checks alongside the portable checks.
The core is created on connection for waiting spectators with placeholders,
while timer updates retain the existing spawn/round lifecycle. Connection-time
creation must not seed the match clock. The unboxed layout has timers at the
upper left, branding at top center and zombies/health at bottom center. HP
numbers appear to the right of the bar only while injured; AFK sits above the
zombie count. Services never reposition the core. Records are right aligned,
with `Map record · Round N` followed by up to three bounded holder lines, no
footer and no single-page counter. Their 12-second page timing is unchanged.
HUD `1.4.0` and AFK `1.2.0` require matching common `1.4.0+`; update all three
where installed and restart the map. Leaderboard `1.1.0` remains compatible.
Overlay helpers use direct normalized `640 × 480` coordinates. Dynamic health
fills use `make_overlay_width()` like their tracks. Apply `int()` after `max()`
in that helper: native `max()` returns a float, but `SetShader` requires an
integer width. Legacy panel helpers retain their `0.75` horizontal conversion
for existing consumers. Font scale is at least `1.0`. This introduces no
Plutonium/native-plugin/backend dependency or full server-process restart
requirement.
HUD owns the exact, case-insensitive `.hud` chat command and registers it in
help only while installed. Common's core wrappers preserve each element's
intended alpha behind a per-player visibility mask; health and AFK changes use
`set_core_alpha()`. Data/timers keep updating while hidden and freeze at game
over. Help, records, stock HUD and AFK protection are unaffected. Visibility
defaults on, survives death/respawn during the connection/map, and resets on
reconnect or map restart. All nine installed commands use one help page,
ordered `.help`, `.hud`, `.afk`, `.back`, `.join`, `.leaders`, `.b`, `.d`, `.w`.
Bank commands display the full `<amount|all>` syntax.
AFK again listens to the native `say` notification, so it no longer needs plugin
chat registration. The additional T6 controls are only held while AFK; `.back`
releases them before the protection grace period. Restoration is deferred during
death/laststand/intermission until active play. Other mods controlling the same
invulnerability or weapon flags can still conflict and need live testing.
The existing optional T5 dvars remain. Leaderboard adds the three settings
documented in the [shared README](../../README.md#map-record-announcements).
`common_config()` and `ensure_config()` are original T5 in-memory HUD helpers,
not an external configuration system.
## Leaderboard join announcements
The module is `tws_t6_leaderboard.gsc` in T6 and `tws_t5_leaderboard.gsc` in T5.
Common's existing
connection listener now also dispatches optional connection handlers after a
one-frame yield. Leaderboard waits for player readiness and uses a level-owned
HTTP cache, independent of the first-spawn handlers. T6 spectators keep
`hasSpawned` false, so T6 readiness uses session state and the intro-screen flag;
T5 sets `hasSpawned` for both playable and spectator spawns.
T6's active `scr_zm_ui_gametype` / `scr_zm_map_start_location` fields come from
[stock `_zm.gsc`](https://github.com/plutoniummod/t6-scripts/blob/2d8440321602f22f63f5335817110d60ddf223d5/ZM/Core/maps/mp/zombies/_zm.gsc).
Mode/location combinations follow the
[T6 server configurations](https://github.com/xerxes-at/T6ServerConfigs/tree/master/localappdata/Plutonium/storage/t6/gamesettings)
and Electric Cherry's map catalogue. Unknown selections require an explicit API
key instead of falling back to another variant sharing the engine map.
Historical validation for the initial leaderboard change: 135 fixture/static
checks passed using the actual data-handling functions from both scripts with
JavaScript engine-value shims. All seven then-current T6 scripts compiled and
assembled using a local Intel macOS driver built
from gsc-tool 1.5.1 sources. PowerShell was unavailable, so `check.ps1` itself was
not executed here. T5 compilation and live plugin/gameplay checks were not run;
gsc-tool has no T5 backend. The production API could not be reached from this
environment. See the shared README for the live validation cases.
## Verified primary sources
- [Plutonium loading guide](https://plutonium.pw/docs/modding/loading-mods/): T6
source scripts load from `storage/t6/scripts/zm`.
- [Entry-point lifecycle](https://plutonium.pw/docs/modding/gsc/new-scripting-features/):
`main()` runs early; `init()` runs after gametype startup. Empty `main()` must
not call `init()` and duplicate initialization.
- [Plutonium changelog, r2234](https://plutonium.pw/docs/changelog/): documents T6
`level waittill("say", message, player)`.
- [Stock T6 Zombies](https://github.com/plutoniummod/t6-scripts/blob/2d8440321602f22f63f5335817110d60ddf223d5/ZM/Core/maps/mp/zombies/_zm.gsc):
round state, `end_game`, invulnerability, and stock control resets.
- [Stock zombie utility](https://github.com/plutoniummod/t6-scripts/blob/2d8440321602f22f63f5335817110d60ddf223d5/ZM/Core/maps/mp/zombies/_zm_utility.gsc):
map-aware enemy counting.
- [Released plugin HTTP implementation](https://github.com/alicealys/t6-gsc-utils/blob/v3.1.1/src/component/http.cpp):
global `httpPost(url, options)` takes an options array with `body` and `headers`.
Its positional README example does not match this implementation.
Completion is `done(response, success, error)`; success reports transport only.
- [Plugin JSON implementation](https://github.com/alicealys/t6-gsc-utils/blob/v3.1.1/src/component/json.cpp):
`jsonSerialize` handles the event payload.
Do not create a dummy `http.gsc`. An unresolved `httpPost`/`jsonSerialize` means
the installed server/plugin must be checked. Installing a DLL requires a full
server-process restart, not just a map restart.
## Telemetry reboot investigation
The T5 and T6 implementations are not runtime-verified equivalents. In particular,
[T6 plugin v3.0.4](https://github.com/alicealys/t6-gsc-utils/blob/v3.0.4/src/component/http.cpp)
expects `httpPost(url, body, headers)` and notifies only the response body;
v3.1.1 expects `httpPost(url, options)` and also provides success/error values.
The current script targets the [TWS build](../plugins/README.md) based on v3.1.1,
which appends diagnostics and enforces native HTTP deadlines. Switching the function name does not establish
compatibility with an unknown installed DLL.
Console markers identify `main`, `init`, round serialization, HTTP invocation,
handle return and completion. They do not log the URL or response body. If startup
fails before `main`, inspect the first linker/plugin error, not the last supervisor
restart message. If no occupied positive round was observed, this script has not
called JSON serialization or HTTP yet.
Earlier live validation: the operator confirmed successful server startup and
Fleet delivery with the original direct reporter. The earlier reboot cause was
not established; logging alone should not be treated as a proven fix.
To recover the server while investigating, move `tws_t6_telemetry.gsc` outside the
autoload directory. The enable dvar cannot bypass unresolved native functions
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 eight files for T6 PC and checks shared
references and entry points. It requires PowerShell and gsc-tool. Run the
[shared HUD checks](../../README.md#hud-validation) for core/service behavior and
command regressions. Compiler success does not certify runtime linking.
Live checks after deploying:
1. Join, late-join, die/respawn, and reconnect: one unboxed core per player,
upper-left timers, top-center branding, bottom-center zombies/health and
spectator placeholders without an early clock start. Check damage-only HP,
health/Juggernog changes, AFK placement and timers frozen at game over.
Test safe-area settings and different resolutions against stock HUD elements.
2. `.afk` blocks movement, shooting and grenades; `.back` restores them. Try rapid
toggles, a round transition, death/respawn and game over.
3. Lock fires at the threshold and clears on game over/restart. HUD must be installed.
T5 semantics intentionally clear an existing password at startup.
4. Telemetry sends the initial occupied round and each new round to the existing
endpoint. Check server ID/player count, same-round joins and an unreachable API.
5. Repeat on the actual server maps, especially afterlife and special-enemy rounds.
6. Type `.help`, `.HELP` and `.commands` before first spawn, during play and
while AFK: one page of nine commands with all modules installed, full bank
syntax and no page counter, only on the requesting player's screen. Verify
dismissal after 12 seconds and repeat-to-restart behavior. Add custom
registered commands to exercise the nine-row page limit and page counter.
Remove optional modules and restart the map to confirm their commands are
absent. Restore them and confirm command behavior is unchanged.
7. Interrupt a record with help and check that its remaining page time resumes.
Repeat `.leaders` during help; only the latest replay should start from page
one after help closes. Check long names across pages, no records and
unavailable records. Reopen after expiry, disconnect/reconnect and end the
game during a service; verify no duplicates or leftovers. Repeat without HUD.
8. Toggle `.hud` before spawning, while playing/AFK and after game over. Verify
the core and AFK indicator hide privately while help/records remain visible.
Show it after taking damage or changing AFK state while hidden: current
values and intended alpha should return. Confirm updates continue hidden,
death/respawn keeps the choice, and reconnect/map restart restores visibility.
The stock T6 [HUD initialization](https://raw.githubusercontent.com/plutoniummod/t6-scripts/main/ZM/Core/maps/mp/gametypes_zm/_hud.gsc)
sets a nominal font height of 12; the corresponding
[font helper](https://raw.githubusercontent.com/plutoniummod/t6-scripts/main/ZM/Core/maps/mp/gametypes_zm/_hud_util.gsc)
uses `int(level.fontheight * fontscale)` for its height. The portable HUD checks
use that nominal box to prevent holder-row, help-row and AFK overlaps. Exact
glyph extents still need live validation, especially on T5.