Files
tws-zombies-scripts/docs/afk.md
T

204 lines
12 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.
# Persistent AFK reserve
AFK `2.0.0` replaces unlimited protected breaks on both T5 and T6. A GUID owns
one free allowance and saved reserve across servers, games, maps and reconnects.
Electric Cherry owns balances, policy, purchase transactions and the time ledger.
The game owns verified contribution events, player commands, countdown rendering,
protection and accepted stop decisions. This uses the existing bank account and
private instance credential, not a second points bank.
## Commands and behavior
| Command | Result |
| --- | --- |
| `.afk` | Reserve available time, acknowledge its start, then enter protected AFK |
| `.back` | Stop time accounting and return, preserving the existing two-second manual grace |
| `.afk balance` | Show free, saved and currently reserved seconds as a clock |
| `.afk buy 10` | Quote ten minutes and its bank-point price |
| `.afk buy 10 confirm` | Accept that quote within 30 seconds |
Return with `.back` before purchasing; an existing reservation never extends
automatically. Purchases require whole policy packs; the initial pack is 10 minutes for 10,000
points. There is no automatic purchase. EC atomically rejects insufficient funds,
pending bank transfers, changed quotes and over-capacity purchases without a
point debit. A submitted purchase retains its ID until EC acknowledges it.
The central countdown and “Protection ends when this timer reaches zero.” remain
visible even with `.hud` hidden. The final minute is larger and red; warnings
sound at 60, 30, and each of the final ten seconds. At zero, AFK protection ends
immediately, including in the damage callback; the script restores its own controls,
weapons and zombie-targeting state. Expiration has no spectator transition, purchase
or extra grace. Repeating `.afk` does not restart the timer or reserve twice.
AFK `2.1.0` allows solo players and the last active player to enter; all players
may be AFK at the same time. Entry still rejects downed/dead/spectating players
and stock protection/control restrictions. A default 15-second reentry cooldown prevents repeated
combat toggles. Manual `.back` retains a separate two-second grace. The AFK damage
callback passes through when it does not own protection, preserving stock game
invulnerability. Other mods that restrict controls should set
`player.tws_afk_external_controls` while their restriction applies.
AFK leaves player session state unchanged, so stock player-count zombie scaling
continues to include AFK players. Losing the last non-AFK teammate does not end
protected breaks or force a match end. Authorized time continues to count down;
normal expiration and stock match-end cleanup still apply. Verify these rules
on each deployed map/mode.
## Rewards
Initial EC policy:
| Source | Time |
| --- | --- |
| Free allowance | 30 minutes per rolling 24 hours |
| Five minutes of active play | 1 minute |
| Completed round with participation | 15 seconds |
| 100 kills | 30 seconds |
| 25 headshot kills | 15 seconds |
| Each successful teammate revive | 30 seconds |
Saved earned and purchased time has a combined six-hour capacity and no expiry.
Free time is separate, non-accumulating and consumed first. EC retains fractional
reward progress across reconnects. Round/kill/headshot rewards share eight minutes
per rolling active hour; headshots stack with kills. Active-play rewards and
**every successful revive** are outside that cap. There is no per-teammate,
per-match or hourly revive limit. Retrying a report cannot award it again.
Both engines consume stock `zom_kill`, `player_revived` and `end_of_round`
notifications. T5 also attaches to stock hellhound spawn/death callbacks because
those enemies omit `zom_kill`; T6 hellhounds already emit the stock zombie death
event. Completed round numbers are deduplicated locally. Headshots require a lethal head/helmet hit with a qualifying damage
type. No reward uses spendable score or `score_total`. A round requires a kill,
revive, or at least 30 seconds of active engagement and eligibility at completion.
The one-second activity sampler uses movement over four units, a view change over
two degrees or a changed input button to refresh a 15-second engagement interval.
The stock `is_reviving` state counts support; holding a zombie that targets
the player within 512 units counts while deliberate input occurred in the last
60 seconds. Kill/revive events also refresh engagement. AFK, dead and spectator
time do not earn rewards. Contributions after manual `.back` count immediately,
including during its separate two-second grace. This permits support and zombie
holding without a minimum kill rate, while passive connection alone earns nothing.
Stock integration was checked against
[T5 scripts 70689b8](https://github.com/plutoniummod/t5-scripts/tree/70689b8288e60079d48926657e670c41aab4abdf)
and [T6 scripts 2d84403](https://github.com/plutoniummod/t6-scripts/tree/2d8440321602f22f63f5335817110d60ddf223d5).
Recheck callback contracts if the stock runtime changes.
## Configuration and coordinated rollout
1. Back up EC and the game runtime journals. Deploy EC #151 and restart its service.
2. Update all EC host agents to **1.12.0+** before enabling these scripts. This
adds AFK settlement before deleting/rebuilding stopped runtime storage.
3. Build and install TWS `t5-plugin` and `t6-plugin` **1.4.0+** and matching AFK
**2.1.0** scripts. Require common **1.4.0+**, telemetry **1.0.0+**, and
Plutonium **r5334+** for `SetTextUnlimited`. Fully restart game-server processes.
4. Retain EC's private `tws_bank_token` and exact `tws_server_id`; telemetry must
establish the current match before AFK commands can be authorized.
5. Keep `tws-afk/t5/` and `tws-afk/t6/`, relative to the process working directory,
on persistent writable storage with one process per server/endpoint scope.
Upgrading AFK scripts from `2.0.0` to `2.1.0` adds no dependency requirement:
copy the matching script for each game and restart the map. No full server-process
restart is required for this script-only update.
| Game dvar | Default | Meaning |
| --- | --- | --- |
| `tws_afk_enabled` | enabled | `0` disables new AFK service startup |
| `tws_afk_cooldown_seconds` | `15` | Reentry cooldown, clamped to 2–300 seconds |
| `tws_afk_warning_sound` | `zmb_perks_packa_ready` | Local warning sound alias; verify on deployed maps |
Economic configuration lives in EC's `EC_AFK_*` environment settings. See the
[EC AFK guide](https://gitea.thewrightserver.net/josh/electric-cherry/src/branch/main/docs/guides/afk.md)
for exact rates, rolling-window accounting and JSON schemas. The fixed game
endpoint is `https://ec.thewrightserver.net/api/afk`; requests reuse the private
`ec_bank_` credential. Shared telemetry tokens cannot spend or reserve time.
## API and recovery ownership
The matching native API `1.0.0` exposes `afkVersion`, `afkResponse`, `afkStore`,
`afkLoad`, `afkRemove`, `afkPrepare`, `afkAuthorize`, `afkBegin`, `afkRemaining`,
`afkCheckpoint`, `afkStop`, and `afkRecover`. Responses must validate their complete
schema and request/session identity before authorization takes effect. Requests
are immutable; journal writes precede network transmission and native activation.
EC actions are `balance`, `event`, `purchase`, `reserve`, `start` and `settle`.
Events carry cumulative counters scoped to GUID, instance and match, with a
monotonic sequence. The native journal coalesces newer cumulative event snapshots
to bound outage queues; EC prevents retries and reordered reports awarding twice.
Revive counts still increase for every distinct successful revive. Kill/active
progress is flushed at most every 30 seconds and on normal disconnect/end; a hard
process crash can lose progress that had not yet reached the local journal.
Already accepted rewards and journaled snapshots persist.
Protection starts only after reservation and start acknowledgments, a final
player-state recheck, and a durable native clock start. Once authorized, an EC
outage cannot shorten protection; a local monotonic deadline still ends it at zero.
Manual return, disconnect, death and match end stop accounting immediately. A
failed stop-journal write freezes the original stop time for retry rather than
charging during the delay. Never replay a reserve/start from a background sender.
Before activation, an interrupted session recovers as `never_started` with zero
consumption. Its tombstone also blocks delayed reserve/start delivery. After
activation, a crash with no durable stop becomes `unresolved`, preserving its last
confirmed checkpoint and full reservation. Absence of a heartbeat never releases
spendable time. An administrator must reconcile such a stopped session using EC's
audited correction endpoint; corrected charges remain distinct from exact durations.
Do not delete journals or change IDs to unblock a hold.
The EC agent independently proves the old process is stopped before recovering
journals during remove/rebuild/cancel-create. It sends requests only to its enrolled
controller using the assigned teardown operation and host credential. Lost replies,
unrecognized endpoints or malformed journals preserve runtime storage for retry.
## Validation
Portable checks (engine shims are not live Plutonium):
```sh
node tools/check_afk.mjs
python3 tools/test_plugin_afk.py --json-header /path/to/pinned/json.hpp
node tools/check_bank.mjs
node tools/check_hud.mjs
node tools/check_telemetry.mjs
```
Use each plugin's pinned JSON header; the native harness also accepts a path with
`{game}` for different T5/T6 dependency revisions. It compiles native utilities
and actual registration adapters with ASan/UBSan, then exercises separate-process
journal recovery. T6 source compilation follows its [script instructions](../t6/scripts/README.md#validation).
T5 linking and behavior require a live server.
Before production activation, validate **both engines**:
- Enter/return/expire, reconnect, die, change maps and restart the process; compare
the displayed countdown and EC balances/ledger. At expiry attempt moving, firing,
throwing equipment and receiving zombie damage immediately, including `.hud` off.
- Try T5 entry while downed, then after a successful revive. Check T6 laststand,
afterlife, intermission and stock control restrictions; no stock protection should
be removed. Repeat rapid `.afk`/`.back` and concurrent commands during slow replies.
- Earn each reward; revive the same teammate repeatedly beyond the performance cap.
Verify passive, spectating, AFK and bank point changes earn nothing. Test support
and zombie holding. Carry partial progress across maps/servers/T5/T6.
- Confirm the displayed purchase price; try expired/changed quotes, insufficient
bank funds, pending bank transfers and capacity overflow. Drop purchase replies
and retry without a second debit. Attempt simultaneous reservations on two servers.
- Disconnect EC after authorization; the countdown must continue and expire locally.
Drop reserve/start/stop replies, reorder delivery, fill/fail journal storage, and
restart. Verify never-started refunds, durable exact stops and unconfirmed crash
holds. Correct only a proven stopped session and confirm the ledger audit.
- Enter as the only connected player and as the last active player with downed,
dead, spectating or AFK teammates. Put every player in AFK. Kill/disconnect the
last active teammate, including while reserve/start replies are pending; verify
protection continues without a forced match end. Check solo return/expiration,
normal stock match-end settlement, afterlife/Grief recovery and zombie scaling.
- Rebuild/remove with journals from both games, retire the instance credential,
interrupt the agent after a lost reply, and retry. Runtime deletion must wait for
acknowledged recovery and cannot authorize a new purchase.
Validation performed for the initial `2.0.0` change: 39 AFK behavior checks, 14 core HUD and
56 service HUD checks passed. All nine T6 scripts compiled and assembled with
the upstream [gsc-tool compiler 8f1d6bd](https://github.com/xensik/gsc-tool/tree/8f1d6bd4d51efdc619629b9254fb439427a6d306)
using its T6 PC compiler/assembler library in a temporary local driver. No Windows
DLL build, production deployment or live T5/T6 validation is implied by these checks.