Remove T5 bank and database modules and standardize script names
This commit is contained in:
+18
-36
@@ -1,16 +1,19 @@
|
||||
# tws-t5-aio notes
|
||||
# TWS T5 script notes
|
||||
|
||||
Reference for the `tws_*.gsc` files in this repo. Platform quirks and
|
||||
Reference for the `tws_t5_*.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
|
||||
Copy all `tws_t5_*.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
|
||||
|
||||
For existing installations, follow the [upgrade cleanup](README.md#install--upgrade)
|
||||
before copying the renamed scripts.
|
||||
|
||||
## Platform quirks (T5 SP engine, Plutonium)
|
||||
|
||||
- **Initialize locals before loops when reading them afterwards.** T5 rejected
|
||||
@@ -18,9 +21,9 @@ Copy all `tws_*.gsc` to `storage/t5/scripts/sp/` on the Plutonium T5 server
|
||||
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
|
||||
- **One `level waittill("connected")` only.** `tws_t5_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
|
||||
through `tws_t5_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
|
||||
@@ -39,9 +42,9 @@ Copy all `tws_*.gsc` to `storage/t5/scripts/sp/` on the Plutonium T5 server
|
||||
- **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.
|
||||
includes `http::request` and `jsonSerialize` / `jsonParse`. Telemetry and
|
||||
leaderboard require a DLL built with these HTTP/JSON components; older
|
||||
builds may lack them.
|
||||
See [HTTP source](https://github.com/alicealys/t5-gsc-utils/blob/main/src/component/http.cpp)
|
||||
and [JSON source](https://github.com/alicealys/t5-gsc-utils/blob/main/src/component/json.cpp).
|
||||
|
||||
@@ -59,35 +62,14 @@ Copy all `tws_*.gsc` to `storage/t5/scripts/sp/` on the Plutonium T5 server
|
||||
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` |
|
||||
| `tws_t5_common` | Shared config, HUD helpers, `.help` registry, spawn-handler registry, single connect listener + dispatcher | — | `say` |
|
||||
| `tws_t5_hud` | Timer row, zombie count, health bar | `hud_round_changed`, `hud_match_started`, `hud_game_over` | (internal) |
|
||||
| `tws_t5_afk` | `.afk` / `.back` chat toggle, owns its [AFK] indicator | — | — |
|
||||
| `tws_t5_join` | `.join` for spectators who have not played on this connection | — | `say`, `end_game`, `game_ended`, `intermission` |
|
||||
| `tws_t5_lock` | Lobby `g_password` lock at milestone round (`tws_lock_round`, default 20) | — | `hud_round_changed`, `hud_game_over` |
|
||||
| `tws_t5_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_t5_leaderboard` | Cached completed-match map record and all tied holders, privately on join | — | `end_game`, `game_ended`, `intermission` |
|
||||
|
||||
+70
-134
@@ -1,9 +1,8 @@
|
||||
# tws-t5-aio
|
||||
# TWS T5 Zombies scripts
|
||||
|
||||
Custom HUD + persistent bank + AFK toggle + immediate join + lobby lock + game telemetry + map records for Plutonium T5
|
||||
(Black Ops 1) zombies dedicated servers. Split across nine `.gsc` files,
|
||||
each installable / removable in isolation (with `tws_common` as the shared
|
||||
hub).
|
||||
Custom HUD + AFK toggle + immediate join + lobby lock + game telemetry + map records for Plutonium T5
|
||||
(Black Ops 1) zombies dedicated servers. Split across seven `.gsc` files,
|
||||
with `tws_t5_common` as the shared hub. Lobby lock also requires the HUD module.
|
||||
|
||||
Platform quirks and deploy commands: [NOTES.md](NOTES.md).
|
||||
|
||||
@@ -11,19 +10,30 @@ Platform quirks and deploy commands: [NOTES.md](NOTES.md).
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| [tws_common.gsc](tws_common.gsc) | Shared config, HUD helpers, `.help`, connect/spawn registries, single `connected` listener + dispatcher |
|
||||
| [tws_db.gsc](tws_db.gsc) | MariaDB pool config + reachability probe |
|
||||
| [tws_hud.gsc](tws_hud.gsc) | Bottom-left HUD stack: timers, zombie count, health bar |
|
||||
| [tws_bank.gsc](tws_bank.gsc) | Persistent per-player bank + console commands |
|
||||
| [tws_afk.gsc](tws_afk.gsc) | `.afk` / `.back` chat toggle + `[AFK]` indicator |
|
||||
| [tws_join.gsc](tws_join.gsc) | `.join` lets newcomers spawn before the current round ends |
|
||||
| [tws_lock.gsc](tws_lock.gsc) | Lobby `g_password` lock at a milestone round |
|
||||
| [tws_telemetry.gsc](tws_telemetry.gsc) | Direct HTTP game start, round, heartbeat, and game end reports |
|
||||
| [tws_leaderboard.gsc](tws_leaderboard.gsc) | Private map high-round record and all tied holders on connection |
|
||||
| [tws_t5_common.gsc](tws_t5_common.gsc) | Shared config, HUD helpers, `.help`, connect/spawn registries, single `connected` listener + dispatcher |
|
||||
| [tws_t5_hud.gsc](tws_t5_hud.gsc) | Bottom-left HUD stack: timers, zombie count, health bar |
|
||||
| [tws_t5_afk.gsc](tws_t5_afk.gsc) | `.afk` / `.back` chat toggle + `[AFK]` indicator |
|
||||
| [tws_t5_join.gsc](tws_t5_join.gsc) | `.join` lets newcomers spawn before the current round ends |
|
||||
| [tws_t5_lock.gsc](tws_t5_lock.gsc) | Lobby `g_password` lock at a milestone round |
|
||||
| [tws_t5_telemetry.gsc](tws_t5_telemetry.gsc) | Direct HTTP game start, round, heartbeat, and game end reports |
|
||||
| [tws_t5_leaderboard.gsc](tws_t5_leaderboard.gsc) | Private map high-round record and all tied holders on connection |
|
||||
|
||||
## Install / upgrade
|
||||
|
||||
Copy `tws_t5_*.gsc` to `storage/t5/scripts/sp/`, then restart the map.
|
||||
When upgrading an existing installation, first remove these old scripts from
|
||||
that directory:
|
||||
|
||||
- `tws_bank.gsc` and `tws_db.gsc` (removed modules)
|
||||
- `tws_common.gsc`, `tws_hud.gsc`, `tws_afk.gsc`, `tws_join.gsc`,
|
||||
`tws_lock.gsc`, `tws_telemetry.gsc` and `tws_leaderboard.gsc` (renamed modules)
|
||||
|
||||
Do not leave both common scripts installed: duplicate connection listeners
|
||||
break T5's connect handshake. Existing dvar names are unchanged.
|
||||
|
||||
## Map record announcements
|
||||
|
||||
Copy `tws_leaderboard.gsc` and the updated `tws_common.gsc` to
|
||||
Copy `tws_t5_leaderboard.gsc` and the updated `tws_t5_common.gsc` to
|
||||
`storage/t5/scripts/sp/`, then restart the map. Leaderboard requires a
|
||||
[t5-gsc-utils](https://github.com/alicealys/t5-gsc-utils) build exposing
|
||||
`http::request`, `jsonParse`, `typeof` and `formatString`. A plugin upgrade
|
||||
@@ -31,7 +41,7 @@ requires a full server-process restart. To omit leaderboard, remove its script;
|
||||
the enable dvar does not bypass native linking dependencies.
|
||||
|
||||
Records are read from the public Electric Cherry API with no credentials and
|
||||
work independently of telemetry, HUD and the bank. Spectator newcomers receive
|
||||
work independently of telemetry and HUD. Spectator newcomers receive
|
||||
the same private announcement as playable joins. T5 matches its engine map to
|
||||
the API's map list. [Shared configuration, caching and validation](../README.md#map-record-announcements)
|
||||
apply to both games.
|
||||
@@ -52,62 +62,55 @@ counter and health display. Typing `.help` again restarts that display time.
|
||||
| `.join` | Join mid-round (newcomers only) |
|
||||
|
||||
Each module registers its own help entries; removing AFK or join also removes
|
||||
those entries from `.help` after a map restart. The bank's `bank`, `deposit`, and
|
||||
`withdraw` commands are server-console commands and are not listed in chat help.
|
||||
those entries from `.help` after a map restart.
|
||||
|
||||
## Dependency graph
|
||||
|
||||
Arrows read "depends on" — solid means the source names the target with
|
||||
`scripts\sp\tws_common::...`, dashed means the source waits on a level
|
||||
notify fired by the target. Transitive edges are elided (so `tws_bank`
|
||||
and `tws_lock` reach `tws_common` through `tws_db` / `tws_hud` on the
|
||||
graph, but they also call `tws_common` directly).
|
||||
`scripts\sp\tws_t5_common::...`, dashed means the source waits on a level
|
||||
notify fired by the target.
|
||||
|
||||
```mermaid
|
||||
graph BT
|
||||
common[tws_common<br/><i>config + helpers + dispatcher</i>]
|
||||
common[tws_t5_common<br/><i>config + helpers + dispatcher</i>]
|
||||
|
||||
db[tws_db]
|
||||
hud[tws_hud]
|
||||
afk[tws_afk]
|
||||
join[tws_join]
|
||||
bank[tws_bank]
|
||||
lock[tws_lock]
|
||||
telemetry[tws_telemetry]
|
||||
leaderboard[tws_leaderboard]
|
||||
hud[tws_t5_hud]
|
||||
afk[tws_t5_afk]
|
||||
join[tws_t5_join]
|
||||
lock[tws_t5_lock]
|
||||
telemetry[tws_t5_telemetry]
|
||||
leaderboard[tws_t5_leaderboard]
|
||||
|
||||
db --> common
|
||||
hud --> common
|
||||
afk --> common
|
||||
join --> common
|
||||
lock --> common
|
||||
telemetry --> common
|
||||
leaderboard --> common
|
||||
|
||||
bank -. db_probe_done .-> db
|
||||
lock -. hud_round_changed<br/>hud_game_over .-> hud
|
||||
```
|
||||
|
||||
- `tws_common` is the only module named by other files at compile time.
|
||||
- `tws_t5_common` is the only module named by other files at compile time.
|
||||
- All other cross-module coupling flows through level notifies
|
||||
(`db_probe_done`, `hud_round_changed`, `hud_match_started`,
|
||||
(`hud_round_changed`, `hud_match_started`,
|
||||
`hud_game_over`) or through spawn handlers registered with
|
||||
`tws_common::register_spawn_handler` / `register_connect_handler`.
|
||||
- Any file except `tws_common` can be removed; the rest still load.
|
||||
`tws_afk` has no downstream consumers — pull it independently.
|
||||
`tws_bank` needs `tws_db`; `tws_lock` needs `tws_hud`.
|
||||
`tws_t5_common::register_spawn_handler` / `register_connect_handler`.
|
||||
- Any file except `tws_t5_common` can be removed; the rest still load.
|
||||
`tws_t5_afk` has no downstream consumers — pull it independently.
|
||||
`tws_t5_lock` needs `tws_t5_hud` to receive round and game-over notifications.
|
||||
|
||||
## Runtime notifies
|
||||
|
||||
| Notify | Fired by | Read by |
|
||||
|---|---|---|
|
||||
| `db_probe_done` | `tws_db` | `tws_bank` (via `bank_deferred_start`) |
|
||||
| `hud_round_changed` | `tws_hud` | `tws_hud` (round-timer reset), `tws_lock` |
|
||||
| `hud_match_started` | `tws_hud` | `tws_hud` (match-timer reveal) |
|
||||
| `hud_game_over` | `tws_hud` | `tws_hud` (freeze timers), `tws_lock` (clear password) |
|
||||
| `hud_round_changed` | `tws_t5_hud` | `tws_t5_hud` (round-timer reset), `tws_t5_lock` |
|
||||
| `hud_match_started` | `tws_t5_hud` | `tws_t5_hud` (match-timer reveal) |
|
||||
| `hud_game_over` | `tws_t5_hud` | `tws_t5_hud` (freeze timers), `tws_t5_lock` (clear password) |
|
||||
|
||||
---
|
||||
|
||||
## tws_common.gsc
|
||||
## tws_t5_common.gsc
|
||||
|
||||
Hub file. Shared config, HUD helpers, spawn-handler registry, and the
|
||||
single `level waittill("connected")` in the fleet. Adding a second
|
||||
@@ -153,31 +156,7 @@ connect listener anywhere else crashes the T5 SP handshake.
|
||||
|
||||
---
|
||||
|
||||
## tws_db.gsc
|
||||
|
||||
**Features**
|
||||
- One MariaDB connection pool for the whole script (used by bank now,
|
||||
leaderboard later)
|
||||
- Reachability probe: round-trips `SELECT 1` and flips `level.db_online`
|
||||
- Fires `db_probe_done` so waiters can proceed regardless of outcome
|
||||
|
||||
**Provides**
|
||||
| Level var / notify | Meaning |
|
||||
|---|---|
|
||||
| `level.db_online` | `true` iff the probe query returned without error |
|
||||
| `level.db_probe_done` | `true` once the probe has completed (either way) |
|
||||
| notify `db_probe_done` | Fired once after probe completion |
|
||||
|
||||
**Depends on**
|
||||
- `scripts\sp\tws_common::ensure_config()`
|
||||
- `t5-gsc-utils` (`mysql::set_config`, `mysql::query`)
|
||||
|
||||
**Config (currently hardcoded — TODO: dvarize before repo goes public)**
|
||||
- Host `mariadb`, port `3306`, DB `tws_zm`, user `josh`, password `joshster`
|
||||
|
||||
---
|
||||
|
||||
## tws_hud.gsc
|
||||
## tws_t5_hud.gsc
|
||||
|
||||
Bottom-left cluster. Per-player elements spawn via `::hud_start`.
|
||||
|
||||
@@ -201,56 +180,17 @@ Spawn handler registered: `::hud_start` — threads `hud_timer_row`,
|
||||
`hud_zombie_counter`, `hud_health_display`.
|
||||
|
||||
**Depends on**
|
||||
- `scripts\sp\tws_common::` — `ensure_config`, `make_text_elem`,
|
||||
- `scripts\sp\tws_t5_common::` — `ensure_config`, `make_text_elem`,
|
||||
`make_shader_elem`, `destroy_on_disconnect`, `format_mmss`,
|
||||
`register_spawn_handler`
|
||||
- Every `level.hud_*` config value from `tws_common`
|
||||
- Every `level.hud_*` config value from `tws_t5_common`
|
||||
- Stock BO1 state: `level.round_number`, `level.zombie_total`,
|
||||
`level.players`, `self.health`, `self.maxhealth`, `self.name` /
|
||||
`self.playername`, AI entities' `.animname` and `.ignore_enemy_count`
|
||||
|
||||
---
|
||||
|
||||
## tws_bank.gsc
|
||||
|
||||
Persistent per-player bank. Balances survive server hops within the fleet
|
||||
because rows are keyed on XUID.
|
||||
|
||||
**Features**
|
||||
- Server-console commands: `bank`, `deposit <amount>`, `withdraw <amount>`
|
||||
- DB-first / memory-second: `self.bank` and `self.score` only move after
|
||||
the DB write confirms
|
||||
- Deposits: `INSERT ... ON DUPLICATE KEY UPDATE` — lazy row create, atomic
|
||||
- Withdrawals: `WHERE balance >= ?` — DB blocks overdrafts under concurrency
|
||||
- Score-drift refund guard on deposit
|
||||
- `bank_load` currently a **diagnostic stub** (bare-minimum to isolate the
|
||||
connect-handshake crash — do not restore the stripped body until it passes
|
||||
join)
|
||||
|
||||
**Provides**
|
||||
| Command | Args | Effect |
|
||||
|---|---|---|
|
||||
| `bank` | — | Prints current `Bank` and `Score` to the caller |
|
||||
| `deposit` | `<amount>` | Score → bank, DB-first with refund on race |
|
||||
| `withdraw` | `<amount>` | Bank → score, DB-first with overdraft guard |
|
||||
|
||||
Per-player state: `self.bank` (int), `self.bank_unavailable` (bool),
|
||||
`self.bank_guid` (set in the full impl — currently unset by the stub).
|
||||
|
||||
**Depends on**
|
||||
- `scripts\sp\tws_common::` — `ensure_config`, `register_spawn_handler`
|
||||
- `tws_db` — waits on `db_probe_done`, gates on `level.db_online`
|
||||
- `t5-gsc-utils` — `mysql::query`, `mysql::prepared_statement`,
|
||||
`command::add_sv`
|
||||
- Stock BO1: `self.score`
|
||||
- Dvar: `tws_server_id` (optional; labels `last_server` on bank rows)
|
||||
- External: MariaDB schema — `bank(guid, balance, last_name, last_server)`
|
||||
|
||||
Spawn handler registered: `::bank_load`.
|
||||
|
||||
---
|
||||
|
||||
## tws_afk.gsc
|
||||
## tws_t5_afk.gsc
|
||||
|
||||
Self-invoked pause mode. Owns the `[AFK]` indicator element entirely — HUD
|
||||
module has zero knowledge of AFK.
|
||||
@@ -271,7 +211,7 @@ module has zero knowledge of AFK.
|
||||
- Level var: `level.afk_grace_seconds` (default 2)
|
||||
|
||||
**Depends on**
|
||||
- `scripts\sp\tws_common::` — `ensure_config`, `make_text_elem`,
|
||||
- `scripts\sp\tws_t5_common::` — `ensure_config`, `make_text_elem`,
|
||||
`destroy_on_disconnect`, `register_spawn_handler`, `register_help_command`
|
||||
- Shared config: `level.hud_x`, `level.hud_row_match`,
|
||||
`level.hud_font_small`, `level.hud_c_afk`
|
||||
@@ -282,10 +222,10 @@ Spawn handler registered: `::afk_spawn`.
|
||||
|
||||
---
|
||||
|
||||
## tws_join.gsc
|
||||
## tws_t5_join.gsc
|
||||
|
||||
Type `.join` in chat while spectating after joining a match in progress to
|
||||
spawn immediately. Install with `tws_common.gsc`; no HUD or DB dependency.
|
||||
spawn immediately. Install with `tws_t5_common.gsc`; no HUD dependency.
|
||||
|
||||
**Eligibility**
|
||||
|
||||
@@ -323,7 +263,7 @@ and [spawn entry point](https://github.com/plutoniummod/t5-scripts/blob/main/ZM/
|
||||
|
||||
---
|
||||
|
||||
## tws_lock.gsc
|
||||
## tws_t5_lock.gsc
|
||||
|
||||
**Features**
|
||||
- Sets `g_password` to a random per-lobby value when the round crosses a
|
||||
@@ -339,8 +279,8 @@ and [spawn entry point](https://github.com/plutoniummod/t5-scripts/blob/main/ZM/
|
||||
| `level.lock_active` | `true` after the password has been set |
|
||||
|
||||
**Depends on**
|
||||
- `scripts\sp\tws_common::` — `ensure_config`, `int_dvar_or`
|
||||
- `tws_hud` — waits on `hud_round_changed` and `hud_game_over`
|
||||
- `scripts\sp\tws_t5_common::` — `ensure_config`, `int_dvar_or`
|
||||
- `tws_t5_hud` — waits on `hud_round_changed` and `hud_game_over`
|
||||
- Stock BO1: `level.round_number`
|
||||
- Dvar: `tws_lock_round` (int, default `20`)
|
||||
|
||||
@@ -351,17 +291,17 @@ and [spawn entry point](https://github.com/plutoniummod/t5-scripts/blob/main/ZM/
|
||||
| Dvar | Consumer | Default | Purpose |
|
||||
|---|---|---|---|
|
||||
| `zombiemode` | every module | — | Gate: every `init()` returns early unless `"1"` |
|
||||
| `tws_lock_round` | `tws_lock` | `20` | Round at which the lobby locks |
|
||||
| `tws_server_id` | `tws_bank`, `tws_telemetry` | Required for telemetry | Exact registered Electric Cherry server name; also used as the bank label |
|
||||
| `tws_telemetry_enabled` | `tws_telemetry` | `1` | Set to `0` to disable telemetry at init |
|
||||
| `tws_telemetry_url` | `tws_telemetry` | `https://ec.thewrightserver.net/api/telemetry` | Electric Cherry telemetry endpoint for JSON POSTs |
|
||||
| `tws_telemetry_log_level` | `tws_telemetry` | `1` | Read live: `0` warnings/errors/recovery only, `1` lifecycle/request/health logs, `2` also capture/queue logs and response previews |
|
||||
| `tws_lock_round` | `tws_t5_lock` | `20` | Round at which the lobby locks |
|
||||
| `tws_server_id` | `tws_t5_telemetry` | Required for telemetry | Exact registered Electric Cherry server name |
|
||||
| `tws_telemetry_enabled` | `tws_t5_telemetry` | `1` | Set to `0` to disable telemetry at init |
|
||||
| `tws_telemetry_url` | `tws_t5_telemetry` | `https://ec.thewrightserver.net/api/telemetry` | Electric Cherry telemetry endpoint for JSON POSTs |
|
||||
| `tws_telemetry_log_level` | `tws_t5_telemetry` | `1` | Read live: `0` warnings/errors/recovery only, `1` lifecycle/request/health logs, `2` also capture/queue logs and response previews |
|
||||
|
||||
## tws_telemetry.gsc
|
||||
## tws_t5_telemetry.gsc
|
||||
|
||||
Uses `t5-gsc-utils` HTTP/JSON components to POST directly to Electric Cherry's
|
||||
`/api/telemetry`. Install alongside `tws_common.gsc` in `storage/t5/scripts/sp/`.
|
||||
No HUD or database dependency. Reports run whether or not a beta is active.
|
||||
`/api/telemetry`. Install alongside `tws_t5_common.gsc` in `storage/t5/scripts/sp/`.
|
||||
No HUD dependency. Reports run whether or not a beta is active.
|
||||
Follow the shared [authentication setup](../README.md#telemetry-authentication-t5-and-t6)
|
||||
to configure the service before upgrading. The reporter token is embedded in
|
||||
`level.telemetry_token`; it must match the service's `EC_TELEMETRY_TOKEN`. Short
|
||||
@@ -503,7 +443,7 @@ and [score tracking](https://github.com/plutoniummod/t5-scripts/blob/main/ZM/Com
|
||||
4. Delay HTTP completion while rounds advance and the match ends. Verify
|
||||
requests remain ordered and retain the stats captured at each event.
|
||||
With the API unreachable, verify transport-error logging and continued
|
||||
gameplay. Repeat without an active beta and with HUD/DB modules removed.
|
||||
gameplay. Repeat without an active beta and with the HUD module removed.
|
||||
5. Stay in one round for over a minute. Verify heartbeats at 30 and 60 seconds
|
||||
after start, with current stats and the same fields as `round_change`.
|
||||
Check that round changes and joins do not reset or duplicate the interval,
|
||||
@@ -522,11 +462,7 @@ and [score tracking](https://github.com/plutoniummod/t5-scripts/blob/main/ZM/Com
|
||||
|
||||
## External dependencies
|
||||
|
||||
- **[t5-gsc-utils](https://github.com/alicealys/t5-gsc-utils)** — required.
|
||||
`tws_db` and `tws_bank` need the `mysql::` namespace; `tws_bank` also
|
||||
needs `command::add_sv`.
|
||||
- **MariaDB / MySQL server** reachable from the Plutonium container as
|
||||
`mariadb:3306` (currently hardcoded — see `tws_db.gsc`).
|
||||
- **Schema** — `bank(guid VARCHAR PRIMARY KEY, balance INT, last_name
|
||||
VARCHAR, last_server VARCHAR)`. `tws_bank` lazily inserts rows on first
|
||||
deposit.
|
||||
[t5-gsc-utils](https://github.com/alicealys/t5-gsc-utils) is required for telemetry
|
||||
and leaderboard HTTP, JSON, type and string helpers. Install a build exposing
|
||||
the natives listed in each module's documentation, then restart the server
|
||||
process. No database is required.
|
||||
|
||||
-229
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
tws_bank.gsc — persistent per-player bank, MariaDB-backed. See NOTES.md
|
||||
for the DB-first / spawn-dispatch / command surface invariants.
|
||||
*/
|
||||
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
init()
|
||||
{
|
||||
if (GetDvar(#"zombiemode") != "1")
|
||||
return;
|
||||
|
||||
scripts\sp\tws_common::ensure_config();
|
||||
|
||||
bank_init();
|
||||
|
||||
scripts\sp\tws_common::register_spawn_handler(::bank_load);
|
||||
}
|
||||
|
||||
bank_init()
|
||||
{
|
||||
if (!isDefined(level.db_probe_done) || !level.db_probe_done)
|
||||
level thread bank_deferred_start();
|
||||
else
|
||||
bank_start();
|
||||
}
|
||||
|
||||
bank_deferred_start()
|
||||
{
|
||||
level waittill("db_probe_done");
|
||||
bank_start();
|
||||
}
|
||||
|
||||
bank_start()
|
||||
{
|
||||
if (!level.db_online)
|
||||
return;
|
||||
|
||||
bank_register_commands();
|
||||
}
|
||||
|
||||
bank_register_commands()
|
||||
{
|
||||
command::add_sv("bank", ::bank_cmd_bank);
|
||||
command::add_sv("deposit", ::bank_cmd_deposit);
|
||||
command::add_sv("withdraw", ::bank_cmd_withdraw);
|
||||
}
|
||||
|
||||
// DIAGNOSTIC STUB — bare minimum to isolate the connect-handshake crash.
|
||||
// Do not restore the getGuid / mysql body until this passes join.
|
||||
bank_load()
|
||||
{
|
||||
self endon("disconnect");
|
||||
self iPrintLnBold("^2bank_load: entered");
|
||||
self.bank = 0;
|
||||
self.bank_unavailable = false;
|
||||
self iPrintLnBold("^2bank_load: done");
|
||||
}
|
||||
|
||||
bank_available(player)
|
||||
{
|
||||
if (!level.db_online)
|
||||
{
|
||||
player iPrintLnBold("^1Bank offline");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_true(player.bank_unavailable))
|
||||
{
|
||||
player iPrintLnBold("^1Bank unavailable for your account");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!isDefined(player.bank))
|
||||
{
|
||||
player iPrintLnBold("^3Bank still loading, try again");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bank_cmd_bank(args)
|
||||
{
|
||||
if (!bank_available(self))
|
||||
return;
|
||||
|
||||
self iPrintLnBold("Bank: " + self.bank + " Score: " + self.score);
|
||||
}
|
||||
|
||||
bank_cmd_deposit(args)
|
||||
{
|
||||
if (!bank_available(self))
|
||||
return;
|
||||
|
||||
if (args.size < 2)
|
||||
{
|
||||
self iPrintLnBold("Usage: deposit <amount>");
|
||||
return;
|
||||
}
|
||||
|
||||
amount = int(args[1]);
|
||||
|
||||
if (amount <= 0)
|
||||
{
|
||||
self iPrintLnBold("^1Amount must be positive");
|
||||
return;
|
||||
}
|
||||
|
||||
if (amount > self.score)
|
||||
{
|
||||
self iPrintLnBold("^1Not enough score");
|
||||
return;
|
||||
}
|
||||
|
||||
self thread bank_deposit_write(amount);
|
||||
}
|
||||
|
||||
bank_cmd_withdraw(args)
|
||||
{
|
||||
if (!bank_available(self))
|
||||
return;
|
||||
|
||||
if (args.size < 2)
|
||||
{
|
||||
self iPrintLnBold("Usage: withdraw <amount>");
|
||||
return;
|
||||
}
|
||||
|
||||
amount = int(args[1]);
|
||||
|
||||
if (amount <= 0)
|
||||
{
|
||||
self iPrintLnBold("^1Amount must be positive");
|
||||
return;
|
||||
}
|
||||
|
||||
if (amount > self.bank)
|
||||
{
|
||||
self iPrintLnBold("^1Insufficient balance");
|
||||
return;
|
||||
}
|
||||
|
||||
self thread bank_withdraw_write(amount);
|
||||
}
|
||||
|
||||
// upsert: first deposit creates the row, later ones increment
|
||||
bank_deposit_write(amount)
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
name = bank_display_name(self);
|
||||
server_id = bank_server_id();
|
||||
|
||||
q = mysql::prepared_statement(
|
||||
"INSERT INTO bank (guid, balance, last_name, last_server) VALUES (?, ?, ?, ?) " +
|
||||
"ON DUPLICATE KEY UPDATE balance = balance + VALUES(balance), " +
|
||||
"last_name = VALUES(last_name), last_server = VALUES(last_server)",
|
||||
self.bank_guid, amount, name, server_id);
|
||||
|
||||
q waittill("done", result, affected_rows, error);
|
||||
|
||||
if (isDefined(error) && error != "")
|
||||
{
|
||||
self iPrintLnBold("^1Deposit failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// score can change between dispatch and write completing — refund if so
|
||||
if (amount > self.score)
|
||||
{
|
||||
mysql::prepared_statement(
|
||||
"UPDATE bank SET balance = balance - ? WHERE guid = ?",
|
||||
amount, self.bank_guid);
|
||||
self iPrintLnBold("^1Deposit rolled back (score changed)");
|
||||
return;
|
||||
}
|
||||
|
||||
self.score -= amount;
|
||||
self.bank += amount;
|
||||
self iPrintLnBold("Deposited " + amount + " Bank: " + self.bank);
|
||||
}
|
||||
|
||||
// balance guard lives in the WHERE so concurrent commands can't overdraw
|
||||
bank_withdraw_write(amount)
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
q = mysql::prepared_statement(
|
||||
"UPDATE bank SET balance = balance - ? WHERE guid = ? AND balance >= ?",
|
||||
amount, self.bank_guid, amount);
|
||||
|
||||
q waittill("done", result, affected_rows, error);
|
||||
|
||||
if (isDefined(error) && error != "")
|
||||
{
|
||||
self iPrintLnBold("^1Withdraw failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isDefined(affected_rows) || affected_rows == 0)
|
||||
{
|
||||
self iPrintLnBold("^1Insufficient balance");
|
||||
self thread bank_load(); // re-sync in case memory drifted from DB
|
||||
return;
|
||||
}
|
||||
|
||||
self.score += amount;
|
||||
self.bank -= amount;
|
||||
self iPrintLnBold("Withdrew " + amount + " Bank: " + self.bank);
|
||||
}
|
||||
|
||||
bank_display_name(player)
|
||||
{
|
||||
if (isDefined(player.name))
|
||||
return player.name;
|
||||
if (isDefined(player.playername))
|
||||
return player.playername;
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
bank_server_id()
|
||||
{
|
||||
id = GetDvar("tws_server_id");
|
||||
if (id == "")
|
||||
return "unknown";
|
||||
return id;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/* tws_db.gsc — MariaDB pool + reachability probe. Fires db_probe_done. */
|
||||
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
init()
|
||||
{
|
||||
if (GetDvar(#"zombiemode") != "1")
|
||||
return;
|
||||
|
||||
scripts\sp\tws_common::ensure_config();
|
||||
|
||||
db_init();
|
||||
}
|
||||
|
||||
// TODO: move creds to dvars before this repo goes public
|
||||
db_init()
|
||||
{
|
||||
level.db_online = false;
|
||||
level.db_probe_done = false;
|
||||
|
||||
cfg = spawnStruct();
|
||||
cfg.host = "mariadb";
|
||||
cfg.user = "josh";
|
||||
cfg.password = "joshster";
|
||||
cfg.port = 3306;
|
||||
cfg.database = "tws_zm";
|
||||
|
||||
mysql::set_config(cfg);
|
||||
|
||||
level thread db_probe();
|
||||
}
|
||||
|
||||
// set_config is silent on failure; only a real query surfaces the error
|
||||
db_probe()
|
||||
{
|
||||
q = mysql::query("SELECT 1 AS ok");
|
||||
q waittill("done", result, affected_rows, error);
|
||||
|
||||
if (isDefined(error) && error != "")
|
||||
level.db_online = false;
|
||||
else
|
||||
level.db_online = true;
|
||||
|
||||
level.db_probe_done = true;
|
||||
level notify("db_probe_done");
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
tws_afk.gsc — .afk / .back chat toggle. Owns the [AFK] indicator element.
|
||||
tws_t5_afk.gsc — .afk / .back chat toggle. Owns the [AFK] indicator element.
|
||||
Chat uses level waittill("say") — callbackPlayerSay never fires on T5 SP
|
||||
dedicated (see NOTES.md).
|
||||
*/
|
||||
@@ -12,13 +12,13 @@ init()
|
||||
if (GetDvar(#"zombiemode") != "1")
|
||||
return;
|
||||
|
||||
scripts\sp\tws_common::ensure_config();
|
||||
scripts\sp\tws_common::register_help_command(".afk", "Pause with protection");
|
||||
scripts\sp\tws_common::register_help_command(".back", "Return from AFK");
|
||||
scripts\sp\tws_t5_common::ensure_config();
|
||||
scripts\sp\tws_t5_common::register_help_command(".afk", "Pause with protection");
|
||||
scripts\sp\tws_t5_common::register_help_command(".back", "Return from AFK");
|
||||
|
||||
afk_init();
|
||||
|
||||
scripts\sp\tws_common::register_spawn_handler(::afk_spawn);
|
||||
scripts\sp\tws_t5_common::register_spawn_handler(::afk_spawn);
|
||||
}
|
||||
|
||||
afk_init()
|
||||
@@ -50,7 +50,7 @@ afk_spawn()
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
afk = scripts\sp\tws_common::make_text_elem(
|
||||
afk = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_x + 42, level.hud_row_match,
|
||||
"left", level.hud_font_small, level.hud_c_afk);
|
||||
afk SetText("[AFK]");
|
||||
@@ -59,7 +59,7 @@ afk_spawn()
|
||||
|
||||
elems = [];
|
||||
elems[elems.size] = afk;
|
||||
self thread scripts\sp\tws_common::destroy_on_disconnect(elems);
|
||||
self thread scripts\sp\tws_t5_common::destroy_on_disconnect(elems);
|
||||
}
|
||||
|
||||
afk_enter()
|
||||
@@ -1,4 +1,4 @@
|
||||
/* tws_common.gsc — shared config, HUD helpers, connect/spawn/help registries. */
|
||||
/* tws_t5_common.gsc — shared config, HUD helpers, connect/spawn/help registries. */
|
||||
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
@@ -1,4 +1,4 @@
|
||||
/* tws_hud.gsc — bottom-left HUD stack. Timer / zombie count / health bar. */
|
||||
/* tws_t5_hud.gsc — bottom-left HUD stack. Timer / zombie count / health bar. */
|
||||
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
@@ -8,12 +8,12 @@ init()
|
||||
if (GetDvar(#"zombiemode") != "1")
|
||||
return;
|
||||
|
||||
scripts\sp\tws_common::ensure_config();
|
||||
scripts\sp\tws_t5_common::ensure_config();
|
||||
|
||||
level thread round_watcher();
|
||||
level thread game_over_watcher();
|
||||
|
||||
scripts\sp\tws_common::register_spawn_handler(::hud_start);
|
||||
scripts\sp\tws_t5_common::register_spawn_handler(::hud_start);
|
||||
}
|
||||
|
||||
hud_start()
|
||||
@@ -87,18 +87,18 @@ hud_timer_row()
|
||||
level notify("hud_match_started");
|
||||
}
|
||||
|
||||
match = scripts\sp\tws_common::make_text_elem(
|
||||
match = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_x, level.hud_row_match,
|
||||
"left", level.hud_font_small, level.hud_c_dim);
|
||||
match.alpha = 0; // revealed by match_timer_bind when round 1 opens
|
||||
|
||||
round = scripts\sp\tws_common::make_text_elem(
|
||||
round = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_x, level.hud_row_round,
|
||||
"left", level.hud_font_small, level.hud_c_dim);
|
||||
round SetTimerUp(0);
|
||||
|
||||
// name only shows in co-op — your own name is noise in solo
|
||||
name = scripts\sp\tws_common::make_text_elem(
|
||||
name = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_x, level.hud_row_name,
|
||||
"left", level.hud_font_small, level.hud_c_name);
|
||||
|
||||
@@ -113,7 +113,7 @@ hud_timer_row()
|
||||
elems[elems.size] = match;
|
||||
elems[elems.size] = round;
|
||||
elems[elems.size] = name;
|
||||
self thread scripts\sp\tws_common::destroy_on_disconnect(elems);
|
||||
self thread scripts\sp\tws_t5_common::destroy_on_disconnect(elems);
|
||||
|
||||
self thread reset_timer_each_round(round);
|
||||
self thread match_timer_bind(match);
|
||||
@@ -177,22 +177,22 @@ freeze_timers_on_game_over(match_elem, round_elem)
|
||||
level waittill("hud_game_over");
|
||||
|
||||
if (isDefined(match_elem) && isDefined(level.match_start_time))
|
||||
match_elem SetText(scripts\sp\tws_common::format_mmss(getTime() - level.match_start_time));
|
||||
match_elem SetText(scripts\sp\tws_t5_common::format_mmss(getTime() - level.match_start_time));
|
||||
|
||||
if (isDefined(round_elem) && isDefined(level.round_start_time))
|
||||
round_elem SetText(scripts\sp\tws_common::format_mmss(getTime() - level.round_start_time));
|
||||
round_elem SetText(scripts\sp\tws_t5_common::format_mmss(getTime() - level.round_start_time));
|
||||
}
|
||||
|
||||
hud_zombie_counter()
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
label = scripts\sp\tws_common::make_text_elem(
|
||||
label = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_x, level.hud_row_count,
|
||||
"left", level.hud_font_large, level.hud_c_label);
|
||||
label SetText("Zombies");
|
||||
|
||||
count = scripts\sp\tws_common::make_text_elem(
|
||||
count = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_col_count, level.hud_row_count,
|
||||
"left", level.hud_font_large, level.hud_c_count);
|
||||
count SetValue(0);
|
||||
@@ -200,7 +200,7 @@ hud_zombie_counter()
|
||||
elems = [];
|
||||
elems[elems.size] = label;
|
||||
elems[elems.size] = count;
|
||||
self thread scripts\sp\tws_common::destroy_on_disconnect(elems);
|
||||
self thread scripts\sp\tws_t5_common::destroy_on_disconnect(elems);
|
||||
|
||||
last = -1;
|
||||
|
||||
@@ -245,12 +245,12 @@ hud_health_display()
|
||||
bar_width = level.hud_bar_width;
|
||||
|
||||
// -2 on both axes so the back frames the bar with 2px padding
|
||||
back = scripts\sp\tws_common::make_shader_elem(self, level.hud_x - 2, level.hud_row_bar - 2);
|
||||
back = scripts\sp\tws_t5_common::make_shader_elem(self, level.hud_x - 2, level.hud_row_bar - 2);
|
||||
back.alpha = 0.5;
|
||||
back.color = (0, 0, 0);
|
||||
back SetShader("black", bar_width + 4, level.hud_bar_height + 4);
|
||||
|
||||
bar = scripts\sp\tws_common::make_shader_elem(self, level.hud_x, level.hud_row_bar);
|
||||
bar = scripts\sp\tws_t5_common::make_shader_elem(self, level.hud_x, level.hud_row_bar);
|
||||
bar.color = level.hud_c_high;
|
||||
bar SetShader("white", bar_width, level.hud_bar_height);
|
||||
|
||||
@@ -260,17 +260,17 @@ hud_health_display()
|
||||
cur is right-aligned so digits grow leftward and the slash + max
|
||||
never shift.
|
||||
*/
|
||||
cur = scripts\sp\tws_common::make_text_elem(
|
||||
cur = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_col_health + 26, level.hud_row_bar + 3,
|
||||
"right", level.hud_font_mid, level.hud_c_high);
|
||||
cur SetValue(self.health);
|
||||
|
||||
slash = scripts\sp\tws_common::make_text_elem(
|
||||
slash = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_col_health + 30, level.hud_row_bar + 3,
|
||||
"center", level.hud_font_mid, level.hud_c_high);
|
||||
slash SetText("/");
|
||||
|
||||
max_hp = scripts\sp\tws_common::make_text_elem(
|
||||
max_hp = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_col_health + 34, level.hud_row_bar + 3,
|
||||
"left", level.hud_font_mid, level.hud_c_high);
|
||||
max_hp SetValue(self.maxhealth);
|
||||
@@ -285,7 +285,7 @@ hud_health_display()
|
||||
elems[elems.size] = cur;
|
||||
elems[elems.size] = slash;
|
||||
elems[elems.size] = max_hp;
|
||||
self thread scripts\sp\tws_common::destroy_on_disconnect(elems);
|
||||
self thread scripts\sp\tws_t5_common::destroy_on_disconnect(elems);
|
||||
|
||||
last_width = bar_width;
|
||||
last_health = -1;
|
||||
@@ -1,4 +1,4 @@
|
||||
/* tws_join.gsc - .join lets a newcomer leave spectator mode before round end. */
|
||||
/* tws_t5_join.gsc - .join lets a newcomer leave spectator mode before round end. */
|
||||
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
@@ -8,9 +8,9 @@ init()
|
||||
if (GetDvar(#"zombiemode") != "1")
|
||||
return;
|
||||
|
||||
scripts\sp\tws_common::ensure_config();
|
||||
scripts\sp\tws_common::register_help_command(".join", "Join mid-round (newcomers only)");
|
||||
scripts\sp\tws_common::register_spawn_handler(::join_spawn);
|
||||
scripts\sp\tws_t5_common::ensure_config();
|
||||
scripts\sp\tws_t5_common::register_help_command(".join", "Join mid-round (newcomers only)");
|
||||
scripts\sp\tws_t5_common::register_spawn_handler(::join_spawn);
|
||||
|
||||
level thread join_chat_listener();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* tws_leaderboard.gsc - private map record announcement, once per connection. */
|
||||
/* tws_t5_leaderboard.gsc - private map record announcement, once per connection. */
|
||||
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
@@ -24,7 +24,7 @@ init()
|
||||
level.tws_lb_pending = undefined;
|
||||
level.tws_lb_cache = undefined;
|
||||
level.tws_lb_attempt = 0;
|
||||
scripts\sp\tws_common::register_connect_handler(::lb_welcome);
|
||||
scripts\sp\tws_t5_common::register_connect_handler(::lb_welcome);
|
||||
level thread lb_worker();
|
||||
}
|
||||
|
||||
@@ -99,11 +99,11 @@ lb_show_hud(snapshot)
|
||||
self endon("disconnect");
|
||||
self endon("tws_lb_hud_done");
|
||||
|
||||
scripts\sp\tws_common::ensure_config();
|
||||
scripts\sp\tws_t5_common::ensure_config();
|
||||
// Match .help's position, typography and row spacing below the health bar.
|
||||
y = level.hud_row_bar + level.hud_bar_height + 20;
|
||||
elems = [];
|
||||
title = scripts\sp\tws_common::make_text_elem(
|
||||
title = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_x, y, "left", level.hud_font_mid, level.hud_c_afk);
|
||||
title.alpha = 0;
|
||||
if (snapshot.round == 0)
|
||||
@@ -114,7 +114,7 @@ lb_show_hud(snapshot)
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
row = scripts\sp\tws_common::make_text_elem(
|
||||
row = scripts\sp\tws_t5_common::make_text_elem(
|
||||
self, level.hud_x, y + 22 + i * 18,
|
||||
"left", level.hud_font_small, level.hud_c_count);
|
||||
row.alpha = 0;
|
||||
@@ -122,7 +122,7 @@ lb_show_hud(snapshot)
|
||||
}
|
||||
|
||||
// Cleanup runs independently of the welcome thread's endon handlers.
|
||||
self thread scripts\sp\tws_common::destroy_on_disconnect(elems);
|
||||
self thread scripts\sp\tws_t5_common::destroy_on_disconnect(elems);
|
||||
self thread lb_hud_end_game(elems, "end_game");
|
||||
self thread lb_hud_end_game(elems, "game_ended");
|
||||
self thread lb_hud_end_game(elems, "intermission");
|
||||
@@ -303,7 +303,7 @@ lb_collect(request, pending)
|
||||
|
||||
lb_log(message)
|
||||
{
|
||||
print("[tws_leaderboard] " + message);
|
||||
print("[tws_t5_leaderboard] " + message);
|
||||
}
|
||||
|
||||
// Pure data helpers below are exercised by tools/check_leaderboard.mjs.
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
tws_lock.gsc — lobby g_password lock at milestone round. Existing players
|
||||
tws_t5_lock.gsc — lobby g_password lock at milestone round. Existing players
|
||||
are unaffected; g_password is only checked at connect. Cleared on
|
||||
hud_game_over so the next lobby opens unlocked.
|
||||
*/
|
||||
@@ -12,14 +12,14 @@ init()
|
||||
if (GetDvar(#"zombiemode") != "1")
|
||||
return;
|
||||
|
||||
scripts\sp\tws_common::ensure_config();
|
||||
scripts\sp\tws_t5_common::ensure_config();
|
||||
|
||||
lock_init();
|
||||
}
|
||||
|
||||
lock_init()
|
||||
{
|
||||
level.lock_round = scripts\sp\tws_common::int_dvar_or("tws_lock_round", 20);
|
||||
level.lock_round = scripts\sp\tws_t5_common::int_dvar_or("tws_lock_round", 20);
|
||||
level.lock_active = false;
|
||||
|
||||
// recover from a prior lobby that crashed before clearing
|
||||
@@ -1,4 +1,4 @@
|
||||
/* tws_telemetry.gsc - Electric Cherry game reports via t5-gsc-utils. */
|
||||
/* tws_t5_telemetry.gsc - Electric Cherry game reports via t5-gsc-utils. */
|
||||
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
@@ -8,11 +8,11 @@ init()
|
||||
if (GetDvar(#"zombiemode") != "1")
|
||||
return;
|
||||
|
||||
scripts\sp\tws_common::ensure_config();
|
||||
scripts\sp\tws_t5_common::ensure_config();
|
||||
|
||||
if (GetDvar("tws_telemetry_enabled") == "0")
|
||||
{
|
||||
print("[tws_telemetry] Disabled by tws_telemetry_enabled=0");
|
||||
print("[tws_t5_telemetry] Disabled by tws_telemetry_enabled=0");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ init()
|
||||
|
||||
if (getSubStr(toLower(level.telemetry_url), 0, 8) != "https://")
|
||||
{
|
||||
print("^1[tws_telemetry] Telemetry disabled: tws_telemetry_url must use HTTPS");
|
||||
print("^1[tws_t5_telemetry] Telemetry disabled: tws_telemetry_url must use HTTPS");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -34,14 +34,14 @@ init()
|
||||
level.telemetry_token = "e03a03f7d22418f0c062b0b2a7317fd91b1194c4400e84b469866de501180dc2";
|
||||
if (level.telemetry_token.size < 32)
|
||||
{
|
||||
print("^1[tws_telemetry] Telemetry disabled: embedded telemetry token must be at least 32 characters");
|
||||
print("^1[tws_t5_telemetry] Telemetry disabled: embedded telemetry token must be at least 32 characters");
|
||||
return;
|
||||
}
|
||||
|
||||
level.telemetry_server = GetDvar("tws_server_id");
|
||||
if (level.telemetry_server == "")
|
||||
{
|
||||
print("^1[tws_telemetry] Set tws_server_id to the registered Electric Cherry server name");
|
||||
print("^1[tws_t5_telemetry] Set tws_server_id to the registered Electric Cherry server name");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ init()
|
||||
telemetry_log(1, "Initialized; waiting for match start. log_level=" + telemetry_log_level());
|
||||
|
||||
// Use the shared dispatcher; a second connected listener breaks T5 SP.
|
||||
scripts\sp\tws_common::register_spawn_handler(::telemetry_game_start);
|
||||
scripts\sp\tws_t5_common::register_spawn_handler(::telemetry_game_start);
|
||||
|
||||
level thread telemetry_game_end_watcher();
|
||||
level thread telemetry_sender();
|
||||
@@ -367,7 +367,7 @@ telemetry_log(verbosity, message)
|
||||
if (verbosity > telemetry_log_level())
|
||||
return;
|
||||
|
||||
print("[tws_telemetry] server=" + level.telemetry_server + " map=" + GetDvar("mapname") + " time_ms=" + getTime() + " " + message);
|
||||
print("[tws_t5_telemetry] server=" + level.telemetry_server + " map=" + GetDvar("mapname") + " time_ms=" + getTime() + " " + message);
|
||||
}
|
||||
|
||||
// Escape newlines/control characters and bound response/error output. Do not
|
||||
Reference in New Issue
Block a user