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

5.0 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)

  • 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 and gets dispatched after spawned_player.
  • 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, spawn-handler registry, single connect listener + dispatcher — —
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