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

5.6 KiB

tws-t5-aio notes

Reference for the tws_*.gsc files in this repo. Platform quirks and load-bearing decisions that show up as invariants in the code.

Install

Copy all tws_*.gsc to storage/t5/scripts/sp/ on the Plutonium T5 server (v2 Plutainer: app/runtime/plutonium/storage/t5/scripts/sp/).

  • sudo chown -R 1000:1000 <app> — Plutainer runs as UID 1000
  • docker exec <container> rcon-cli map_restart — reloads scripts in place

Platform quirks (T5 SP engine, Plutonium)

  • Initialize locals before loops when reading them afterwards. T5 rejected leaderboard's chosen variable at load time when its only assignment was inside the map-search loop, even though its later use was guarded by the match count. It now starts as undefined before that loop in both versions. The JavaScript fixture harness and T6 compiler did not catch this T5 error.
  • One level waittill("connected") only. tws_common owns it. A second listener breaks the T5 SP connect handshake. Per-player work goes through tws_common::register_spawn_handler after spawned_player, or register_connect_handler for spectator-safe work after the dispatcher yields. Leaderboard uses the latter; its level worker owns all HTTP work.
  • Chat uses level waittill("say", ...), not callbackPlayerSay. T5 SP dedicated disables the sound subsystem, cascading through the say-callback dispatch — callbackPlayerSay never fires.
  • SetTimerUp(N) only ticks when N == 0 on T5 SP. Non-zero seeds render "0:00" but don't advance. Late joiners see 0, not real elapsed; authoritative elapsed lives in level.match_start_time.
  • Dynamic text: use SetValue, not SetText. SetText allocates a config string per call; per-tick rebuilds overflow and take the server down. Composite strings like "87/160" are three elements.
  • NewClientHudElem(player), not NewHudElem(). NewHudElem is globally owned; in co-op every player's HUD draws on top of every other player's. Fall back to NewHudElem only if elements don't render at all (diagnostic).
  • Zombies namespace is WaW-derived (maps\_zombiemode_*), not BO2's maps\mp\zombies\_zm_*.
  • Check t5-gsc-utils source as well as its README. Current source includes http::request and jsonSerialize / jsonParse, in addition to file IO, console commands and MySQL. Telemetry requires a DLL built with these HTTP/JSON components; older builds may lack them. See HTTP source and JSON source.

Load-bearing decisions

  • Match / round timers anchor to first spawn / first observed round transition — never level init. Anchoring at init included the map-load
    • connect + intro window, producing "displayed 4:00 → frozen 7:00" drift. Many BO1 maps pre-set round_number = 1 at init, so the round watcher fires on transitions only and the timer row seeds on first spawn as a fallback.
  • Game-over trigger is level-scope, raced across three candidate notifies (end_game / game_ended / intermission) since BO1 maps are inconsistent. Per-player triggers do not work — self waittill("death") is intercepted by the zombiemode scripts before it reaches our scope, and polling self.health misses the zero-crossing (health is rewritten during the game-over sequence).
  • Bank writes DB-first, memory-second. Every mutation writes to the DB and only updates self.bank / self.score after the write confirms. A dead DB can never create phantom money. Deposits use INSERT ... ON DUPLICATE KEY UPDATE; withdrawals gate on WHERE balance >= ? so the DB itself blocks overdrafts under concurrent commands.
  • Bank command surface is command::add_sv (server console), not chat. SP-engine chat is unreliable and chat::register_command isn't available in t5-gsc-utils.

Current state / caveats

  • bank_load in tws_bank.gsc is a diagnostic stub: bare minimum to isolate what specifically kills the connect handshake. Do not restore the stripped getGuid / MySQL body until the stub passes join cleanly.
  • DB credentials in tws_db.gsc are hardcoded for the initial fleet test. Move to dvars (tws_db_host / tws_db_user / tws_db_password / tws_db_name) before this repo goes public — otherwise the fleet's DB password lives in source.

Module map

File Role Fires notifies Reads notifies
tws_common Shared config, HUD helpers, .help registry, spawn-handler registry, single connect listener + dispatcher — say
tws_db MariaDB pool config + reachability probe db_probe_done —
tws_hud Timer row, zombie count, health bar hud_round_changed, hud_match_started, hud_game_over (internal)
tws_bank Persistent bank + bank / deposit / withdraw commands — db_probe_done
tws_afk .afk / .back chat toggle, owns its [AFK] indicator — —
tws_join .join for spectators who have not played on this connection — say, end_game, game_ended, intermission
tws_lock Lobby g_password lock at milestone round (tws_lock_round, default 20) — hud_round_changed, hud_game_over
tws_telemetry Ordered JSON game start, round, 30-second heartbeat, and game end reports with full player snapshots telemetry_queued, telemetry_finished (internal) end_game, game_ended, intermission
tws_leaderboard Cached completed-match map record and all tied holders, privately on join — end_game, game_ended, intermission