Files

12 KiB
Raw Permalink Blame History

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 and T6 scripts 2d84403. 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 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):

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. 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 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.