RATScript v2 / Complete Reference
Scripting Reference
The current RAT 5 event language: syntax, values, scopes, reusable functions, telnet capture, runtime limits, and built-ins.
Start here
RATScript is a small language for answering three questions: what happened, should RAT react, and what should RAT do. You can begin by editing a template; you do not need to memorize the language or the function list.
Names beginning with $, such as $player.name, are facts supplied by the current event.
Use if ... then to run actions only when a condition is true.
Functions such as log(...), discord_send(...), and gs_broadcast(...) do the work.
# This script runs when a new player joins.
log(format("Welcome, {0}!", $player.name))
Contents
- Start here
- Execution model and source layout
- Statements and control flow
- Values, operators, and conditions
- Variables, objects, and scopes
- Arrays, indexing, and FOR EACH
- Global runtime variables
- Event variables
- String interpolation
- Persistent shared state
- Reusable functions
- Telnet commands and capture
- Built-in functions
- Limits and failure behavior
- Complete examples
1. Execution model and source layout
rat5.v2 is the supported event-script version. RAT selects enabled definitions for an event, builds read-only event and runtime values, validates the script, and executes statements from top to bottom. Scripts can calculate values, branch, update definition-local persistent state, call reusable functions, and perform controlled side effects.
- Event and runtime values are fixed for the logical execution.
- Validation rejects unknown names, invalid object paths, malformed blocks, and incorrect argument counts.
- Only the first matching branch of an
ifblock executes. wait(...)suspends this execution without blocking other scripts.- Successful
global.*mutations are persisted for this definition.
Source layout
- Statements are separated by line breaks; semicolons are unnecessary.
#starts a comment outside a quoted string or telnet command.- Strings use double quotes and support
\",\\,\n,\r, and\t. - Keywords and function names are case-insensitive. Lowercase is used throughout this reference.
- Indentation is optional but recommended.
# A minimal chat command
set local.message = lower(trim($chat_content))
if local.message == "!hello" then
set global.hello_count = coalesce(global.hello_count, 0) + 1
gs_broadcast(format("Hello {0}! Use #{1}", $player.name, global.hello_count), "say")
end
2. Statements and control flow
set and unset
set assigns a local or persistent global value. Object paths are created as needed. unset removes the selected local or global path and its descendants.
set local.normalized = lower(trim($chat_content))
set global.last_player = $player.name
unset global.last_error
if, else if, else, and end
if $players_online == 0 then
log("Server is empty")
else if $players_online < $players_max then
log("Slots are available")
else
log("Server is full")
end
Calls, actions, and return
Value-returning calls may appear inside expressions. Action calls are complete statements. return is valid inside reusable functions and may return a value or stop with no value.
FOR EACH ... IN ... END
FOR EACH repeats a block once for every item in an array or compatible collection. The item is placed in a local variable for the duration of each pass. Start with the arrays and loops guide before using nested loops.
for each local.player in $players
log(local.player.name)
end
wait(milliseconds)
wait suspends the current logical execution and resumes from the following statement. Its limits and restart behavior are documented below.
3. Values, operators, and conditions
RATScript values are null, strings, numbers, booleans, objects, and arrays. Function results and variables retain their type. Strings can interpolate scalar values, but arrays must be indexed, joined, or processed with FOR EACH.
| Precedence | Operators | Purpose |
|---|---|---|
| 1 | () | Grouping and function calls |
| 2 | not, unary - | Boolean negation and numeric negation |
| 3 | *, /, % | Multiplication, division, remainder |
| 4 | +, - | Addition, concatenation, subtraction |
| 5 | <, <=, >, >= | Numeric or compatible ordered comparison |
| 6 | ==, != | Equality and inequality |
| 7 | and | Short-circuit conjunction |
| 8 | or | Short-circuit disjunction |
null, false, numeric zero, an empty string, and an empty array are falsey; other values are truthy. Arrays and objects support equality checks. Prefer explicit comparisons and exists(...) when optional data matters.
4. Variables, objects, and scopes
| Form | Lifetime | Writable | Use |
|---|---|---|---|
$name, $object.field, $array[index] | Current execution | No | Event-specific and runtime values supplied by RAT. |
local.name, local.items[index] | Current call frame | Yes | Temporary calculations, objects, and native arrays. |
global.name | Persistent per event definition | Scalars only | Persistent strings, numbers, booleans, and null values. Objects and arrays must stay local. |
| Reusable-function parameter name | Current function call | No | Arguments declared by function name(parameter). |
Objects use dotted paths, for example $player.position.x. Arrays use brackets, and access can be chained: $players[0].position.x or local.groups[0].players[1].name. Missing optional properties and out-of-range reads evaluate to null. Use exists(...) before relying on optional data.
5. Arrays, indexing, and FOR EACH
An array is an ordered list of values. Use arrays when the same action should be applied to several names, numbers, players, attachments, or other items. Array positions start at zero, so the first item is at position [0].
Create and read arrays
set local.names = ["Alice", "Bob", "Charlie"]
set local.first = local.names[0]
set local.chosen = local.names[local.index]
set local.matrix = [[1, 2], [3, 4]]
set local.value = local.matrix[1][0]
Array items may be strings, numbers, booleans, null, objects, other arrays, or expressions. Empty arrays are written as []. Brackets can be followed by more brackets or object properties, such as $players[0].position.x.
Change a local array
set local.names[1] = "Robert"
set local.names = append(local.names, "Charlie")
Indexed assignment works only through a mutable local.* native array. Replacing an existing item does not change other copies of the array. Assignment cannot grow an array; use append(...), which returns a new array.
null. Writing beyond the end, or using a negative, fractional, or nonnumeric index, produces a runtime error.Repeat work with FOR EACH
for each local.player in $players
log(format("{0} is level {1}", local.player.name, local.player.level))
end
The iterator must be a simple local.* name. RAT evaluates the collection once when the loop starts, then runs the body once per item in order. An empty collection runs zero times and leaves the iterator as null; after a nonempty loop, the iterator contains the final item.
Loops may be nested, may call reusable functions, and may contain wait(...). A wait resumes at the same item. break and continue are not currently part of RATScript.
Built-in and compatible collections
| Collection | How to use it | Notes |
|---|---|---|
$players | $players[0] or FOR EACH | Read-only snapshot of currently online players, with the same fields as $player. |
$discord.attachments | $discord.attachments[0] or .item_01 | Both forms work; existing scripts do not need to change. |
$discord.embeds | $discord.embeds[0] or .item_01 | Read-only compatibility-indexed collection. |
$discord.reactions | $discord.reactions[0] or .item_01 | Read-only compatibility-indexed collection. |
count(...), join(...), contains_value(...), bracket indexing, and FOR EACH accept native arrays and compatible indexed collections. append(...) accepts native arrays only.
global.*. Store a scalar result such as a count, name, number, boolean, or joined string instead.6. Global runtime variables
These values are supplied to event scripts and scheduled tasks..
| Name | Kind | Description | Example | Availability |
|---|---|---|---|---|
$players
| array | Bounded snapshot of players currently online, ordered by the current player snapshot. Read-only rat5.v2 only | [{"name":"Trekkan","online":true}] | Required |
$backup
| object | Most recent backup operation result. rat5.v2 only | — | Required |
$config
| object | Current managed game server configuration. Sensitive password and token properties are never included. rat5.v2 only | — | Required |
$bm
| object | Current and upcoming blood moon timing when RAT knows it. rat5.v2 only | — | Required |
$game_server_name | string | Configured game server name when RAT knows it. | Initial RAT5 Server | Optional |
$players_online | string | Current number of players online. | 4 | Required |
$players_max | string | Configured maximum concurrent players when RAT knows it. | 16 | Optional |
$uptime | string | Elapsed time since the current game server process started. | 2d 4h 10m | Optional |
$day | string | Current in-game day when RAT knows it. | 7 | Optional |
$hour | string | Current in-game hour when RAT knows it. | 21 | Optional |
$minute | string | Current in-game minute when RAT knows it. | 30 | Optional |
$gametime | string | Current in-game day and time in Day N, HH:MM format when RAT knows it. | Day 710, 14:51 | Optional |
$current_time | string | Current UTC time at event execution in HH:MM:SS format. | 17:37:01 | Required |
$current_date | string | Current UTC date at event execution in YYYY-MM-DD format. | 2026-06-20 | Required |
$current_datetime | string | Current UTC datetime at event execution in RFC3339 format. | 2026-06-20T17:37:01Z | Required |
7. Event variables
Every event supplies only the tokens declared by its catalog entry, in addition to the runtime variables above. The compact index below lists top-level names; object fields, examples, nullability, deprecations, and templates are in the event catalog.
| Event type | Source | Top-level variables |
|---|---|---|
chat.global_messageChat Global Message | telnet.chat.global_message | $event_type, $event_key, $occurred_at_utc, $player.name, $chat_content, $channel_name, $platform_id, $entity_id, $player, $0, $1, $N-, $N+ |
chat.server_messageChat Server Message | telnet.chat.server_message | $event_type, $event_key, $occurred_at_utc, $speaker_name, $chat_content, $channel_name, $0, $1, $N-, $N+ |
discord.message_receivedDiscord Message | discord.message_received | $event_type, $event_key, $occurred_at_utc, $discord_guild_id, $discord_channel_id, $discord_channel_key, $discord_channel_name, $discord_message_id, $discord_message_timestamp, $discord_author_id, $discord_author_username, $discord_author_global_name, $discord_author_name, $discord_author_is_bot, $discord_mentions_everyone, $discord_mention_count, $discord_mentioned_user_ids, $discord_mentioned_role_ids, $discord_role_mention_count, $discord_attachment_count, $discord_embed_count, $discord_reaction_count, $discord_message_type, $discord_message_edited_at, $discord_message_pinned, $discord_message_tts, $discord_reply_message_id, $discord_reply_channel_id, $discord_reply_guild_id, $discord_reply_author_id, $discord_attachment_name, $discord_attachment_type, $discord_attachment_url, $discord_attachment_size, $discord_embed_title, $discord_embed_description, $discord_embed_url, $discord_embed_field_count, $discord_webhook_id, $discord_content_raw, $chat_content, $discord |
discord.message_updatedDiscord Message Updated | discord.message_updated | $event_type, $event_key, $occurred_at_utc, $discord_guild_id, $discord_channel_id, $discord_channel_key, $discord_channel_name, $discord_message_id, $discord_message_timestamp, $discord_message_edited_at, $discord_author_id, $discord_author_name, $discord_mentioned_user_ids, $discord_mentioned_role_ids, $discord_attachment_count, $discord_embed_count, $discord_reply_message_id, $discord_content_raw, $chat_content, $discord |
discord.message_deletedDiscord Message Deleted | discord.message_deleted | $event_type, $event_key, $occurred_at_utc, $discord_guild_id, $discord_channel_id, $discord_channel_key, $discord_channel_name, $discord_message_id, $discord_message_timestamp, $discord_message_edited_at, $discord_author_id, $discord_author_name, $discord_mentioned_user_ids, $discord_mentioned_role_ids, $discord_attachment_count, $discord_embed_count, $discord_reply_message_id, $discord_content_raw, $chat_content, $discord |
discord.reaction_addedDiscord Reaction Added | discord.reaction_added | $event_type, $event_key, $occurred_at_utc, $discord_guild_id, $discord_channel_id, $discord_channel_key, $discord_message_id, $discord_reaction_user_id, $discord_reaction_emoji, $discord_reaction_emoji_id |
discord.reaction_removedDiscord Reaction Removed | discord.reaction_removed | $event_type, $event_key, $occurred_at_utc, $discord_guild_id, $discord_channel_id, $discord_channel_key, $discord_message_id, $discord_reaction_user_id, $discord_reaction_emoji, $discord_reaction_emoji_id |
player.joinedPlayer Joined | telnet.player.joined | $event_type, $event_key, $occurred_at_utc, $player.name, $player |
player.leftPlayer Left | telnet.player.left | $event_type, $event_key, $occurred_at_utc, $player.name, $player |
entity.killedEntity Killed | telnet.entity.killed | $event_type, $event_key, $occurred_at_utc, $killed_entity_name, $killed_entity_id, $killed_player_name, $killed_player_id, $killed_platform_id, $killed_cross_platform_id, $killer_name, $killer_entity_id, $killer_player_name, $killer_player_id, $killer_platform_id, $killer_cross_platform_id |
server.unresponsiveServer Unresponsive | rat.telnet_health.unresponsive | $event_type, $event_key, $occurred_at_utc, $failure_count, $failure_reason, $failure_detail, $last_responsive_at_utc, $first_failure_at_utc, $unresponsive_since_utc, $probe_interval_seconds, $probe_timeout_seconds |
server.responsiveServer Responsive | rat.telnet_health.responsive | $event_type, $event_key, $occurred_at_utc, $responsive_at_utc, $unresponsive_since_utc, $first_failure_at_utc, $outage_duration_seconds, $failed_probe_count, $last_health_failure_reason |
text.matchText Match | | $event_type, $event_key, $occurred_at_utc, $raw_line |
backup.startedBackup Started | internal.backup.started | $event_type, $event_key, $occurred_at_utc, $backup_filename, $backup_destination, $backup_start_time, $backup_completion_time, $backup_duration, $backup_size, $backup_compression_type, $backup_error_message, $backup_retained_count |
backup.completedBackup Completed | internal.backup.completed | $event_type, $event_key, $occurred_at_utc, $backup_filename, $backup_destination, $backup_start_time, $backup_completion_time, $backup_duration, $backup_size, $backup_compression_type, $backup_error_message, $backup_retained_count |
backup.failedBackup Failed | internal.backup.failed | $event_type, $event_key, $occurred_at_utc, $backup_filename, $backup_destination, $backup_start_time, $backup_completion_time, $backup_duration, $backup_size, $backup_compression_type, $backup_error_message, $backup_retained_count |
server.readyServer Ready | internal.server.ready | $event_type, $event_key, $occurred_at_utc, $server_state, $server_process_id, $server_started_at, $server_ready_at, $server_stopped_at, $server_uptime, $server_restart_reason, $server_restart_delay |
server.restartingServer Restart | internal.server.restarting | $event_type, $event_key, $occurred_at_utc, $server_state, $server_process_id, $server_started_at, $server_ready_at, $server_stopped_at, $server_uptime, $server_restart_reason, $server_restart_delay |
server.startedServer Start | internal.server.started | $event_type, $event_key, $occurred_at_utc, $server_state, $server_process_id, $server_started_at, $server_ready_at, $server_stopped_at, $server_uptime, $server_restart_reason, $server_restart_delay |
server.stoppedServer Stop | internal.server.stopped | $event_type, $event_key, $occurred_at_utc, $server_state, $server_process_id, $server_started_at, $server_ready_at, $server_stopped_at, $server_uptime, $server_restart_reason, $server_restart_delay |
player.new_joinedNew Player Joined | internal.player.new_joined | $event_type, $event_key, $occurred_at_utc, $player.name, $player |
bloodmoon.startedBloodmoon Started | telnet.bloodmoon.started | $event_type, $event_key, $occurred_at_utc, $bloodmoon_day |
bloodmoon.endedBloodmoon Ended | telnet.bloodmoon.ended | $event_type, $event_key, $occurred_at_utc |
custom.backpack_locationPlayer Backpack Location | telnet.custom.backpack_location | $event_type, $event_key, $occurred_at_utc |
custom.preparing_quitPreparing Quit | telnet.custom.preparing_quit | $event_type, $event_key, $occurred_at_utc |
custom.server_statsGame Server Stats | telnet.custom.server_stats | $event_type, $event_key, $occurred_at_utc, $inf_time, $fps, $heap, $max, $chunks, $cgo, $ply, $zom, $ent, $items, $co, $rss |
custom.start_gameStart Game | telnet.custom.start_game | $event_type, $event_key, $occurred_at_utc |
player.connectedPlayer Connected | telnet.player.connected | $event_type, $event_key, $occurred_at_utc, $entityid, $name, $pltfmid, $crossid, $steam_owner, $ip, $player |
player.diedPlayer Died | telnet.player.died | $event_type, $event_key, $occurred_at_utc, $inf_gmsg, $player, $player_name |
player.disconnectedPlayer Disconnected | telnet.player.disconnected | $event_type, $event_key, $occurred_at_utc, $inf_player_disconnected, $pltfm_id, $cross_id, $owner_id, $player.name, $client_number, $player |
player.kickedPlayer Kicked | telnet.player.kicked | $event_type, $event_key, $occurred_at_utc, $kick_type, $kick_message, $entity_id, $pltfm_id, $cross_id, $owner_id, $player.name, $client_number, $player |
player.bannedPlayer Banned | telnet.player.banned | $event_type, $event_key, $occurred_at_utc, $ban_until, $ban_reason, $entity_id, $pltfm_id, $cross_id, $owner_id, $player.name, $client_number, $player |
player.spawned_in_worldPlayer Spawned in World | telnet.player.spawned_in_world | $event_type, $event_key, $occurred_at_utc, $reason, $position, $position_x, $position_y, $position_z, $entity_id, $pltfm_id, $cross_id, $owner_id, $player.name, $client_number, $player |
8. String interpolation
Quoted strings and telnet command text support {{expression}} interpolation. Expressions may include bracket access such as {{$players[0].name}}. Arrays cannot be rendered directly; select an item, use join(...) for scalar arrays, or iterate with FOR EACH. Use format(...) when numbered placeholders make a message easier to read.
log("Player {{$player.name}} triggered {{$event_type}}")
@say "Welcome {{$player.name}}"
discord_send("general", format("{0}: {1}", $player.name, $chat_content))
The complete shipped templates are maintained with their event entries in RAT 5 Events, preventing a second divergent copy in this page.
9. Persistent shared state
global.* is persisted per event definition. Two definitions using global.count do not share the same value. Persistent values may be strings, numbers, booleans, or null. Arrays and objects cannot be stored in global.*; keep them in local.* and persist only the scalar result you need. Unset a path to remove it.
set global.uses = coalesce(global.uses, 0) + 1
set global.last.player = $player.name
set global.last.at = $current_datetime
if global.uses >= 100 then
unset global.uses
end
Preview reports proposed mutations without committing them. The Events screen in RAT 5 Client can inspect globals and remove a stored global when it is no longer needed.
10. Reusable functions
A reusable function is a separately stored, versioned rat5.v2 script containing one top-level function declaration. Names begin with a lowercase letter and contain lowercase letters, numbers, and underscores.
function announce(message)
log(message)
return upper(message)
end
Parameters are read-only call-frame values and may contain arrays. Reusable functions may return arrays, and each call receives fresh locals. Event tokens and the calling definition's globals remain available when the function is context-dependent. Reusable functions may call enabled reusable functions, use FOR EACH, and suspend through wait(...). Direct and indirect recursion are rejected.
RAT tracks event and function dependencies. A referenced function cannot be deleted, and renames update stored references through the event store. Disabled functions cannot be called.
11. Telnet commands and response capture
A line beginning with @ sends one normalized telnet command. Carriage returns, line feeds, and NUL characters are rejected to prevent command injection.
@say "Maintenance begins in 10 minutes"
Capture is permitted only as the complete right-hand side of a set statement. Use @@command for the one-second response timeout or @@(duration)command to override it.
set local.server_time = @@(3s)gettime
log(local.server_time)
Capture waits up to five seconds for the command queue, treats 250 ms of idle output as completion, strips an echoed command, ignores transport noise, and captures at most 64 lines or 16 KiB. Empty responses, timeout, queue failure, unsafe commands, and limit overruns produce structured runtime errors.
12. Built-in functions
The server currently exposes 98 built-ins. User-defined reusable functions appear alongside these at runtime but are installation-specific.
Action
Write information to the RAT log or pause the current script. These are useful while learning and troubleshooting.
log(message)Writes an info-level event script message to the RAT server log.Example:log("Player {{$player.name}} said: {{$chat_content}}")debug(message)Writes a debug-level event script message to the RAT server log when debug logging is enabled.Example:debug("Matched {{$event_type}} at {{$current_datetime}}")wait(milliseconds)Suspends only the current script instance for up to 60000 ms, then resumes later from the next statement. Pending waits are kept in memory only, so restart or shutdown drops them.Example:wait(1500)credits_modify(player_ref, amount)Adds or subtracts credits for the resolved player. Amount must be an integer, and unresolved players are ignored.Example:credits_modify($player.name, 25)credits_set(player_ref, amount)Sets credits for the resolved player. Amount must be an integer, and unresolved players are ignored.Example:credits_set($player.name, 1000)
Conversion
Change a value into text, a number, or true/false so it can be compared or displayed safely.
to_string(value)Converts a value to a string using render-time rules.Example:to_string(global.help_count)to_number(value)Converts a value to a number or fails when conversion is not possible.Example:to_number(global.score)to_bool(value)Converts a value to a boolean using the script truthiness rules.Example:to_bool(global.enabled)
Discord
Send, reply to, edit, delete, react to, pin, or inspect Discord content. These require a working Discord integration.
discord_send(channel_key_or_id, message)Sends a Discord message to a configured channel mapping key or a raw reachable Discord channel ID.Example:discord_send("general", format("{0}: {1}", $discord_author_name, $chat_content))Returns:Sends `Trekkan: hello world` to the `general` channel mapping.`channel_key_or_id` accepts an enabled script-target mapping key or a numeric channel ID in the configured guild.`message` is limited to 2000 characters after trimming.Raw `<@...>`, `<@&...>`, `@everyone`, and `@here` text is displayed without notifying anyone. Use the Discord mention helpers to authorize notifications.Requires the bot to view the channel and send messages.discord_embed(channel_key_or_id, title, description, color?, url?, footer?, image_url?, thumbnail_url?)Sends a Discord embed to a configured channel mapping key or a raw reachable Discord channel ID. Sends the embed only; no separate plain-text message body is included. Description-only embeds are allowed, trailing optional arguments may be omitted, colors must use #RRGGBB, and URLs must be http/https.Example:discord_embed("general", "Server Alert", format("{0}: {1}", $event_type, $chat_content), "#ff8800")Returns:Sends one orange embed titled `Server Alert` with the rendered event text.Arguments after `description` are optional and must be supplied in signature order.`color` must be `#RRGGBB`; URL, image, and thumbnail values must use HTTP or HTTPS.Title is limited to 256 characters, description to 4096, footer to 2048, and total embed text to 6000.This legacy form sends no plain-text content and supports no fields, author, timestamp, or footer icon; use `discord_embed_send` for those features.Requires View Channel, Send Messages, and Embed Links.discord_embed_send(channel_key_or_id, embed_object)Sends a structured Discord embed object. Supports content, author, timestamp, footer icons, images, thumbnails, and deterministically ordered fields.Example:set local.embed.content = format("{0}", discord_mention_user($discord_author_id)) set local.embed.title = "Server Alert" set local.embed.description = $chat_content set local.embed.color = "#ff8800" set local.embed.timestamp = $occurred_at_utc set local.embed.author.name = "RAT" set local.embed.author.url = "https://example.com" set local.embed.author.icon_url = "https://example.com/rat.png" set local.embed.footer.text = "Automated" set local.embed.footer.icon_url = "https://example.com/footer.png" set local.embed.image_url = "https://example.com/image.png" set local.embed.thumbnail_url = "https://example.com/thumb.png" set local.embed.fields.field_01.name = "State" set local.embed.fields.field_01.value = "Online" set local.embed.fields.field_01.inline = true discord_embed_send("general", local.embed)Returns:Sends the structured embed and safely mentions only `$discord_author_id` in its plain-text content.Supported root properties: `content`, `title`, `description`, `color`, `url`, `timestamp`, `image_url`, and `thumbnail_url`.Author properties: `author.name`, `author.url`, and `author.icon_url`. URLs/icons require `author.name`.Footer properties: `footer.text` and `footer.icon_url`. The icon requires footer text.Fields are objects under `fields`; each requires `name` and `value`, with optional boolean `inline`. Field keys must be valid RatScript identifiers and are sorted alphabetically.Up to 25 fields are allowed. Field names are limited to 256 characters and values to 1024; aggregate embed text is limited to 6000.`timestamp` must be RFC3339. All URL properties must use HTTP or HTTPS.Only `content` can generate notifications, and only mention-helper values propagated through `format(...)` are authorized.discord_status(kind, text?)Updates the active Discord bot's scripted activity/custom status for the live session only. Supports clear, playing, watching, and custom. Repeating the same normalized request is a no-op, and clear removes the current scripted override without persisting anything across reconnects.Example:discord_status("playing", format("Watching {0} players", $player_count))Returns:Sets the bot activity to `Playing Watching 4 players` for the current Discord session.`kind` supports `playing`, `watching`, `custom`, and `clear`.`playing`, `watching`, and `custom` require non-empty text. `clear` accepts no text.Status changes are session-only and are not persisted across reconnects. Repeating the same normalized value is a no-op.discord_reply(channel_key_or_id, message_id, message, mention_replied_user?)Replies to a Discord message. The replied user is not notified unless the final argument is true.Example:discord_reply("general", $discord_message_id, "Acknowledged", false)Returns:Replies `Acknowledged` to `$discord_message_id` without notifying the original author.`message_id` must be a numeric Discord message ID in the target channel.`mention_replied_user` defaults to false. Set it to true only when the reply should notify the original author.Mentions inside `message` remain default-deny unless constructed with Discord mention helpers.Requires View Channel, Send Messages, and Read Message History.discord_edit(channel_key_or_id, message_id, message)Edits a message created by the Discord bot.Example:discord_edit("general", local.message_id, "Updated status")Returns:Replaces the bot message content with `Updated status`.The bot can edit only messages it created. `message_id` must be numeric and the replacement is limited to 2000 characters.Raw mention syntax does not notify; use Discord mention helpers for explicitly authorized mentions.discord_delete(channel_key_or_id, message_id)Deletes a Discord message when the bot has permission.Example:discord_delete("general", local.message_id)Returns:Deletes the selected Discord message.`message_id` must be numeric. Deleting another user's message requires Manage Messages.The target channel must be an enabled script target or a reachable channel in the configured guild.discord_react(channel_key_or_id, message_id, emoji)Adds a reaction to a Discord message.Example:discord_react("general", $discord_message_id, "👍")Returns:Adds 👍 to `$discord_message_id`.`emoji` accepts a Unicode emoji such as `👍` or Discord custom-emoji format such as `name:123456789012345678`.Requires Add Reactions and Read Message History; custom emoji may require Use External Emoji.discord_pin(channel_key_or_id, message_id)Pins a Discord message.Example:discord_pin("general", $discord_message_id)Returns:Pins `$discord_message_id` in the target channel.Requires Manage Messages. `message_id` must be numeric.discord_unpin(channel_key_or_id, message_id)Unpins a Discord message.Example:discord_unpin("general", $discord_message_id)Returns:Removes the pin from `$discord_message_id`.Requires Manage Messages. `message_id` must be numeric.discord_thread_start(channel_key_or_id, message_id, name, archive_minutes?)Starts a thread from a Discord message. Archive minutes may be 60, 1440, 4320, or 10080.Example:discord_thread_start("general", $discord_message_id, "Incident discussion", 1440)Returns:Creates `Incident discussion` from `$discord_message_id` and auto-archives it after 1440 minutes of inactivity.`name` is required and limited to 100 characters.`archive_minutes` defaults to 1440 and must be one of 60, 1440, 4320, or 10080. Availability depends on guild features.Requires Create Public Threads and Send Messages in Threads.discord_mention_user(user_id)Builds a user mention and authorizes only that user mention when the value is sent to Discord.Example:discord_mention_user($discord_author_id)Returns:<@456789012345678901>`user_id` must contain only digits.The returned value carries a whitelist for exactly that user. Preserve it with `format(...)` and pass the result directly to a Discord message, reply, edit, or structured embed `content`.discord_mention_role(role_id)Builds a role mention and authorizes only that role mention when the value is sent to Discord.Example:discord_mention_role("123456789012345678")Returns:<@&567890123456789012>`role_id` must contain only digits.The returned value carries a whitelist for exactly that role. Whether it notifies depends on Discord role mentionability and bot permissions.discord_mention_everyone()Builds an explicit @everyone mention. This is a high-impact notification and should be used sparingly.Example:discord_mention_everyone()Returns:@everyoneRequires `[discord.automation_options].allow_mass_mentions = true`; otherwise sending fails.This authorizes Discord's `everyone` mention type and therefore applies to `@everyone` or `@here` text in the same message.discord_mention_here()Builds an explicit @here mention. This is a high-impact notification and should be used sparingly.Example:discord_mention_here()Returns:@hereRequires `[discord.automation_options].allow_mass_mentions = true`; otherwise sending fails.This authorizes Discord's `everyone` mention type and therefore applies to `@everyone` or `@here` text in the same message.discord_user_has_role(user_id, role_id)Returns true when the user is a member of the configured Discord guild and currently has the specified role.Example:discord_user_has_role($discord.author.id, "567890123456789012")Returns:trueParameters:user_id(string);role_id(string)Return type:booleanBoth arguments must be numeric Discord IDs; role names are not accepted.Returns false when the user is not in the configured guild or does not have the role.Discord configuration or connection failures are reported as runtime errors.discord_user_in_guild(user_id)Returns true when the user is currently a member of the configured Discord guild.Example:discord_user_in_guild($discord.author.id)Returns:trueParameters:user_id(string)Return type:boolean`user_id` must be a numeric Discord ID.Returns false when Discord reports that the user is not a member of the configured guild.Discord configuration or connection failures are reported as runtime errors.discord_channel_exists(channel_key_or_id)Returns true when a configured channel mapping key or numeric channel ID resolves inside the configured Discord guild.Example:discord_channel_exists("general")Returns:trueParameters:channel_key_or_id(string)Return type:booleanAccepts a configured channel mapping key or a numeric Discord channel ID.Returns false when the channel does not exist or belongs to another guild.The mapping does not need to be enabled as a script target for this existence check.discord_role_exists(role_id)Returns true when the numeric role ID exists in the configured Discord guild.Example:discord_role_exists("567890123456789012")Returns:trueParameters:role_id(string)Return type:boolean`role_id` must be a numeric Discord ID; role names are not accepted.Returns false when the role is absent from the configured guild.Discord configuration or connection failures are reported as runtime errors.
Game Server
Broadcast messages and start, stop, restart, or inspect the managed game server. Review these carefully before enabling them.
gs_start()Starts the game server. Fire-and-forget; the script does not wait for the server to finish starting.Example:gs_start()gs_stop(reason?)Stops the game server. An optional reason string is logged. Fire-and-forget.Example:gs_stop("Scheduled maintenance")gs_restart(reason?)Restarts the game server. An optional reason string is logged. Fire-and-forget.Example:gs_restart("Nightly restart")gs_status()Returns the current server state as a string: "unknown", "stopped", "starting", "running", "stopping", "restarting", or "crashed".Example:gs_status()gs_broadcast(message, broadcast_type?, channel_key?)Broadcasts a message via one or more channels. broadcast_type: "say" (default), "discord", "discord_embed", "log", "all". channel_key is required for discord types.Example:gs_broadcast("Server restarting in 5 minutes.", "say")gs_countdown(seconds, action, reason?, interval?, broadcast_type?, channel_key?)Starts a countdown that executes action ("stop" or "restart") at zero. Fires milestone broadcasts automatically. A second call while a countdown is active is a no-op — call gs_countdown_cancel() first.Example:gs_countdown(300, "restart", "Nightly maintenance", 60, "say")gs_countdown_cancel(message?, broadcast_type?, channel_key?)Cancels the active countdown without executing the action. Silent by default; pass a message to broadcast the cancellation.Example:gs_countdown_cancel("Restart cancelled by admin.", "say")
Logic
Test whether values exist, are empty, match text, occur in collections, or meet common conditions.
count(collection)Returns the number of elements in an array or indexed collection.Example:count($players)Returns:4Parameters:collection(array)Return type:numberAccepts native arrays and compatibility-indexed collections.append(array, value)Returns a new array with the value appended.Example:append([], "Alice")Returns:["Alice"]Parameters:array(array);value(any value)Return type:arrayReturns a copy and never mutates the input array.Arrays are limited to 256 elements.contains_value(collection, value)Returns true when a scalar collection element equals the supplied value.Example:contains_value(local.names, "Alice")Returns:trueParameters:collection(array);value(string, number, boolean, or null)Return type:booleanValues are compared without changing their types. Object and array elements are skipped.empty(value)Returns true when the value is null or an empty string.Example:empty($chat_content)exists(value)Returns true when the value is not null.Example:exists(global.last_help_player)coalesce(a, b, ...)Returns the first non-null value.Example:coalesce(global.help_count, 0)
Lookup
Find structured information, such as a player record. Lookups can return null when no unique result exists.
player(name_or_id)Returns a structured player object for the matching current player name or stored identifier. Assign the result to a local before reading properties like local.pinfo.name.Example:SET local.pinfo = player($player.name)Parameters:name_or_id(string)Return type:object(nullable)return.id - Stable RAT player identifier.return.name - Current player display name.return.platform_id - Primary platform identifier reported by the game.return.cross_platform_id - Cross-platform identifier when available.return.steam_id - Steam user identifier when available.return.eos_id - Epic Online Services identifier when available.return.xbl_id - Xbox Live identifier when available.return.platform_family - Primary platform family.return.platform_user_id - User-id portion of the primary platform identifier.return.cross_platform_family - Cross-platform identifier family.return.cross_platform_user_id - User-id portion of the cross-platform identifier.return.entity_id - Current in-game entity identifier.return.online - True when RAT currently considers the player online.return.last_seen_at - Last known UTC observation time in RFC3339 format.return.ip_address - Most recently observed IP address.return.level - Current player level.return.health - Current health value.return.stamina - Current stamina value.return.score - Current score.return.ping - Current network latency in milliseconds.return.deaths - Recorded death count.return.zombie_kills - Recorded zombie kill count.return.player_kills - Recorded player kill count.return.total_play_time_seconds - Recorded total play time in seconds.return.credits - Current RAT credits balance.return.ban_active - True when the player has an active ban.return.ban_reason - Current ban reason when available.return.ban_until - Current ban expiration in UTC when available.return.group - Effective RAT player group.return.group.id - Effective group identifier.return.group.name - Effective group display name.return.group.max_teleport_destinations - Maximum saved teleport destinations.return.group.teleport_cooldown_seconds - Teleport cooldown in seconds.return.position - Last known player position.return.position.x - World X coordinate.return.position.y - World Y coordinate.return.position.z - World Z coordinate.
Math
Calculate, round, limit, or randomly select numeric values.
abs(value)Returns the absolute numeric value.Example:abs(-10)min(a, b, ...)Returns the smallest numeric value.Example:min(1, 2, 3)max(a, b, ...)Returns the largest numeric value.Example:max(1, 2, 3)round(value)Rounds a number to the nearest whole value.Example:round(12.5)floor(value)Rounds a number down.Example:floor(12.5)ceil(value)Rounds a number up.Example:ceil(12.5)clamp(value, min, max)Clamps a number into the provided range.Example:clamp(global.score, 0, 100)chance(percent)Returns true with the requested percentage probability from 0 through 100.Example:chance(25)Returns:true or falseParameters:percent(number)Return type:boolean`percent` may be fractional and must be between 0 and 100 inclusive.`chance(0)` is always false and `chance(100)` is always true.is_between(value, min, max)Returns true when a number is inclusively between the supplied minimum and maximum.Example:is_between($player.level, 10, 25)Returns:trueParameters:value(number);min(number);max(number)Return type:booleanBoth boundaries are inclusive.A minimum greater than the maximum is a runtime error.
Player
Read player status, groups, distances, positions, areas, balances, and leaderboard information.
player_has_group(player_ref, group_ref)Returns true when the uniquely resolved player's effective RAT group matches the supplied group ID or display name.Example:player_has_group($player.id, "VIP")Returns:trueParameters:player_ref(string);group_ref(string)Return type:boolean`player_ref` uses the same unique player resolution rules as `player(...)`.`group_ref` matches either the effective group ID or display name, case-insensitively.The default group counts as the player's effective group. Unresolved or ambiguous players return false.player_exists(player_ref)Returns true when the reference uniquely resolves to a stored player.Example:player_exists("Steam_76561197970441157")Returns:trueParameters:player_ref(string)Return type:booleanAccepts a RAT player ID, unique display name, platform ID, Steam ID, EOS ID, or Xbox ID.Returns false when there is no match or more than one player matches.player_online(player_ref)Returns true when RAT currently considers the uniquely resolved player online.Example:player_online($player.id)Returns:trueParameters:player_ref(string)Return type:booleanUses RAT's current stored online state for the uniquely resolved player.Unresolved or ambiguous players return false.player_banned(player_ref)Returns true when the uniquely resolved player has an active ban.Example:player_banned($player.id)Returns:falseParameters:player_ref(string)Return type:booleanReturns the active-ban state for the uniquely resolved player.Unresolved or ambiguous players return false.player_distance(player_a, player_b)Returns the unrounded three-dimensional distance between two players' latest known positions, or null when unavailable.Example:player_distance($player.id, "TargetPlayer")Returns:312.47Parameters:player_a(string);player_b(string)Return type:number(nullable)Calculates Euclidean distance using unrounded X, Y, and Z coordinates.Returns null when either player is unresolved, ambiguous, or lacks a complete known position.player_distance_from(player_ref, x, y, z)Returns the unrounded three-dimensional distance from a player's latest known position to the supplied coordinates, or null when unavailable.Example:player_distance_from($player.id, 1250, 70, -840)Returns:84.32Parameters:player_ref(string);x(number);y(number);z(number)Return type:number(nullable)Calculates Euclidean distance using the player's unrounded X, Y, and Z coordinates.Returns null when the player is unresolved, ambiguous, or lacks a complete known position.Coordinates must be finite numbers.player_in_area(player_ref, x1, y1, z1, x2, y2, z2)Returns true when a player's latest known position is inside or on the boundary of the 3D box defined by two opposite corners.Example:player_in_area($player.id, 1200, 60, -900, 1300, 100, -800)Returns:trueParameters:player_ref(string);x1(number);y1(number);z1(number);x2(number);y2(number);z2(number)Return type:booleanThe two coordinate triples are opposite corners of an axis-aligned 3D box.Corner order does not matter, and all six boundaries are inclusive.Returns false when the player is unresolved, ambiguous, or lacks a complete known position.Coordinates must be finite numbers.in_area(inner_x1, inner_y1, inner_z1, inner_x2, inner_y2, inner_z2, outer_x1, outer_y1, outer_z1, outer_x2, outer_y2, outer_z2)Returns true when the first 3D box is entirely inside or on the boundary of the second 3D box.Example:in_area(1210, 65, -890, 1290, 95, -810, 1200, 60, -900, 1300, 100, -800)Returns:trueParameters:inner_x1(number);inner_y1(number);inner_z1(number);inner_x2(number);inner_y2(number);inner_z2(number);outer_x1(number);outer_y1(number);outer_z1(number);outer_x2(number);outer_y2(number);outer_z2(number)Return type:booleanEach pair of coordinate triples defines opposite corners of an axis-aligned 3D box.Corner order does not matter, and containment includes all six boundaries.Partial overlap is not containment and returns false.Coordinates must be finite numbers.player_leaderboard(metric, limit, row_template?, separator?)Returns a formatted leaderboard using current stored player data. The default row template is "{rank}. {player.name} - {formatted_value}".Example:player_leaderboard("zombie_kills", 10, "#{rank} {player.name}: {formatted_value}", "\n")Parameters:metric(string);limit(number);row_template(string, optional);separator(string, optional)Return type:stringAvailable metrics:deaths - Recorded death count.zombie_kills - Recorded zombie kill count.player_kills - Recorded player kill count.total_play_time_seconds - Recorded total play time.score - Current recorded score.level - Current recorded player level.credits - Current RAT credits balance.Available row-template fields:{rank} - One-based ordinal rank.{metric} - Canonical leaderboard metric key.{metric_label} - Human-readable metric label.{value} - Raw numeric metric value.{formatted_value} - Metric-aware display value.{player.id} - Stable RAT player identifier.{player.name} - Current player display name.{player.online} - Whether RAT currently considers the player online.{player.level} - Current player level, or blank when unavailable.{player.score} - Current score, or blank when unavailable.{player.deaths} - Recorded death count, or blank when unavailable.{player.zombie_kills} - Recorded zombie kill count, or blank when unavailable.{player.player_kills} - Recorded player kill count, or blank when unavailable.{player.total_play_time_seconds} - Recorded total play time in seconds, or blank when unavailable.{player.credits} - Current RAT credits balance.{player.last_seen_at} - Last known UTC observation time, or blank when unavailable.player_leaderboard_entry(metric, position)Returns one structured leaderboard entry, or null when that position has no eligible player. Assign the result to a local before reading its properties.Example:player_leaderboard_entry("zombie_kills", 1)Parameters:metric(string);position(number)Return type:object(nullable)return.rank - One-based ordinal rank.return.metric - Canonical leaderboard metric key.return.metric_label - Human-readable metric label.return.value - Raw numeric metric value.return.formatted_value - Metric-aware display value.return.player - Ranked player.return.player.id - Stable RAT player identifier.return.player.name - Current player display name.return.player.platform_id - Primary platform identifier reported by the game.return.player.cross_platform_id - Cross-platform identifier when available.return.player.steam_id - Steam user identifier when available.return.player.eos_id - Epic Online Services identifier when available.return.player.xbl_id - Xbox Live identifier when available.return.player.platform_family - Primary platform family.return.player.platform_user_id - User-id portion of the primary platform identifier.return.player.cross_platform_family - Cross-platform identifier family.return.player.cross_platform_user_id - User-id portion of the cross-platform identifier.return.player.entity_id - Current in-game entity identifier.return.player.online - True when RAT currently considers the player online.return.player.last_seen_at - Last known UTC observation time in RFC3339 format.return.player.ip_address - Most recently observed IP address.return.player.level - Current player level.return.player.health - Current health value.return.player.stamina - Current stamina value.return.player.score - Current score.return.player.ping - Current network latency in milliseconds.return.player.deaths - Recorded death count.return.player.zombie_kills - Recorded zombie kill count.return.player.player_kills - Recorded player kill count.return.player.total_play_time_seconds - Recorded total play time in seconds.return.player.credits - Current RAT credits balance.return.player.ban_active - True when the player has an active ban.return.player.ban_reason - Current ban reason when available.return.player.ban_until - Current ban expiration in UTC when available.return.player.group - Effective RAT player group.return.player.group.id - Effective group identifier.return.player.group.name - Effective group display name.return.player.group.max_teleport_destinations - Maximum saved teleport destinations.return.player.group.teleport_cooldown_seconds - Teleport cooldown in seconds.return.player.position - Last known player position.return.player.position.x - World X coordinate.return.player.position.y - World Y coordinate.return.player.position.z - World Z coordinate.credits_balance(player_ref)Returns the current credits balance for the resolved player, or null when no unique player match is found.Example:credits_balance($player.name)
String
Build, search, normalize, split, format, and join text or scalar collections.
join(collection, separator)Renders scalar collection elements joined by the separator.Example:join(local.names, ", ")Returns:Alice, BobParameters:collection(array);separator(string)Return type:stringEvery element must be a scalar value; objects and nested arrays are rejected.format(template, value1, value2, ...)Formats a string with numbered placeholders like {0} and {1}.Example:format("Player {0} said {1}", $player.name, $chat_content)contains(value, search)Returns true when the plain-text search value appears within the source string.Example:contains(lower($chat_content), "!help")contains_any(value, search1, search2, ...)Returns true when any supplied plain-text search value appears within the source string.Example:contains_any(lower($chat_content), "help", "admin", "support")Returns:trueParameters:value(string);search1(string);search2...(string, optional)Return type:booleanSearches are plain text and case-sensitive; use `lower(...)` when case should be ignored.At least one search value is required. An empty search value matches every string.equals_ignore_case(a, b)Returns true when two rendered strings are equal without case sensitivity.Example:equals_ignore_case($chat_content, "!HELP")Returns:trueParameters:a(string);b(string)Return type:booleanRenders both values as strings and compares them with Unicode-aware case folding.matches(value, pattern)Returns true when the string matches a bounded RE2 regular expression.Example:matches($chat_content, "^![a-z_]+$")Returns:trueParameters:value(string);pattern(string)Return type:booleanUses Go's RE2 syntax, which does not support backreferences or look-around assertions.Input is limited to 8192 characters and the pattern to 512 characters.Invalid patterns and oversized values are runtime errors.starts_with(value, prefix)Returns true when the source string begins with the provided prefix.Example:starts_with($player.name, "[Admin]")ends_with(value, suffix)Returns true when the source string ends with the provided suffix.Example:ends_with($player.name, "_bot")lower(value)Converts a string to lowercase using culture-invariant rules.Example:lower($player.name)upper(value)Converts a string to uppercase using culture-invariant rules.Example:upper($player.name)trim(value)Trims leading and trailing whitespace.Example:trim($chat_content)trim_start(value)Trims leading whitespace.Example:trim_start($chat_content)trim_end(value)Trims trailing whitespace.Example:trim_end($chat_content)replace(value, from, to)Replaces the first plain-text match in a string.Example:replace($chat_content, " ", " ")replace_all(value, from, to)Replaces every plain-text match in a string.Example:replace_all($chat_content, " ", " ")substring(value, start, length?)Returns a substring from the provided start index, optionally limited by length.Example:substring($chat_content, 0, 24)length(value)Returns the rendered string length.Example:length($chat_content)concat(a, b, ...)Concatenates rendered values into a single string.Example:concat($player.name, ": ", $chat_content)left(value, count)Returns the leftmost count characters from a string.Example:left($player.name, 3)right(value, count)Returns the rightmost count characters from a string.Example:right($player.name, 3)pad_left(value, length, pad?)Pads a string on the left to the requested width.Example:pad_left($player.name, 12, ".")pad_right(value, length, pad?)Pads a string on the right to the requested width.Example:pad_right($player.name, 12, ".")index_of(value, search)Returns the first zero-based index of a substring or -1 when absent.Example:index_of($chat_content, "!")last_index_of(value, search)Returns the last zero-based index of a substring or -1 when absent.Example:last_index_of($chat_content, "!")pluralize(count, singular, plural?)Returns singular when count equals 1; otherwise returns the supplied plural or singular with s appended.Example:pluralize($players_online, "player", "players")Returns:playersParameters:count(number);singular(string);plural(string, optional)Return type:stringReturns `singular` only when count equals exactly 1.When `plural` is omitted, the default is `singular` with `s` appended.The function returns the selected word only; it does not include the count.
Teleport
Manage teleport destinations and move players. These functions perform live game actions.
tp_dc(player_ref)Returns the player's current teleport destination count. Unresolved players return 0.Example:tp_dc($player.name)tp_mdc(player_ref)Returns the player's maximum teleport destination count. Unresolved players return 0.Example:tp_mdc($player.name)tp_list(player_ref)Returns teleport destinations as newline-delimited text: name => (x, y, z[, dir]). Unresolved players return an empty string.Example:tp_list($player.name)tp_add(player_ref, destination, x, y, z, direction?)Adds or updates a saved teleport destination for the resolved player.Example:tp_add($player.name, "home", 10, 65, -2, "n")tp_remove(player_ref, destination)Removes a saved teleport destination for the resolved player.Example:tp_remove($player.name, "home")tp_go(player_ref, destination)Teleports the resolved player to a saved destination. Missing destinations are ignored.Example:tp_go($player.name, "home")tp_to(player_ref, x, y, z, direction?)Teleports the resolved player to explicit coordinates.Example:tp_to($player.name, 100, 70, -100, "e")tp_to_ground(player_ref, x, z, direction?)Teleports the resolved player to x/z using y=-1.Example:tp_to_ground($player.name, 100, -100, "s")tp_to_player(player_ref, target_player_ref)Teleports the resolved player to another player's current position.Example:tp_to_player($player.name, "TargetPlayer")tp_offset(player_ref, dx, dy, dz)Teleports the resolved player by an integer offset from their current position.Example:tp_offset($player.name, 0, 1, 0)
Time
Convert durations and compare stored timestamps with the current event time.
duration_seconds(value)Parses a non-negative duration such as 30s, 5m, or 2h and returns its length in seconds.Example:duration_seconds("5m")Returns:300Parameters:value(string)Return type:numberUses duration units such as `ms`, `s`, `m`, and `h`; units may be combined, as in `1h30m`.Negative and invalid durations are runtime errors. Fractional seconds are preserved.elapsed_seconds(datetime)Returns seconds elapsed between an RFC3339 timestamp and the current event time.Example:elapsed_seconds($player.last_seen_at)Returns:3600Parameters:datetime(string)Return type:number(nullable)`datetime` must use RFC3339. Null input returns null.Uses the event's `$current_datetime`, so previews are evaluated relative to their selected occurrence time.Future timestamps produce negative results.
13. Limits and failure behavior
- A single
wait(...)is limited to 60,000 ms. - One logical execution may live for at most 10 minutes and suspend at most 16 times.
- The process accepts at most 256 pending waits. Pending waits are not persisted across restart or shutdown.
- Telnet capture defaults to a one-second response timeout and is capped at 64 lines or 16 KiB.
- Native arrays may contain at most 256 elements and may nest at most 16 levels deep.
- One logical execution may run at most 1,000 loop iterations in total, including nested loops and resumed waits.
- Reusable-function recursion is rejected during validation.
- A runtime error stops the current definition only. Other definitions for the event continue in order.
- Preview simulates side effects and persistent mutations; it does not send live commands or messages.
14. Complete examples
Welcome every currently online player
$players is a snapshot taken when this script starts. This example sends one message per online player.
for each local.player in $players
gs_broadcast(format("Welcome, {0}!", local.player.name), "say")
end
Persistent chat-command counter
Event type: chat.global_message
set local.message = lower(trim($chat_content))
if local.message == "!status" then
set global.status_uses = coalesce(global.status_uses, 0) + 1
gs_broadcast(
format("Server: {0}; players: {1}/{2}; uses: {3}",
gs_status(), $players_online, $players_max, global.status_uses),
"say"
)
end
Discord reply with a safe mention
Event type: discord.message_received
if equals_ignore_case(trim($chat_content), "!ack") then
discord_reply(
$discord_channel_id,
$discord_message_id,
format("{0} acknowledged", discord_mention_user($discord_author_id)),
false
)
end
Leaderboard announcement
set local.board = player_leaderboard("zombie_kills", 10)
discord_send("general", local.board)
Check whether a player position is in an area
This example can be used with a player event such as player.spawned_in_world. player_in_area(...) checks the player's latest known position when that event runs. It does not continuously monitor the area between events.
if player_in_area($player.id, 1200, 60, -900, 1300, 100, -800) then
log(format("{0} is inside the protected area", $player.name))
end
Check whether one area fits inside another
in_area(...) compares two boxes rather than looking up a player. The first six coordinates define the box being tested; the final six define the containing box. Touching the boundary is allowed, but partial overlap returns false.
if in_area(
1210, 65, -890, 1290, 95, -810,
1200, 60, -900, 1300, 100, -800
) then
log("The proposed area fits inside the protected area")
end
Safe player lookup
set local.pinfo = player($player.name)
if exists(local.pinfo.id) then
debug(format("Resolved {0} as {1}", local.pinfo.name, local.pinfo.id))
else
debug(format("Could not uniquely resolve {0}", $player.name))
end