Skip to content

Server API

A game mode is a Lua script the server runs: it defines the callbacks it cares about (OnPlayerConnect, OnPlayerDamage …) and calls the functions below to act. Every name here has its own page with the syntax, the arguments and their types, what it returns and an example. New to it? Read the guides first, then come back to the index. The keys that name game things - items, souls, buffs, meshes, presets, clips - are listed in the reference.

Guide
Getting started what a game mode is, running one, the tick, ids and units, what happens on an error
Combat how a swing or a shot becomes damage, stamina, injuries, fights, teams - the model behind the combat callbacks
Constants every constant the API defines - colors, body parts, entity kinds, HUD alignments, the pose aliases
Parties parties with a leader, frames and invitations - what the server does by itself and the callbacks and functions a mode builds its party commands around
Topic
Server and timers 3 callbacks, 10 functions
Players 8 callbacks, 64 functions
Chat and commands 2 callbacks, 17 functions
Dirt and blood 1 callback, 6 functions
Vitals 18 functions
Combat 8 callbacks, 12 functions
Recipes 1 callback, 7 functions
Stats, skills, XP and perks 4 callbacks, 28 functions
Buffs and the drink 2 callbacks, 10 functions
Items and inventory 6 callbacks, 38 functions
GameText and HUD 29 functions
Compass markers 14 functions
Effects and sounds 3 functions
Map icons 10 functions
Script events 1 callback, 2 functions
State bags 9 functions
Storage and persistence 4 functions
The game mode’s database 1 function
World entities 14 functions
Carts 5 callbacks, 44 functions
Horses 10 callbacks, 36 functions
Props 1 callback, 10 functions
Siege engines 6 callbacks, 14 functions
Dogs 7 functions
Voice chat 4 callbacks, 21 functions
NPC actors 11 callbacks, 62 functions
Actor life 5 callbacks, 22 functions
Zones 4 callbacks, 15 functions
The world - clock, weather, terrain, the navmesh, the geometry 24 functions
Doors and containers 7 callbacks, 47 functions
Herbs and mushrooms 1 callback, 11 functions
Sound files 1 callback, 7 functions
Accounts, admins, bans and the audit 3 callbacks, 11 functions
Gates 1 callback, 5 functions
Level layers 6 functions
The map’s areas 3 callbacks, 20 functions
The server’s map 3 callbacks, 45 functions
Catalogues 10 functions
Parties 7 callbacks, 23 functions
Shops and vendors 5 callbacks, 22 functions
Dialogue 1 callback, 3 functions
Emotes 1 callback, 7 functions
Looks and character creation 1 callback, 8 functions
Dice 2 callbacks, 4 functions
Carry items 3 callbacks, 13 functions
Carrying 5 callbacks, 18 functions
Discovery - the map and the places a player found 2 callbacks, 8 functions
Interface 6 functions
Pickpocketing 3 callbacks, 10 functions
Web interface 3 callbacks, 13 functions
Web surfaces 3 callbacks, 9 functions
Key bindings 1 callback, 1 function
Key hints 4 functions
Quests 16 functions
The game’s texts 7 functions
The Codex 5 functions
The game’s screens 1 callback, 5 functions
Beds and sleep 1 callback, 3 functions

The mode’s own lifecycle, the server’s facts, timers and the log. Everything a mode does happens on the simulation thread, one tick at a time, thirty times a second - the callbacks run inside a tick, the timers run in the tick they fall due, and a slow callback delays the tick for every player (Getting started).

Callback When
OnGameModeInit The script is loaded and the API is ready - the place to create zones, HUD texts, timers and actors.
OnGameModeExit The server shuts down or the mode is about to be reloaded.
OnTick Every simulation tick, with the time since the last one.
Function What it does
SetGameModeText Names the mode in the server log and the server browser.
GetServerTick The number of the simulation tick being processed.
GetServerTime The server’s clock in milliseconds.
GetMaxPlayers How many players the server holds ([server] max_players).
GetLevel The name of the level the server runs.
GetLevelName The level as a player reads it.
Log Writes a line to the server log, prefixed [lua].
SetTimer Calls a function after a delay, once or repeatedly.
KillTimer Stops a timer.
ReloadGameMode Reloads this mode at the end of the tick, without restarting the server.

A player is a pid from 0 to GetMaxPlayers() - 1, given at the handshake and reused after a disconnect: keep the pid while a player is on, and check IsPlayerConnected before trusting a pid kept across ticks. Readers return nil for a pid that is not connected; setters return false. Positions are metres, yaw is degrees (0 = facing +Y, counter-clockwise); a mounted player’s position and velocity are the horse’s.

Callback When
OnPlayerStanceChange A player crouched, stood up, got into a saddle or sat down in a cart.
OnPlayerVisorChange A player closed or opened their helmet’s visor.
OnPlayerSeatChange A player sat down on a bench, a chair or a bed of the level, stood up, lay down or got up.
OnPlayerConnect The handshake is done and the client is loading the level.
OnPlayerRequestSpawn The client’s level is ready - decide where the player spawns, or hold them.
OnPlayerSpawn The player stands in the world and the others see them.
OnPlayerDisconnect The player is gone.
OnPlayerInteractPlayer The player pressed the use key on another player whose prompt they see.
Function What it does
GetPlayers Everyone who passed the handshake, in join order.
GetPlayersInRange The players in the world within a radius of a point, nearest first.
GetPlayerCount How many players are connected.
ForEachPlayer Calls a function for every connected player, in join order.
GetPlayerName The player’s name, as they joined.
GetPlayerUid The player’s id on this server - the same at every join from their game, theirs alone.
GetPlayerByUid The player online with this id.
GetPlayerSteamId The player’s Steam ID, as their game reports it.
GetPlayerHwid The player’s PC on this server - for bans a new name, address or reinstall does not get around.
GetPlayerHardware The parts of the player’s PC by name - for a database with a column per part.
CompareHwid How many parts two PCs share - 0 to 4.
GetPlayersByHwid The players online on one PC - a banned PC’s other names.
GetPlayerId The player a command names - a pid, a name or a fragment of one - or nil and why.
IsPlayerConnected Whether a pid belongs to a connected player.
IsPlayerInWorld Whether the player is spawned and replicated.
GetPlayerPing The player’s round trip to the server in milliseconds.
GetPlayerMods The mods the player’s game loaded - its Steam Workshop items and the folders of its Mods folder.
GetPlayerIP The player’s address.
GetPlayerPos The player’s position of record.
GetPlayerYaw The direction the player faces, in degrees.
GetPlayerVelocity The player’s velocity in metres per second.
SetPlayerPos Moves the player’s game to a point - a teleport.
SetPlayerFlying Lets the player fly - or lands them.
IsPlayerFlying Whether the player flies (SetPlayerFlying).
SetPlayerThirdPerson Gives a player the third-person view - or keeps them in first person.
GetPlayerThirdPerson The third-person view the mode gave a player (SetPlayerThirdPerson).
SetSpawnInfo Where and as what the player’s next spawn happens.
SpawnPlayer Spawns - or respawns - the player at their SetSpawnInfo point.
GetDefaultSpawn The server’s spawn point from server.toml.
AddSpawnPoint Remembers a spawn point under a tag.
GetSpawnPoints The spawn points of a tag.
GetRandomSpawnPoint One spawn point of a tag, at random.
ClearSpawnPoints Forgets the spawn points of a tag.
TogglePlayerControllable Holds or releases the player’s keyboard.
SetPlayerCamera Puts the player’s view at a point, looking at another - a cutscene, a view over a town.
ResetPlayerCamera Gives the player their own view back.
IsPlayerCameraSet Whether the mode’s camera holds the player’s view.
IsPlayerControllable Whether the player’s keyboard is theirs right now.
Kick Disconnects the player with a reason.
SetPlayerNameplate The label over the player’s body on every other screen.
GetPlayerNameplate The label as the mode set it.
SetPlayerNameplateFor What one player alone sees over another player’s body - a name they were told, a rank only they know.
GetPlayerNameplateFor The text one player alone sees over another’s body, as the mode set it.
SetPlayerNameplateHidden Hides the label over a player’s body on every other screen, or shows it again.
IsPlayerNameplateHidden Whether the label over a player’s body is hidden.
SetPlayerInvisible Makes a player invisible to every other player, or seen again.
IsPlayerInvisible Whether a player is invisible to other players.
SetPlayerInvisibleFor Hides a player from one viewer, or shows them to one viewer while they are invisible to the rest.
IsPlayerVisibleTo Whether one player sees another.
GetPlayerStance How a player stands - on their feet, crouching, in a saddle or in a cart seat.
IsPlayerCrouching Whether a player is crouching.
IsPlayerVisorDown Whether a player’s helmet visor is down.
GetPlayerSeat The bench, chair or bed of the level a player sits or lies on.
SetPlayerPrompt A use prompt over a player - “[E] Talk” under their name, and the use key on them reaches the mode.
GetPlayerPrompt The use prompt everyone sees over a player (SetPlayerPrompt).
IsPlayerPromptHidden Whether the use prompt everyone sees over a player is hidden (SetPlayerPrompt’s hidden).
SetPlayerPromptFor The use prompt one viewer alone sees over a player.
GetPlayerPromptFor The use prompt one viewer alone sees over a player (SetPlayerPromptFor).
SetPlayerColor The color of the player’s label and of their name in the Tab roster.
GetPlayerColor The player’s color as set.
SetPlayerTeam Puts the player in a team - teammates cannot hurt each other.
GetPlayerTeam The player’s team.
GetPlayerVirtualWorld The virtual world the player is in.
SetPlayerVirtualWorld Moves the player into another virtual world.

Every chat line a player types passes through the mode before anyone sees it: a plain line through OnPlayerText, a / line through OnPlayerCommandText. A / line the mode does not answer goes to the server’s own built-in commands (/help, /pos, /give, /tp, /horse …), then to Unknown command; a mode overrides a built-in by handling its name. /fight and /peace are the server’s and are answered before the mode sees them; /mute and /unmute are every player’s whatever [commands] says, unless the mode handles them itself. The mode’s own lines go out with SendClientMessage, SendClientMessageInRange and SendClientMessageToAll.

What a player types is cleaned and rationed by the server before the mode sees it - no invisible or direction-changing characters, no stacks of accents, no flood of lines - so a mode’s own filters start from a tidy line; OnPlayerText has the details.

Beyond plain lines and commands, a mode can shape the chat itself:

  • Messages - SendChatMessage and SendChatMessageToAll send a line made of pieces that differ in colour, weight and slant (spans), on a channel of the mode’s choice; ClearPlayerChat empties a player’s chat.

  • Channels - RegisterChatChannel adds a channel - Trade, Staff, a guild’s - that only some players see or may write into; what a player types on a channel goes to the players who see it. UnregisterChatChannel takes one away and RefreshChatChannels tells the players’ chats to look again after a rule of the mode changed.

  • Commands - RegisterCommand gives a command its handler, its help line, its usage and its admin or secret mark in one call; a chat that can suggest offers the command while the player types it. AddChatSuggestion and RemoveChatSuggestion do the same for commands the mode still answers in OnPlayerCommandText. UnregisterCommand takes one away.

  • Where it sits and how big it is - the chat is a component of the interface: SetPlayerInterfaceOptions (one player) and SetInterfaceOptionsForAll (everyone) move it to any corner or edge (anchor, margin_x, margin_y), size it (width, lines from 4 to 20, font_scale) and set its backing; SetPlayerInterface hides it or hands it to a web page. Change the interface has every option, with an example:

    -- the chat in the top-right corner, eight lines, for everyone
    SetInterfaceOptionsForAll("chat", { anchor = "top-right", margin_x = 16, margin_y = 24, lines = 8 })

A line’s words are always there as plain text, so every chat can show every line; a chat that can style them - a chat built as a web page - draws the spans, the channel’s tab and the suggestions. The game’s own chat draws each line in one colour (the first span’s, when it has one, otherwise the line’s), puts the channel’s label in front of a line ([Trade] Henry: two loaves), has no channel picker - what a player types there is a line in the default channel - and no suggestion list.

Every list the mode builds here - channels, registered commands, suggestions - starts empty again after a reload, so a mode registers them where it is made again, in OnGameModeInit.

Callback When
OnPlayerText A plain chat line - return false and nobody sees it.
OnPlayerCommandText A / command - return true when the mode answered it.
Function What it does
sscanf The arguments of a command as typed values - a player, a number, a word, the rest of the line - in one call.
SendClientMessage A line in one player’s chat.
SendClientMessageToAll The same line in everyone’s chat.
SendClientMessageInRange The same line in the chat of everyone near a point - a role-play mode’s nearby chat.
SendChatMessage A chat message to one player - a text, or pieces that differ in colour, weight and slant.
SendChatMessageToAll The same message in everyone’s chat - on a channel, in the chat of the players who see it.
ClearPlayerChat Empties a player’s chat.
SetPlayerChatBubble A line over a player’s head, in a color of your own, for everyone near them.
RegisterChatChannel Adds a chat channel that only some players see or may write into.
UnregisterChatChannel Takes a chat channel away.
RefreshChatChannels Sends the channel list to a player’s chat again - for a rule of the mode that changed.
RegisterCommand Makes a /command with its handler, its help and its rules in one call.
UnregisterCommand Takes a registered command away.
AddChatSuggestion Suggests a command to the chats that can suggest one - for everyone, or for one player.
RemoveChatSuggestion Takes back a suggestion made with AddChatSuggestion.
SetPlayerChatVisible Shows or hides the chat on a player’s screen.
GetPlayerChatVisible Whether the chat shows on a player’s screen as far as the mode goes (SetPlayerChatVisible).

The game keeps a dirt level and the blood of six body zones ("head", "torso", "arm_left", "arm_right", "leg_left", "leg_right" - the list BLOOD_ZONES) on a player’s skin and on every piece of clothing they wear, each from 0 (clean) to 1. The road, a fight and a wash change them in the player’s own game, and every other player sees them on the body. The game’s own marks: the inventory shows “Dirt” from 0.5 and “Blood” from 0.25, a water trough offers its wash from 0.6.

A mode reads them as the player’s game last reported them (GetPlayerDirt, GetPlayerBlood, every value with GetPlayerGrime) and hears each change (OnPlayerGrimeChange). It changes them through the player’s game: WashPlayer is the game’s own wash (a bathhouse, a trough), SetPlayerDirt and SetPlayerBlood set a value. A part is "all" (the default: the skin and every piece worn), "skin", "clothes" (every piece worn) or one item - a class GUID, or a name the item catalogue knows - for the worn pieces of it. A change shows in the readers once the player’s game has applied it and reported it back, within a second. A piece put on within ten seconds of a change takes it too, so a mode that gives the clothes at the spawn (SetPlayerInventory) can set their dirt in the same breath.

Callback When
OnPlayerGrimeChange A player’s dirt or blood changed.
Function What it does
GetPlayerDirt How dirty a player is - their skin and their dirtiest piece of clothing.
GetPlayerBlood How bloody a player is - their skin and their bloodiest piece of clothing.
GetPlayerGrime Every dirt and blood value of a player - the skin and each worn piece.
SetPlayerDirt Sets a player’s dirt - on their skin, their clothes or one piece.
SetPlayerBlood Sets a player’s blood at one body zone or all of them - on their skin, their clothes or one piece.
WashPlayer Washes a player with the game’s own wash - every dirt and blood value to 0.

The server owns every player’s health, stamina, injuries and bleeding ([combat] in server.toml; the Combat guide has how a hit becomes damage). Health and stamina are full at every spawn; 0 health is dead until the respawn. The character’s stats, skills, XP and perks are a group of their own, from SetPlayerStat on.

Function What it does
GetPlayerHealth The player’s health.
GetPlayerMaxHealth The player’s maximum health (100).
SetPlayerHealth Sets the player’s health; 0 kills.
IsPlayerDead Whether the player’s health is 0 and they wait for the respawn.
GetPlayerStamina The player’s stamina - the bar they see.
GetPlayerMaxStamina The player’s maximum stamina ([combat] max_stamina).
SetPlayerStamina Sets the player’s stamina.
GetPlayerInjuries The player’s injured body parts.
IsPlayerInjured Whether the player has an injury - anywhere, or on one part.
GetBodyPartName The name of a body part id.
GetPlayerBleeding How fast the player is bleeding, in health per second.
IsPlayerBleeding Whether the player is bleeding.
SetPlayerBleeding Sets how fast the player bleeds, in place of their open wounds.
SetBleedRules How cuts bleed on this server - the rate, how long, and how much armour holds.
GetBleedRules The bleeding’s rules in force.
SetPerkEffects The game’s health perks on this server - Revenant’s regeneration, Diehard’s save from a killing blow and the prayer’s Guardian Angel.
GetPerkEffects The health perks’ rules in force.
HealPlayer Makes the player whole - health, stamina, injuries, bleeding, buffs, drink.

A player’s game only reports what its swing or its arrow hit; the server decides what that did and tells the mode. The Combat guide walks through the model - the tables, stamina, injuries and bleeding, perfect blocks, master strikes and clinches, fights and the lock-on, teams and pvp. The callbacks let a mode change or cancel every hit; the functions manage fights.

Callback When
OnPlayerDamage The server accepted a hit on a player - change the damage, cancel it, or let it through.
OnPlayerInjury A hit injured one of the player’s body parts.
OnPlayerDeath The player’s health reached 0.
OnPlayerLootBody A player wants to search a dead player’s body - return false to refuse.
OnPlayerCorpse A dead player respawns and their body stays behind as a corpse - fill it here if it should hold anything.
OnFightStart Two players are in a fight from now on.
OnFightEnd A fight between two players is over.
OnPlayerHitScenery A player’s melee blow struck the level itself - a tree, a rock, a wall.
Function What it does
SetPlayerCanAttack Keeps a player from attacking at all, or lets them again.
CanPlayerAttack Whether the player may attack.
StartFight Puts two players in a fight so their games can lock on to each other.
EndFight Ends the fight between two players.
AreFighting Whether two players are in a fight right now.
GetPlayerOpponents Everyone the player is fighting right now.
GetPlayerWeapon The weapon the damage model charges the player’s hits to.
GetPlayerHandItems What a player holds in their hands right now.
IsPlayerWeaponDrawn Whether a player has a weapon drawn.
GetCorpseItems What a corpse holds.
SetCorpseItems What a corpse holds from now on - the list anyone who searches it takes from.
RemoveCorpse Takes a corpse away now, with whatever it still holds.

The recipes a character knows are the ones the alchemy table’s book and the anvil’s book show - the recipes list has all of them, 31 alchemy recipes and 61 blacksmithing ones. In the game a character learns one by reading a recipe document; a game mode can also teach one itself (GivePlayerRecipe) - a recipe bought from the mode’s own shop, found in its own inventory system, earned in a quest - and take one away (RemovePlayerRecipe).

A recipe is named by its key ("alchemy:1", "smithing:r_axework02" - the first column of the list), by its English name ("Hair o' the Dog", any case; alchemy: or smithing: in front picks between two of one name) or by the class name of the document that teaches it ("recipe_hairodogPotion"). Every function that gives a recipe back gives its key; GetRecipeInfo says the rest. The server knows the recipes without the game’s tables export.

Saving them. Nothing is kept between visits unless the mode keeps it. OnPlayerLearnRecipe is the moment a player’s game taught them one - save it then - and SetPlayerRecipes puts the saved list back at the next login, exactly: every other recipe is taken away, also the ones the player’s game still holds from an earlier character (the game keeps the alchemy book for as long as it runs). GetPlayerRecipes lists what a character knows. A mode that teaches recipes its own way can refuse the game’s: return false from OnPlayerLearnRecipe and the recipe is taken away again (or hold the document’s reading before it happens with SetItemUseCheck).

A blacksmithing recipe is a perk of the character in the game, so it is in GetPlayerPerks too; an alchemy recipe learned from a document is not. Keep recipes with the recipe functions, not the perk ones.

Callback When
OnPlayerLearnRecipe The player’s game taught them a recipe - save it, or return false to take it away again.
Function What it does
GetRecipes Every recipe of the game - their keys, the alchemy ones first.
GetRecipeInfo A recipe’s key, kind, name, document and what it makes.
GetPlayerRecipes The recipes the player’s character knows.
HasPlayerRecipe Whether the player’s character knows a recipe.
GivePlayerRecipe Teaches the player’s character a recipe - the book shows it from now on.
RemovePlayerRecipe Takes a recipe from the player’s character - the book forgets it.
SetPlayerRecipes Exactly these recipes - the saved ones back at a login, every other one taken away.

A player’s progression is what the game’s character screen shows: the stats - strength, agility, vitality and speech, with the story’s storyprogress and the prestige of the Blacksmith - and the skills (marksmanship, weapon_sword, alchemy … thirty in all; the names), each with a level from 0 to 30 and the XP gathered toward the next one; the main level, the one figure the screen shows for the whole character; the perk points the levels bring and the perks a character earns (the perks); and two states of the character, the nourishment and the energy (the Rest). All of it is the game mode’s: a mode reads what a player has, sets any of it, decides whether and how much XP the players gain, and saves it with its character - the server keeps nothing between visits.

The record. The server keeps a record of each player’s progression as their game reports it - and, where the progression check acts under [audit] mode = "enforce" (below), as the server can explain it: a level, a perk or a number of perk points the moment it changes, XP and the two states within seconds, the whole of it again every minute and after every spawn. GetPlayerStat, GetPlayerSkill, GetPlayerLevel, GetPlayerPerkPoints, GetPlayerPerks and GetPlayerProgress read the record. A stat or skill it has not heard of yet reads as level 0, so a mode that saves a character waits for the player’s first report (OnPlayerProgressChange) before it trusts what it reads.

The main level. The game shows one level for the whole character and works it out itself from the levels of the stats and skills, so it is read only: GetPlayerLevel answers it (so does GetPlayerStat with mainlevel), and it rises and falls as the levels beneath it do, whether the player earned them or the mode set them. SetPlayerStat and AddPlayerStatXP refuse the name, and it gathers no XP. A rise the player earns reaches OnPlayerLevelUp as the stat mainlevel. storyprogress is another thing: the story’s own progress, a stat like the four core ones.

Perk points. The game gives a character perk points as its levels rise, and the player spends them on perks. Every stat and skill holds its own unspent points, and the main level holds a pool for the points that belong to no stat or skill. GetPlayerPerkPoints reads a count and SetPlayerPerkPoints sets it exactly, 0 .. 999, with the name mainlevel for the pool. GetPlayerProgress and SetPlayerProgress carry the points as points, and a change of points counts as a change of levels for OnPlayerProgressChange: something to save now.

Setting. SetPlayerStat, SetPlayerSkill and SetPlayerProgress are exact: the level and the XP are what they say, raising or lowering the character, with no level-up notice, and the record holds them at once. They are the only calls that lower a level. AddPlayerStatXP and AddPlayerSkillXP give XP the game’s own way - the notice, the perk points - and only ever raise. [spawn] stat_level in server.toml raises the four core stats to at least that level at every spawn (0, the default, leaves them alone; set it only for a mode that does not own the levels). A set made before the player is in the world - at the login - waits for their spawn and is applied right after it, in the order it was made. Every player who was not set starts as the level’s own character: level 5 in the four core stats and in most skills, level 0 in the rest, no perk points.

XP is off unless the mode turns it on. The game awards XP on its own - a kill, a hit, a distance walked, a book read. A server gives none of it to begin with: SetXPRate is how a mode turns it on (1 is the game’s own amounts, 0 none, up to 100), SetPlayerXPRate gives one player a rate of their own, and OnPlayerGainXP lets the mode judge each award. XP the mode hands out itself (AddPlayerSkillXP) does not pass through any of this. The shipped modes choose differently: freeroam.lua and the built-in freeroam set the rate to 1 and keep nothing of a player’s progress between visits, duel_arena.lua sets 0 so the duelists stay equal, and basicrp.lua sets 1 and saves everything with the character.

Saving a character. Read it with GetPlayerProgress - when OnPlayerProgressChange says a level, a perk or perk points changed, on a timer for the XP, and in OnPlayerDisconnect - and put it back with SetPlayerProgress when the player logs in. Never write before the restore has gone out (or, for a character with nothing saved yet, before the game’s first report has arrived): a player whose game has not reported reads as an empty record, and saving that over the stored character loses it. The snapshot holds the main level too, but the restore puts back only its pool of perk points: the level itself follows from the levels that were restored.

Names are lower case; case, spaces and hyphens are forgiven, and a few words the game’s menus use are understood: warfare (fencing), horsemanship (horse_riding), sword / swords (weapon_sword), polearm / polearms (weapon_large), unarmed (weapon_unarmed), dagger (weapon_dagger), shield (weapon_shield) and bow / archery (marksmanship). The stats are strength, agility, vitality, speech, storyprogress, prestige and the read-only mainlevel. A stat function given a skill’s name - or the other way round - refuses it; the perk points calls take either kind. A perk is its GUID, or with the game’s tables export (Exporting the game’s tables) its name or English name as the perks list spells them. A horse has stats too - SetHorseStat, in the Horses group.

The check. A trainer writes a level, XP, perk points, a perk, the nourishment or the energy into a player’s game as easily as a player earns them, so the server judges what the game reports against what it can explain: the XP the game awarded (the player’s game counts each award it makes and tells the server), what the mode gave (AddPlayerSkillXP, SetPlayerStat, SetPlayerProgress …), the potions the player drank, the perks they hold, and the perk points their levels pay. A rise nothing explains is an excess, and [audit] mode in server.toml decides what happens to it. With observe, the default, the server logs that it would put the excess back, asks OnPlayerProgressViolation for the XP and levels and changes nothing in the player’s game - and the record this group reads still follows the game’s report, a forged value included, so a mode that saves characters should run enforce before it trusts the record. With enforce it puts the excess back - the player’s game is told the figure the server can explain - and the record this group reads, and so what a mode saves, holds that figure: a forged value is never the one that is saved. A game that writes the same forged value back again and again after it was put back is cheating beyond doubt: OnPlayerCheatDetected hears progress_write_repeat as a proven one and [audit] action follows. Progress the server cannot see being earned - a teacher, a quest script, an event’s reward - is put back like any excess unless the mode vouches for it in OnPlayerProgressViolation; a server with story quests on that enforces must. Everything the mode itself orders - every set and every AddPlayerSkillXP - counts as the character’s from the moment it is sent, so a restore at the login is never an excess. The nourishment and the energy fall steadily with the game’s clock, so a value over its maximum is put back and one that stands still while the clock runs is judged too, and the carry weight is checked (GetPlayerWeight). This version acts only on the rules that are measured - an impossible XP or level, a clear rise (300 XP or more that nothing explains, over three times what the server explains or three levels above it - not with story quests on), perk points the levels do not pay for, a perk bought below its level or with points nothing paid for, a nourishment or an energy over its maximum; the rest is judged and logged as “would …”, puts nothing back, and reaches the mode at most as a hint in OnPlayerCheatDetected (the server configuration lists them). A set of the mode’s own that the player’s game did not confirm is sent again after about 45 seconds, in either mode. GetPlayerProgressAudit shows what the check counted for one player.

Callback When
OnPlayerGainXP The player’s game awarded XP on its own - return false to refuse it, or a number to give that much instead.
OnPlayerLevelUp The player earned a level in a stat or a skill, or a level of the character.
OnPlayerProgressChange The player’s game reported a change to their progression - the moment to save it.
OnPlayerProgressViolation The server found progress it cannot explain and is about to put it back - return false to vouch for it.
Function What it does
SetPlayerStat Sets a stat of the player’s character to a level, and the XP toward the next, exactly.
SetPlayerSkill Sets a skill of the player’s character to a level, and the XP toward the next, exactly.
GetPlayerStat The level of a stat, as the server last heard or set it.
GetPlayerSkill The level of a skill, as the server last heard or set it.
GetPlayerLevel The player’s main level - the level the game shows for the whole character.
GetPlayerStatXP The XP a stat has gathered toward its next level, and what that level takes.
GetPlayerSkillXP The XP a skill has gathered toward its next level, and what that level takes.
AddPlayerStatXP Gives a stat XP the game’s own way.
AddPlayerSkillXP Gives a skill XP the game’s own way.
GetPlayerPerkPoints The perk points a stat, a skill or the main level has not spent yet.
SetPlayerPerkPoints Sets the perk points a stat, a skill or the main level has not spent yet.
GetPlayerPerks The perks the player’s character holds.
HasPlayerPerk Whether the player’s character holds a perk.
AddPlayerPerk Gives the player’s character a perk.
RemovePlayerPerk Takes a perk from the player’s character.
GetPerkName The English name of a perk.
GetPlayerNourishment How well fed the player’s character is.
SetPlayerNourishment Sets how well fed the player’s character is.
GetPlayerEnergy How rested the player’s character is.
SetPlayerEnergy Sets how rested the player’s character is.
GetPlayerProgress Everything a mode saves with a character - stats, skills, perk points, perks, nourishment and energy.
SetPlayerProgress Puts a saved progression back on the player’s character - a whole restore.
GetPlayerWeight What the server judges the player carries, the most they may carry, and whether that is too much.
GetPlayerProgressAudit What the progression check counted for the player this session.
SetXPRate Sets how much of the XP the game awards on its own the players gain.
GetXPRate The server-wide XP rate.
SetPlayerXPRate Gives one player an XP rate of their own, over the server-wide one.
GetPlayerXPRate The XP rate that applies to a player.

A buff is the game’s own timed or permanent modifier on a character - a potion’s effect, an injury, drunkenness, a perk’s bonus. The server gives and takes them by id, name or GUID from the buff list; the player’s client adds the game’s buff once and removes it by GUID. The server also keeps a blood-alcohol level per player from the drinks their game consumed, and judges when they are drunk. A player’s game consuming anything - a potion, food, an ointment - goes through the server (OnPlayerUseItem), which applies the tables’ effect (Consumables).

Callback When
OnPlayerUseItem The player’s game used an item - a potion, food, a book, a letter, a map; return false to cancel its effect, or (for a checked item) the use itself.
OnPlayerDrunk The player got drunk, or sobered up.
Function What it does
GivePlayerBuff Gives the player a buff of the game’s tables.
RemovePlayerBuff Takes a buff off the player.
HasPlayerBuff Whether the server gave the player this buff and has not taken it back.
GetPlayerBuffs The buffs the server gave the player, as GUIDs.
ClearPlayerBuffs Takes every server-given buff off the player.
GetClaimedBuffClasses The buff classes the server has claimed.
ClaimBuffClasses Names the buff classes the server takes over from the game.
GetPlayerAlcohol The player’s blood-alcohol level, 0 to 1.
IsPlayerDrunk Whether the player is drunk.
SetPlayerAlcohol Sets the player’s blood-alcohol level; the drunk state is judged at once.

What a player carries, what the server gives them, and the pickups lying in the world. An item is named by any key of the item catalogue - the id, the game’s name, the English name or the class GUID; the client reports equipment and inventory as class GUIDs (GetItemName turns one into a name).

The server keeps the books. Every item a player carries has to be explained by a record the server holds: what it gave (GivePlayerItem, SetPlayerInventory, the spawn outfit), a pickup it placed, a take from a chest or a body, a shop, a drop picked up again, the game’s own making (OnPlayerNativeItem). The player’s game reports each change with where the item came from, and the server checks it against the records - under [audit] mode = "enforce" an item nothing explains is taken out of the player’s game, and a drop, a use, a shot or a sale of more than the records explain is refused (the configuration has what each mode does). The functions below read and write those records, not the game’s own list: what a mode gives or takes is in the records at once - a GetPlayerInventory right after a GivePlayerItem already shows the item, and a SetPlayerInventory called twice orders nothing twice - while the player’s game carries the order out a moment later. Under observe the readers show what the player’s game holds (the mode’s own gives and takes on their way counted), so an item a cheat tool conjured is visible there too.

Callback When
OnPlayerInventoryChange What the player carries or their purse changed - the moment to save it.
OnPlayerOutfitChange The player’s outfits changed - the moment to save them.
OnPlayerPickup The player picked a pickup up - return false to take it back.
OnPlayerDrop The player dropped an item and the world made a pickup of it.
OnPlayerItemWear One of the player’s items wore down or was mended.
OnPlayerCraft The player started a crafting station - the alchemy table, the anvil or the grindstone.
Function What it does
GetPlayerEquipment What the player wears and holds - clothing, armour, the weapons in the slots.
GetPlayerInventory The player’s whole inventory as the server’s records hold it.
SetPlayerInventory Makes the player’s inventory exactly this list - taking what they hold beyond it and giving what they miss.
EmptyPlayerInventory Takes every item the player holds - or all but what they wear.
GetPlayerOutfits The player’s three outfits - what each one wears and which one they wear now.
SetPlayerOutfits Hands the player’s three outfits back - after the bag’s restore, at a login.
GivePlayerItem Puts items in the player’s inventory - or takes them out.
GetPlayerItemHealth The condition of the player’s item of a class.
SetPlayerItemHealth Sets the condition of every item of a class the player carries.
GetPlayerItemQuality The quality of the player’s item of a class - I to IV.
SetPlayerItemQuality Sets the quality of every item of a class the player carries.
SetItemWear How fast items wear on this server.
GetItemWear The wear rate that applies to an item class, a kind or every item.
SetItemUseCheck Decide before the game uses an item - a book read, a letter opened, food eaten.
IsItemUseChecked Whether a use of the item waits for the mode’s word.
GivePlayerTaggedItem Gives the player one item with the mode’s own id, name and text - a letter, a contract, a key to one door.
SetPlayerItemTag Renames one of the player’s tagged items - a contract signed, a letter opened.
FindPlayerItem The player’s tagged item with that id.
SetPlayerItemWeight Gives one of the player’s tagged items a weight of its own - a heavy relic, a feather-light charm.
SetPlayerItemPrice Gives one of the player’s tagged items a price of its own - and puts it up for sale.
SetItemClassWeight Sets what every item of a kind weighs, for every player - lighter rocks, heavier armour.
GetItemClassWeight What an item of a kind weighs now - the mode’s rule, else the game’s own.
SetItemClassPrice Sets what every item of a kind is worth, for every player.
GetItemClassPrice What an item of a kind is worth now - the mode’s rule, else the game’s own.
DefineItem Makes an item of your own - a named item on one of the game’s, with its own price, weight, condition and look.
RemoveItemDefinition Removes one of your items - its pieces become the plain base item.
GetItemDefinition One of your items as it was defined.
GetItemDefinitions The names of all your items.
SetPlayerItemModel Gives one of the player’s tagged items the look of another item.
SetCraftCheck Decide before a crafting station starts.
IsCraftChecked Whether a crafting station’s start waits for the mode’s word.
GetPlayerMoney The player’s purse in Groschen, as far as the server stands behind it.
GivePlayerMoney Puts Groschen in the player’s purse - or takes them out.
CreatePickup Puts an item on the ground for everyone to see and anyone to take.
SetPickupHealth Sets the condition a pickup’s item has.
GetPickupHealth The condition of a pickup’s item.
SetPickupQuality Sets the quality a pickup’s item has.
GetPickupQuality The quality of a pickup’s item.

Two ways to put text on a player’s screen besides the chat: a GameText - one big line for a moment (“Round 3”, “You win”, a subtitle) - and a HUD text - a line the mode places at a fraction of the screen and keeps there, changing it whenever (a clock, a score, a timer). Both draw under the game’s own menus and vanish behind the loading screen. For anything richer a client script draws it.

Function What it does
GameText One big line on the player’s screen for a while.
GameTextForAll One big line on every screen.
CreateHudText A line of text at a screen position, shown to the players you choose.
DestroyHudText Removes a HUD text from every screen.
SetHudText Changes a HUD text’s text.
GetHudText A HUD text’s current text.
SetHudTextPos Moves a HUD text.
SetHudTextColor Recolors a HUD text.
SetHudTextScale Resizes a HUD text.
SetHudTextAlign Changes which side of a HUD text sits at its x.
ShowHudText Shows a HUD text on one player’s screen.
HideHudText Takes a HUD text off one player’s screen.
ShowHudTextForAll Shows a HUD text to everyone connected now.
HideHudTextForAll Takes a HUD text off every screen (the element stays for later).
IsHudTextShown Whether a HUD text is on a player’s screen.
GetHudTexts Every HUD text the mode has made.
ShowInfoText A line in the game’s own info slot under the compass.
ShowInfoTextForAll The info line on every screen.
HideInfoText Takes the info line down before its time.
ShowNotification The game’s short notification at the top of the screen.
ShowNotificationForAll The short notification on every screen.
ShowGameLog A line in the game’s log toast.
ShowGameLogForAll A log line on every screen.
ShowObjectiveEvent The quest-style banner - a title with a line under it.
ShowObjectiveEventForAll The banner on every screen.
ShowTutorial A tutorial box with a text that stays a while.
ShowTutorialForAll The tutorial box on every screen.
HideTutorial Takes a tutorial box down by its name.
SetPlayerHudVisible Shows or hides one of the game’s own HUD pieces - the compass, the health bars, the hints - on a player’s screen.

A compass marker is a point in the level a mode shows to the players it chooses, as a blip on the game’s own compass strip at the point’s bearing, drawn with the game’s quest symbol or its point-of-interest symbol. Like the HUD texts, a marker is shown to nobody until ShowMarker; a change to it is re-sent to everyone it is shown to; a shown marker survives its player’s respawns and goes with their disconnect; the mode’s markers go with a reload. Ids start at 1; there are 1024. The party members’ blips need no marker: the server puts them on the compass by itself ([ui] party_compass). The world map is the server’s call too: every player sees the whole map from the start unless [ui] map_fog keeps the game’s fog of war over what they have not walked, and then RevealPlayerMap lifts it for one of them.

Function What it does
CreateMarker A compass marker at a point, shown to the players you choose.
DestroyMarker Removes a marker from every compass and frees its id.
SetMarkerPos Moves a marker; everyone it is shown to sees it move.
SetMarkerKind Changes the symbol a marker is drawn with.
SetMarkerColor Changes a marker’s color.
SetMarkerText Changes a marker’s label.
GetMarkerInfo A marker’s point, kind, color and label.
ShowMarker Puts a marker on a player’s compass.
HideMarker Takes a marker off a player’s compass (the marker stays for later).
ShowMarkerForAll Puts a marker on every compass.
HideMarkerForAll Takes a marker off every compass.
IsMarkerShown Whether a marker is on a player’s compass.
GetMarkers Every marker the mode has made.
RevealPlayerMap Shows one player the whole world map, without the fog of war.

One-shot things at a point in the world for everyone nearby: a particle effect of the game’s own libraries (smoke, fire, sparks), a decal on the ground or a wall, a sound from the game’s audio triggers. They reach the players within [effects] range metres (150; 0 = everyone in that virtual world) and are fire-and-forget - a player who arrives later sees and hears nothing. Each returns how many players got it. A name the game does not know is not an error on the server: it only warns in the clients’ logs.

Function What it does
SpawnEffect Plays one of the game’s particle effects at a point for everyone nearby.
SpawnDecal Puts a decal of a material on whatever is at a point.
PlaySound Plays one of the game’s sounds at a point for everyone nearby.

The world map and the compass show the game’s own icons: towns, shops, services, camps. A mode puts icons of the same kind there - a player’s shop, a guild hall, a quest giver - with a type’s icon and legend name (CreateMapIcon), and takes the level’s own away where they mean nothing on its server - the tailor who no longer sells, a smithy that is a player’s house now (HideLevelMapIcons). Both are for everyone or for one player, and a player who joins later gets them at the spawn. They last for the server’s run: a mode makes them again in OnGameModeInit.

The types and every level’s own shop and service icons, with their ids and places, are on the map icons reference page. For a blip on the compass alone, see the compass markers.

Function What it does
CreateMapIcon An icon of the game’s own kind on the world map and the compass.
SetMapIcon An icon anew - moved, renamed, another type.
DeleteMapIcon Takes an icon off every map.
GetMapIcon An icon as it stands.
GetMapIcons Every icon of the mode’s, by id.
SetMapIconVisibleFor Shows an icon to one player, or hides it from them.
HideLevelMapIcons Hides some of the level’s own map icons from everyone.
HideLevelMapIconsFor Hides some of the level’s own map icons from one player.
ShowLevelMapIcons Takes a hiding rule away - its icons come back.
GetMapIconTypes The game’s map icon types.

A mode that needs something on the client the server cannot draw - a marker in the world, a sound, a bit of UI, a value read from the game - keeps a client script in the client/ folder next to itself (the server sends it to every player who joins) and talks to it through named events with a string payload, both ways: SendClientEvent down, SendServerEvent up into OnClientEvent. The payload is whatever string the two halves agree on - a number, a comma list, JSON. For values every client should simply know - a team, a round, a flag carrier - the state bags are the better fit. The marker example mode in the server folder is the round trip whole.

The limits count bytes of UTF-8, not characters - a Cyrillic or Chinese letter is two or three bytes. An event’s name is at most 64 bytes both ways; the payload is at most 60000 bytes from the server to a client and 4096 bytes from a client to the server. The server refuses a bigger event and never cuts it - a cut payload is broken JSON - so send large data in several smaller events. SendClientEvent says with false when it refused one, and the server log names the event (the first twenty refusals, then every hundredth).

A server with a web interface has a second listener for these events, and a second sender: its pages. An event of SendClientEvent also reaches every page whose events_in in ui.toml lets it receive the name (by default the names that start with the frame’s own name and a dot: shop.open for a frame called shop), and a page’s emitServer arrives in OnClientEvent with the frame’s name as its source. The payload may be a table, which travels as its JSON. The names that start with kcdmp: belong to the game itself and are refused. From a player, a client script’s events and a page’s events share one budget: at most 30 events and 64 KB (name and payload together) a second in all; a page’s payload is at most 16384 bytes.

Callback When
OnClientEvent A player’s client script sent an event.
Function What it does
SendClientEvent A named event with a string payload to one player’s client script.
SendClientEventToAll The same event to every connected client.

String keys and values the mode sets on the world, a player or an entity, and every client’s script reads - GetGlobalState(key), GetPlayerState(pid, key), GetEntityState(id, key), with a change hook on each (the client API). The way a mode’s client half learns a team, a round, a marker, a flag carrier without a script event per client: the global and the players’ bags reach every client from its join on, an entity’s follows its spawn to whoever sees it. Numbers and booleans become strings; nil removes a key. Nothing is persisted - a player’s bag goes with the session, an entity’s with the entity, all of them with a reload. Limits: a key of 1-48 characters, a value of at most 1 KB, 64 keys a bag (a set beyond them returns false and logs). The mode’s private storage is SetPlayerData / SetEntityData.

Function What it does
SetGlobalState Sets a key of the world’s bag, read by every client.
GetGlobalState A key of the world’s bag.
GetGlobalStates The whole world bag.
SetPlayerState Sets a key of a player’s bag, read by every client.
GetPlayerState A key of a player’s bag.
GetPlayerStates A player’s whole bag.
SetEntityState Sets a key of an entity’s bag, read by every client that sees the entity.
GetEntityState A key of an entity’s bag.
GetEntityStates An entity’s whole bag.

Two places to keep a value, by how long it should live. Data (SetPlayerData, SetEntityData, SetZoneData) is the mode’s private bag on a player, an entity or a zone - any Lua value, gone with the player’s session, the entity or a reload; nothing leaves the server. Anything that should outlive the session - accounts, scores, factions, the place a player left - goes into the mode’s own database when the owner connected one; the server itself remembers nothing about a player between visits. What every client should read is the state bags instead. The rule that keeps the tick fast: read from the database once, on the connect, into SetPlayerData and your own tables; write on change and on the disconnect.

Function What it does
SetPlayerData Stores a value on the player, private to the server, for the session.
GetPlayerData A value stored on the player with SetPlayerData.
SetEntityData Stores a value on a world entity, private to the server.
GetEntityData A value stored on an entity with SetEntityData.

A mode keeps what should outlive a session - accounts, factions, scores, the rules on doors and chests - in a database of its own: MySQL / MariaDB or PostgreSQL, the one thing a server owner connects in server.toml ([gamemode.database]; the databases guide sets one up). GetDatabase hands out the handle, or nil when the owner configured none: say so and run without. The server’s own state - doors, chests, taken items, bans - lives apart and is never reachable through it. Every query runs off the tick and answers in a callback; parameters only (@name in the SQL, the values in a table - never concatenate a value into the SQL text); a failing query hands its error to the callback and the server goes on. The sync pair is for the mode’s init alone.

Function What it does
GetDatabase The mode’s database handle, or nil when the server has none.

A world entity is something the server owns and every client in range sees: a horse (ENTITY_HORSE), a pickup (ENTITY_ITEM), an NPC actor (ENTITY_NPC), a prop (ENTITY_PROP), a dog (ENTITY_DOG), a horse-drawn cart (ENTITY_CART, made by CreateCart) or an animal (ENTITY_ANIMAL, made by CreateAnimal) - the kinds. Its id is unique while it lives and nil from every reader once it is gone. A horse is simulated by its controller - the client of the player who rides or minds it - and carries at most one rider; a loose horse is handed to the nearest player within 30 m once a second. Entities live within a virtual world. These are the calls every kind shares; horses, pickups, props, dogs, actors, carts and animals have their own.

Function What it does
GetEntities Every entity in the world, or every entity of one kind.
GetEntityPos An entity’s position and heading.
SetEntityPos Moves an entity.
GetEntityKind What an entity is.
GetEntityTemplate What an entity is made of - the item class, the soul, the mesh path.
GetEntityName An NPC actor’s label; empty for everything else.
DestroyEntity Removes an entity from the world, for everyone.
GetEntityController The player whose client simulates the entity.
SetEntityController Hands the simulation of an entity to a player, or to nobody.
GetEntityRider The player in the saddle of a horse.
GetEntityIdleTime Seconds since the entity’s pose was last reported.
GetEntityVirtualWorld The virtual world the entity is replicated in.
SetEntityVirtualWorld Moves an entity into another virtual world.
GetNearestEntity The entity nearest to a player, of a kind, within a radius.

Horse-drawn carts, entities of ENTITY_CART, of two kinds: the "wagon" (four wheels, two horses, six seats) and the "cart" (two wheels, one horse between its shafts, three seats); GetEntityTemplate answers a cart’s kind. A route is a road the server drives its carts along - a loop, or there and back with a turn at each end - at a steady pace ([carts] speed, a horse’s canter by default), slowing for its stops and waiting there; a wagoner sits on the bench and players ride along. A free cart stands until a player takes the reins at its bench; their client then drives it (the keys) and everyone sees it move. Players get in with the game’s own prompt - the reins by the bench of a free cart nobody drives, a seat anywhere else - and out with the game’s dismount key. Seats: 0 is at the reins, 1 the bench beside it; in the back of the wagon 2 and 3 sit at its tail (right and left), 4 and 5 ahead of them; on the two-wheeled cart 0 is at the reins on the bed’s front edge, 1 and 2 on its right and left side rail. The mode sees every seat (GetCartSeatPlayer), moves a seated player to another (SetPlayerCartSeat), keeps seats from the prompt (SetCartSeatLocked) and chooses the seat a player gets (OnPlayerEnterCart). Parts: a cart is the game’s own parts - a wagon’s body, front axle, wheels, load and the two horses’ coats (horse1, horse2), a two-wheeler’s body, wheels, load and horse1 - each the mode’s to set (SetCartPart) and to read in any callback (GetCartParts); every screen shows the same, at once (personal carts has the catalogue, a cart dealer and a cartwright). The owner records routes in the game with /cartroute (the routes guide) into the routes file the server reads at its start; a mode adds its own with AddCartRoute (kept until the server stops unless SaveCartRoutes writes them to the file) and places free carts with CreateCart. A seated player’s position is the seat’s; a teleport, a death or the cart’s end takes them out first.

Callback When
OnPlayerEnterCart A player asks to get into a cart - return false to keep them out, or a seat number to seat them there.
OnPlayerExitCart A player left their seat in a cart.
OnPlayerChangeCartSeat A seated player moved to another seat of their cart.
OnCartStop A route’s cart pulled up at one of its stops and waits there.
OnCartHorsesTired A cart’s horses ran out of stamina - they walk until they have caught their breath.
Function What it does
CreateCart Puts a free cart in the world - a wagon with its two horses or a two-wheeler with one, standing until a player takes the reins.
AddCartRoute Makes a route and sets its carts going.
RemoveCartRoute Takes a route away, and its carts with it.
SaveCartRoutes Writes every route into the routes file the server reads at its start.
GetCartRoutes Every route - from the file, the admins’ /cartroute and the mode’s own.
SetCartRoute Puts a cart on a route, or takes it off (a free cart again).
GetCartRoute The route a cart drives.
SetCartSpeed One cart’s own pace - a route cart’s travelling speed, or the most a player may drive it at.
HoldCart Keeps a route’s cart standing - or sends it on at once.
PutPlayerInCart Sits a player in a cart.
RemovePlayerFromCart Takes a player out of their cart - their game climbs down.
GetPlayerCart The cart a player sits in, and the seat.
GetCartPassengers The players in a cart, the one at the reins first.
SetPlayerCartSeat Moves a seated player to another seat of their cart.
GetCartSeatCount How many seats a cart has.
GetCartSeatPlayer Who sits on one seat of a cart.
SetCartSeatLocked Keeps a seat of a cart from the use key - or gives it back.
IsCartSeatLocked Whether a seat of a cart is locked.
SetCartPart Changes one part of a cart - its body, axle, wheels, load or a horse - on every screen at once.
SetCartParts Changes several parts of a cart at once.
GetCartPart What a cart has in one slot.
GetCartParts Every part of a cart - what it looks like, to show, to price or to save.
GetCartPartSlots The slots a cart of a kind has - a shop’s menu.
GetCartPartNames The parts a slot takes - a shop’s shelf.
AddCartProp Puts one of the game’s models on a cart - it rides with it, on every screen.
SetCartProp Changes a prop of a cart in place - another model, place, turn, scale or material.
RemoveCartProp Takes a prop off a cart.
ClearCartProps Takes every prop off a cart.
GetCartProps The props on a cart - for a mode that saves a player’s cart.
SetCartPartMaterial Gives a part of a cart another of the game’s materials - its wood a different colour.
GetCartPartMaterial The material a part was given, or nil for its own.
HitchHorse Puts a player’s horse in front of a cart, in place of its own horse or an empty slot.
UnhitchHorse Takes a player’s horse from a cart; it stands beside it again.
GetCartHorse The player’s horse hitched in a slot of a cart.
GetHorseCart The cart a horse is hitched to, and its slot.
SetCartLoad Says how much a cart carries - the weight its horses pull.
GetCartLoad The weight the mode put on a cart (kilograms).
SetCartLoadFactor How much a cart’s weight slows its horses - 0 never, 1 as it is, more for heavier going.
GetCartLoadFactor How much a cart’s weight counts against its horses.
SetCartStaminaRate How fast a cart’s horses tire - 0 never, 1 as they do, more for sooner.
GetCartStaminaRate How fast a cart’s horses tire.
SetCartStamina Sets a cart team’s stamina - fresh horses at a station, tired ones after a long road.
GetCartStamina A cart team’s stamina, 0 - 100.
GetCartPull What a cart’s team pulls against what it carries, and the pace that leaves - for a mode’s own rules and messages.

A horse is a world entity of ENTITY_HORSE simulated by its controller - the client of the player who rides or minds it; the others see a puppet following its pose. Its soul is the breed, a key of the Horse archetype of the souls. Players get a horse with the /horse built-in (an admin command by default); a mode gives one with CreateHorse and puts a player in the saddle with MountPlayer. A mounted player’s position and velocity are the horse’s. A horse may have an owner (SetHorseOwner; a horse made for a player is theirs): it is their horse in the game - its saddlebags open from their inventory and hold their things whoever happens to be simulating it, and they get on with the game’s plain “Mount” - while anyone else gets “Mount and steal” (OnPlayerStealHorse decides). The saddlebags are the server’s record: it keeps what each horse carries (GetHorseItems), whoever holds the bags, and fills the copy on the screen of the player whose game holds them - the owner’s, else the rider’s, else the one whose game simulates the horse. What that player moves between their bag and the saddlebags changes the record only for what the server’s item records let go of, and an item that appears in the saddlebags with nothing to explain it is taken out under enforce (the item check). How players come by horses - a horse seller, a stable, a reward - is the mode’s to build; a player may own several. The server forgets every horse when it stops: a mode that keeps them saves the breed (GetEntityTemplate), the coat (GetHorseCoat) and its own look over it (GetHorseLook - a coat, mane and tail from the game’s horses, SetHorseLook), the gear (GetHorseGear), the saddlebags (GetHorseItems) and the stats it gave (GetHorseStats) - on OnHorseItemsChange and OnPlayerDisconnect - and makes the horse again (CreateHorse with the breed and the coat or the look, SetHorseGear, SetHorseItems, SetHorseStat). The mode’s own id for a saved horse rides on it with SetEntityData: the entity id is new every time the horse is made. A rider whose head meets a low branch at speed, or whom the horse throws, falls off as in the game - the fall, the lying still and the get-up are seen on every screen and reach the mode as OnPlayerThrown; ThrowPlayerFromHorse does it on order, and SetPlayerRiderHeadHit / SetPlayerRiderThrow switch it off. A player on foot can also pull a rider off the horse with the game’s own take-down move (the “Pull down” prompt on a rider’s body): off for everyone until a mode allows it (SetPlayerPullDown); the server checks the reach and pace, pvp, teams and parties, the mode has the last word and the chance (OnPlayerPullDown, OnPlayerPulledDown), and PullPlayerFromHorse does it on order.

Callback When
OnPlayerMount The player is in the saddle of a horse.
OnPlayerDismount The player got off the horse - or left while riding, or the horse was destroyed.
OnPlayerThrown The player was thrown off the horse they ride - a low branch, the horse, or the mode’s own order.
OnPlayerPullDown A player on foot asks to pull a rider off their horse - return false to refuse, or the chance it works.
OnPlayerPulledDown A pull-down is over - the rider was thrown off the horse, or the pull failed.
OnPlayerStealHorse A player got on a horse another player owns - return false to put them off it.
OnPlayerWhistle The player whistled for their horse with the game’s own whistle.
OnHorseItemsChange What a horse’s saddlebags hold or what it wears changed - the moment to save it.
OnHorseDamage A player hit a horse - change the damage, cancel it, or let it through.
OnHorseDeath A horse died.
Function What it does
CreateHorse Puts a horse in the world.
MountPlayer Puts a player in the saddle of a horse.
GetPlayerMount The horse the player rides right now.
ThrowPlayerFromHorse Has a rider’s game throw them off their horse, the fall every player sees.
IsPlayerThrown Whether the player is in the fall of a rider thrown off their horse.
SetPlayerRiderHeadHit Turns the head hit on low branches and beams on or off for a rider - the game’s own throw.
SetPlayerRiderThrow Turns the throws off for a rider - a head hit, the horse and ThrowPlayerFromHorse no longer take them off their horse.
SetPlayerPullDown Lets a player pull riders off their horses with the game’s take-down move - off by default.
GetPlayerPullDown Whether the player may pull riders off their horses.
PullPlayerFromHorse Has a player on foot pull a rider off their horse - the game’s take-down, on order.
IsPlayerInPullDown Whether the player is pulling a rider down or being pulled off a horse right now.
SetHorseOwner Makes a horse a player’s - or nobody’s.
GetHorseOwner Whose horse it is.
GetPlayerHorses Every horse in the world the player owns.
GetHorseItems What a horse’s saddlebags hold.
SetHorseItems Makes a horse’s saddlebags hold exactly this list.
GetHorseGear What a horse wears - its saddle, bridle, saddlebags and caparison.
SetHorseGear Dresses a horse in exactly this gear, on every screen.
GetPlayerHorse The horse the player rides, or else the newest one they own, or else one they control.
SetHorseStat Sets a stat of a horse to a level, exactly.
GetHorseStat The level a mode set on a horse’s stat.
GetHorseStats Every stat a mode set on a horse.
SetHorseCoat Sets a horse’s coat - its colour, mane and tail - on every screen.
GetHorseCoat The coat a horse wears.
GetHorseCoats The coats a horse can wear.
SetHorseLook Gives a horse its own coat, mane and tail from the game’s horses - on every screen.
GetHorseLook A horse’s look.
GetHorseLookParts The coats, manes or tails a horse’s look may name.
GetHorseHealth A horse’s health.
SetHorseHealth Sets a living horse’s health.
SetHorseInvulnerable No blow hurts the horse.
SetHorseType Makes a horse a cart horse, a riding horse or a type of the mode’s - what it pulls and how it goes under a rider.
GetHorseType A horse’s type.
SetHorseTypeRule Makes a horse type or changes one - what one horse of it pulls and its pace under a rider.
GetHorseTypeRule What a horse type pulls and its pace under a rider.
GetHorseTypes Every horse type’s name - a stable’s list.

A prop is a static mesh of the game’s object files placed in the world for everyone in range to see - a barrel, a fence, a table, a stone - like a pickup nobody can take. The mesh is a key of the mesh list: the id, the file’s name (barrel_a, when only one file carries it) or the path. A static prop stands where it is placed and blocks the way; a rigid one is a physics body on each client - pushable, but its motion is not synchronised, so a barrel one player kicks stays put for the others. The /prop and /props built-ins place and search them.

An interaction point is an invisible spot with a use prompt of yours (CreateInteraction): a notice board to read, a house’s sign, a well to drink from - the player looks at it, the game’s own use hint shows your text, and the use key calls OnPlayerInteract. A prop takes a prompt the same way (SetEntityPrompt). A door takes a row of yours with SetDoorPrompt.

Callback When
OnPlayerInteract A player pressed the use key on an interaction point or a prop with a prompt.
Function What it does
CreateInteraction Places an invisible spot with your use prompt - “Read the notices”, “View the house”, “Drink”.
SetEntityPrompt The use prompt on a prop or an interaction point (an actor’s too).
GetEntityPrompt An entity’s use prompt.
SetPropCollision Whether players walk into a prop or through it.
IsPropSolid Whether a prop is solid.
CreateProp Places a static mesh in the world.
GetMeshPath The path a mesh key stands for.
FindMeshes Meshes whose path holds every word of a pattern.
GetEntityScale A prop’s scale.
IsEntityRigid Whether a prop is a physics body.

Siege engines, entities of ENTITY_SIEGE, of four kinds (GetSiegeKinds): the "trebuchet" - the game’s own, throwing a stone 100-330 m - and the "cannon", the game’s bombard, firing a ball up to about 400 m; GetEntityTemplate answers an engine’s kind. A player works one with the game’s use prompt beside it: they take the operator’s place, aim by holding the right mouse button and looking (the engine turns to the point under their crosshair at its own pace and sets its throw for it - a mark on their screen shows where the shot will come down), press R to load it and the left mouse button (or F) to fire, and the use prompt again to let it go - walking off, mounting a horse or dying lets go too. A trebuchet winds its arm down before each load; the shot leaves a moment after the fire (the sling’s swing, the cannon’s fuse). The server flies every shot and decides where it comes down - against the level’s collision and heightmap when the server has them, else on the shooter’s word, checked against the arc - and the impact hurts every player and actor within the kind’s radius (the operator is the attacker: the kills are theirs) and takes structure from the engines near it: an engine at 0 % is wrecked until SetSiegeEngineHealth repairs it. The mode can refuse a player’s hand (OnSiegeEngineAction), spare a player (OnPlayerSiegeHit), work an engine itself (AimSiegeEngine, LoadSiegeEngine, FireSiegeEngine), limit its shots (SetSiegeEngineShots) and tune one engine’s timing, reach and damage (SetSiegeEngineRules). Admins place them with /siege.

The third kind is the siege ladder, "ladder": the game’s own 10 m ladder of the siege battles, leaning against a wall, climbed with the game’s own climb. A player on the wall at its top knocks it down by holding the use key: it falls outward, everyone on it comes down with it - hurt by how high they were (OnPlayerSiegeHit) - and it lands on whoever stands in its way. A player at the foot of a fallen ladder raises it with the use key. The mode can do both (PushSiegeLadder, RaiseSiegeLadder) and refuse either (OnSiegeEngineAction); the other engines’ shots break a ladder like any engine.

The fourth is a pile of stones, "stones": the defenders’ hurling stones of the game’s own sieges, nine on a wall walk. A player beside it lifts one with the use key, holds it while they look where it should fall - over the wall, onto the attackers below - and throws it with the left mouse button (or F); the use key again puts it back. A stone hurts whoever it lands on and knocks a climber off a siege ladder; a thrown stone is back on the pile 20 s later. The mode can refuse a lift or a throw (OnSiegeEngineAction), count the stones itself (SetSiegeEngineShots) and tune the pile (SetSiegeEngineRules); nothing wrecks it.

Callback When
OnSiegeEngineAction A player puts a hand to a siege engine - return false to refuse.
OnSiegeShot A siege engine’s shot left it - the sling let go, the fuse burned down.
OnSiegeImpact A siege engine’s shot came down - after its damage went out.
OnSiegeEngineHit Another engine’s shot is about to damage a siege engine - return the damage to apply.
OnPlayerSiegeHit A siege engine’s shot is about to hurt a player - return the damage to apply.
OnSiegeEngineDestroyed A siege engine was wrecked - by another engine’s shots, or by the mode.
Function What it does
CreateSiegeEngine Stands a siege engine in the world - a trebuchet, a cannon, a siege ladder or a pile of stones.
GetSiegeKinds The kinds of siege engine there are.
GetSiegeEngines Every siege engine in the world.
GetSiegeEngineInfo A siege engine as it stands - its phase, operator, aim, structure and shots.
GetPlayerSiegeEngine The siege engine a player works.
SetSiegeEngineOperator Puts a player at a siege engine as its operator, or takes its operator away.
AimSiegeEngine Aims a siege engine at a point.
LoadSiegeEngine Loads a siege engine, as its operator’s R would.
FireSiegeEngine Fires a loaded siege engine, as its operator’s fire key would.
SetSiegeEngineShots Limits the shots a siege engine has left.
SetSiegeEngineHealth Sets a siege engine’s structure - wrecks it, repairs it, or makes it unbreakable.
SetSiegeEngineRules Tunes one siege engine - its timing, reach, turning and damage.
PushSiegeLadder Knocks a standing siege ladder down.
RaiseSiegeLadder Stands a fallen siege ladder up against its wall again.

A player’s dog: a world entity of ENTITY_DOG whose controller is its master for life. On the master’s screen it is the game’s own companion - it follows, waits or roams on the game’s dog AI, it can be praised - and everyone in range sees the same dog following them. One dog per player; it goes with the master’s disconnect or DestroyEntity. A following dog comes along when its master respawns or is moved more than 30 m by SetPlayerPos - it appears two metres behind them; a dog told to stay or roam stays where it is. The /dog built-in gives the caller one (and sends it away on the second call); /dog stay, /dog follow and /dog free set its mode.

The mode is the dog’s state bag key mode (GetEntityState), a number of the game’s own list: DOG_STAY 0, DOG_FOLLOW 1 (the default), DOG_FREE 2, DOG_AGGRESSIVE 3, DOG_SEARCH 4, DOG_HUNT 5, DOG_GUARD 6, DOG_AMBUSH 7. Stay, follow and free are the tested ones.

Function What it does
CreateDog Gives a player a dog that follows them.
GetPlayerDog The player’s dog.
SetDogMode Tells a dog to stay, follow or roam.
GetDogMode A dog’s mode.
SetDogCoat Sets a dog’s coat - its colour and markings - on every screen.
GetDogCoat The coat a dog wears.
GetDogCoats The coats a dog can wear.

Players talk to whoever stands near them: a voice plays from where its owner stands, through the game’s own 3D sound, fading with the distance. The server relays every voice frame the moment it arrives to the players within the range, and the mode steers it: how far a voice carries (SetVoiceRange), one player’s own reach (SetPlayerVoiceRange - a crier, a whisperer), a mute nobody hears (SetPlayerVoiceMuted) and a deafening that hears nobody (SetPlayerVoiceDeaf); OnPlayerVoiceStart and OnPlayerVoiceStop say who speaks.

A player’s own mutes silence one talker for that player alone - everyone else still hears them. Players have the server’s /mute <name|id> and /unmute <name|id> and the scoreboard’s mute button; OnPlayerVoiceMute hears (and may refuse) each one, and a mode that handles /mute itself, or offers a menu, sets them with SetPlayerVoiceMutedFor. GetPlayerVoiceMutes lists them to save; they last while both players are in the game. The server’s defaults are the [voice] section of server.toml; players pick their microphone, key and mode in the launcher.

Voice levels let the players choose how far they are heard: a whisper, the normal voice, a shout - as many as the mode likes (SetVoiceLevels). A player switches with the voice level key (left Ctrl unless they changed it in the launcher’s options; on horseback Ctrl stays the horse’s brake), the game’s HUD shows the level they picked (“Voice: Whisper (3 m)”), and their voice carries as far as the level says. OnPlayerVoiceLevelChange may refuse a switch, SetPlayerVoiceLevel puts a player at a level.

Callback When
OnPlayerVoiceStart A player started speaking.
OnPlayerVoiceStop A player stopped speaking.
OnPlayerVoiceLevelChange A player pressed the voice level key and asks for the next level.
OnPlayerVoiceMute A player asks to stop hearing another player, or to hear them again.
Function What it does
SetVoiceRange How far a voice carries by default, in metres.
GetVoiceRange The server’s default voice range in metres.
SetPlayerVoiceRange One player’s own voice range in metres; 0 = the default again.
GetPlayerVoiceRange A player’s own voice range, 0 when they use the default.
SetPlayerVoiceMuted Nobody hears the player while muted.
IsPlayerVoiceMuted Whether the mode muted the player.
SetPlayerVoiceDeaf The player hears nobody while deaf.
IsPlayerVoiceDeaf Whether the mode deafened the player.
SetPlayerVoiceMutedFor One player no longer hears another - for that player alone.
IsPlayerVoiceMutedFor Whether one player muted another for themselves.
GetPlayerVoiceMutes The players one player muted for themselves.
IsPlayerTalking Whether the player’s voice reached the server in the last 300 ms.
IsPlayerVoiceEnabled Whether the player keeps the voice chat on in their own settings.
SetVoiceLevels The voice levels players switch between with the voice level key - a whisper, a shout, as many as you like.
GetVoiceLevels The voice levels of SetVoiceLevels and the one players start at.
SetPlayerVoiceLevel Puts a player at one of the voice levels.
SetVoiceOcclusion How much walls muffle a voice.
GetVoiceOcclusion How much walls muffle a voice on this server.
SetVoiceVisorMuffle How much a closed helmet visor muffles its wearer’s voice.
GetVoiceVisorMuffle How much a closed helmet visor muffles a voice on this server.
GetPlayerVoiceLevel The voice level a player speaks at.

An NPC actor is a dressed, named human body the server owns outright - a guard, a merchant, an arena opponent, a crowd - without the game’s own AI. The mode creates it, walks it, poses it and sets it on a player; it takes hits, dies and fights back. Its id is a world entity of ENTITY_NPC: GetEntityPos, GetEntityName, SetEntityState and DestroyEntity work on it. Its look is a soul of the souls, its clothes and arms are clothing and weapon presets, its poses are clips of the animation list. It fights like a player: an armed actor raises its guard against a swing part of the time ([actors] block_chance, block_hold), a heavy blow wounds the part it hits, a cut bleeds, a bleed-out kills it. With the level’s navigation mesh it walks around walls and opens the doors in its way ([actors] open_doors). Several actors on one player all swing at once by default; [actors] max_attackers makes them take turns - at most that many swing at one player within a swing_interval, the rest wait at arm’s length, the longest waiting first. Actors fight each other too (SetActorHostileToActor), and a mode can relabel and color the name over one (SetActorNameplate, SetActorColor). [actors] in server.toml tunes how it fights. How hard it hits and what it wears are the mode’s too: its stats and skills (SetActorStat, SetActorSkill) and its items one by one (SetActorInventory - its armour counts, its weapon prices its blows). An actor also rides a horse, speaks the game’s own lines and sits on the level’s benches or works at its work spots (MountActor, PlayActorBark, SetActorUse - the next section).

Animals (CreateAnimal, ENTITY_ANIMAL) are the game’s own wildlife and farm animals, owned by the server the same way an actor is. The kinds are wolves, wild dogs, dogs (a stray the server walks; a player’s own dog is CreateDog’s), boars, pigs, red deer stags and does, roe deer bucks and hinds, hares, sheep (ewes and rams), cattle (cows and bulls), hens and ravens.

  • Moving and keeping them: MoveActor, StopActor, TurnActor, the health functions, HealActor, SetActorInvulnerable and DestroyEntity work on them as on an actor.
  • Hunting them: a player’s blow or arrow hurts one (OnActorDamage may change or cancel the damage), a cut bleeds, and it dies when its health reaches 0 or it bleeds out. An animal never blocks, poses, trades or takes a look, wears no label or torch, is not knocked out, robbed or carried (SetActorNameplate, SetActorTorch, SetActorKnockedOut, SetActorPocket and the like answer false). It bleeds but is never injured: OnActorInjury never runs for an animal and GetActorInjuries stays empty.
  • Animals that attack and flee: left alone an animal does nothing by itself. SetAnimalHostile sets one on a player - it runs after them and bites within its reach (a wolf’s or a dog’s attack on every screen; the bite goes through their armour and OnActorAttack); SetAnimalFlee runs it from a player. SetAnimalBehavior gives it a temper that acts by itself: "aggressive" hunts a player who comes close, "defensive" turns on whoever hurts it, "skittish" runs from a player who comes close and from whoever hurts it. SetAnimalAttack tunes the bite, GetAnimalState says what it is doing.
  • What a kill is worth: a dead animal gives nothing by itself. OnActorDeath runs for it with the player who killed it (-1 when its health was set to 0 or the last blow was no player’s) - hand out the meat or the pelt there, or put it on the body for a search (SetActorLoot), and DestroyEntity the carcass when you are done with it, since it lies there until you do.
Callback When
OnActorArrive An actor (or a horse) reached its MoveActor target.
OnActorDamage A player hit an actor - change the damage, cancel it, or let it through.
OnActorInjury A hit wounded one of an actor’s body parts.
OnActorDeath An actor’s health reached 0.
OnActorAttack An actor’s blow landed on its opponent - change the damage, cancel it, or let it through.
OnActorAttackActor An actor’s blow landed on another actor - change the damage, cancel it, or let it through.
OnActorBlocked An actor’s swing met a player’s block.
OnPlayerBlockedByActor A player’s swing met an actor’s raised guard.
OnPlayerInteractActor The player pressed the use key on an actor that has a prompt - return false to stop its shop opening.
OnPlayerLootActor A player wants to search a dead actor’s or animal’s body - return false to refuse.
OnPlayerButcher A player wants to butcher a dead animal - return false to refuse.
Function What it does
CreateActor Creates an NPC actor - a dressed, named body the server owns.
CreateAnimal Creates an animal - the game’s wolf, boar, deer, hare … that the server walks like an actor.
SetAnimalHostile Sets an animal on a player - it runs after them and bites.
SetAnimalFlee Runs an animal from a player.
SetAnimalBehavior What an animal does by itself - calm, aggressive, defensive or skittish.
GetAnimalBehavior An animal’s behaviour.
SetAnimalAttack An animal’s bite - its damage and how often it bites.
GetAnimalState What an animal is doing - hunting, fleeing or calm - and who it is about.
MoveActor Walks an actor to a point - around the walls when the server has the navigation mesh.
StopActor Stops an actor where it is.
TurnActor Turns a standing actor to face a direction.
IsActorMoving Whether an actor is on its way to a MoveActor target.
SetActorAnim Puts a pose on a standing actor - a clip of the game’s animation set.
GetActorHealth An actor’s health.
SetActorHealth Sets an actor’s health; 0 kills it.
IsActorDead Whether an actor is a corpse.
HealActor Makes an actor whole - full health, no wounds, no bleeding.
GetActorInjuries An actor’s wounded body parts.
IsActorInjured Whether an actor has a wound - anywhere, or on one part.
GetActorBleeding How fast an actor is bleeding, in health per second.
SetActorBleeding Sets how fast an actor bleeds, in place of its open wounds.
IsActorBleeding Whether an actor is bleeding.
SetActorHostile Sets an actor on a player - or stands it down.
SetActorHostileToActor Sets an actor on another actor - or stands it down.
GetActorTarget The actor an actor is fighting.
StaggerActor Staggers an actor - it reels and loses its next swing.
SetActorBlockRules Sets what a player’s block costs an actor.
GetActorBlockRules The actor block rules in force.
SetActorInvulnerable Makes an actor one no blow hurts - or hittable again.
IsActorInvulnerable Whether an actor takes no hits.
SetActorInvisible Makes an actor or an animal invisible to every player, or seen again.
IsActorInvisible Whether an actor or an animal is invisible to players.
SetActorInvisibleFor Hides an actor from one player, or shows it to one player while it is invisible to the rest.
IsActorVisibleTo Whether a player sees an actor or an animal.
SetActorTorch Puts a lit torch or lantern in an actor’s free hand - or puts it out.
SetActorHandItem Puts an item in an actor’s hand - a tool for its work or its animation - or empties the hand.
GetActorHandItem The item in an actor’s hand.
SetActorRanged Lets an actor with a bow or a crossbow shoot in its fights - or keeps it to its melee weapon.
IsActorTorchLit Whether an actor holds a lit torch (or a lantern).
GetActorLight Which light an actor holds - a torch or a lantern.
SetActorStat Sets one of an actor’s stats - strength, agility, vitality, speech.
GetActorStat The level SetActorStat gave one of an actor’s stats.
SetActorSkill Sets one of an actor’s skills - a weapon skill, defense, warfare.
GetActorSkill The level SetActorSkill gave one of an actor’s skills.
SetActorInventory Gives an actor exactly these items - what it wears dresses and arms it.
GiveActorItem Gives an actor one item more - worn unless told otherwise.
RemoveActorItem Takes items from an actor - what it carries first, then what it wears.
GetActorInventory An actor’s items, as SetActorInventory and GiveActorItem left them.
SetActorLoot What a dead actor’s or animal’s body gives the players who search it.
GetActorLoot What a dead actor’s or animal’s body still holds for a search.
SetActorButcher Lets players butcher a dead animal the game’s own way - or not.
IsActorButchered Whether a player butchered the animal’s carcass.
SetActorPrompt The prompt under an actor’s name within reach - the use key on it reaches the mode.
GetActorPrompt An actor’s prompt.
SetActorNameplate The label over an actor’s body on every screen.
GetActorNameplate An actor’s label as set.
SetActorNameplateFor The label one viewer alone reads over an actor.
GetActorNameplateFor The label one viewer alone reads over an actor (SetActorNameplateFor).
SetActorColor The color of an actor’s label.
GetActorColor An actor’s label color as set.
SetActorShop Makes an actor a vendor - the use key on it opens the shop.
GetActorShop The shop an actor sells.

What brings a town’s people to life: an NPC actor (CreateActor) can ride a horse, speak the game’s own lines and use the level’s seats, beds and work spots or stand in a pair animation with another actor. All of it is the server’s: every player sees the same rider on the same road, hears the same line from the same body, finds the same man on the same bench - and a player who arrives later finds them there too.

  • Riding: MountActor puts an actor on a horse nobody rides or owns (CreateHorse): it walks to the horse’s side and climbs on with the game’s own mount; MoveActor then rides - the speed picks the gait (about 1.8 a walk, 4 a trot, 7 a canter, 11 a gallop) and the horse walks around walls on the navigation mesh like a walking actor; DismountActor gets it off. A mounted actor does not fight, and its death, its horse’s, either one’s removal or a knock-out take it off at once (OnActorDismount).
  • Speaking: PlayActorBark says one line of one of the game’s barks ("greeting", "farewell", "self_talk", "work_sigh", "market_call", "pray", "pain" …), PlayActorVoice one line by its id, PlayActorConversation a whole conversation of the game between two actors (gossip, greetings, a trader with a customer). The players around hear the line from the actor’s body in their own game’s language, with the face the game animated for that recording and its gesture. Each actor speaks in its soul’s voice where the game recorded the line in it (SetActorVoice gives it another), else in a voice of its gender. The lines: the voice lines.
  • Seats, beds and work spots: GetSmartObjects lists the level’s own - benches, chairs, stools, beds, wells, weeding beds, debarking trestles, waiting and leaning places, more than 14,000 of them on Kuttenberg’s map - and SetActorUse sends an actor to one: it walks there, sits down (kneels, leans, starts work) with the game’s own animation, stays until StopActorUse or a MoveActor, and gets up before it walks away. SetActorUseAt does an activity anywhere. The activities: the activities.
  • Pairs: PlayActorPairAnim stands two actors face to face in one of the game’s pair animations - talking, drinking and cheering, dancing.

An actor in an activity or on a horse keeps its pose: SetActorAnim and TurnActor answer false until it is up or off. The voice lines and the level’s seats and work spots come from the server’s export of the game’s tables (re-export with this version: Exporting the game’s tables).

Callback When
OnActorMount An actor sits on its horse - MountActor’s climb is done.
OnActorDismount An actor is off its horse.
OnActorVoiceEnd The line PlayActorVoice or PlayActorBark started is over.
OnActorConversationEnd The conversation PlayActorConversation started is over.
OnActorActivity An actor’s activity or pair began, ended or never got under way.
Function What it does
MountActor Puts an actor on a horse - it walks to it and climbs on with the game’s own mount.
DismountActor Gets an actor off its horse with the game’s dismount.
GetActorHorse The horse an actor is on.
IsActorMounted Whether an actor sits in the saddle.
PlayActorVoice An actor says one of the game’s lines by its id.
PlayActorBark An actor says a line of one of the game’s barks.
PlayActorConversation Two actors hold one of the game’s conversations, line by line.
StopActorVoice Cuts what an actor is saying, on every screen.
IsActorSpeaking Whether an actor is saying a line or is in a conversation.
GetActorVoice The voice an actor speaks in.
SetActorVoice Gives an actor one of the game’s voices.
GetVoiceLineText A line’s English text - the game’s subtitle.
GetBarkLines The line ids of a bark.
SetActorUse Sends an actor to one of the level’s seats, beds or work spots to do what the game’s people do there.
SetActorUseAt An activity anywhere - the actor at a place you name.
StopActorUse Gets an actor up from its activity or pair.
GetActorUse An actor’s activity or pair.
GetActorUseObject The smart object an actor uses.
GetSmartObjects The level’s seats, beds and work spots around a point.
GetNearestSmartObject The nearest free seat, bed or work spot.
PlayActorPairAnim Two actors in one of the game’s pair animations, face to face.
GetPairAnims The names PlayActorPairAnim takes.

A zone is a region the server watches for the mode: a box between two corners, or a circle around a point with any height unless a zMin/zMax band is given. Once per tick every player in the world is tested against every zone and the mode hears OnPlayerEnterZone and OnPlayerLeaveZone on the edges. Ids start at 1 and are reused after a destroy; there are 4096. A zone has a private data bag (SetZoneData). Zones go with a reload.

A zone can also be a target: SetZoneHittable makes it catch the arrows, bolts and balls players shoot and the swings they throw. The server flies every shot itself from where it left the bow, stops it at the ground, at the level’s walls (with the collision export) and at a body it struck, and calls OnProjectileHitZone for every target the arrow reached, at the moment it got there; a swing that reaches a target calls OnMeleeHitZone. A target is invisible and stops nothing - put a prop or an actor there for something to see. CreateSphereZone makes a ball-shaped zone, and AttachZoneToEntity lets a zone ride a prop, an actor, a horse or a cart, for a moving target.

Callback When
OnPlayerEnterZone A player’s position of record entered a zone.
OnPlayerLeaveZone A player left a zone - walked or was moved out, despawned, respawned elsewhere, disconnected.
OnProjectileHitZone A player’s arrow, bolt or ball reached a target zone.
OnMeleeHitZone A player’s swing reached a target zone.
Function What it does
CreateZone A box zone between two corners.
CreateCircleZone A circular zone around a point - a cylinder of any height, or of a band.
CreateSphereZone A ball-shaped zone around a point - a target hung in the air, or the space around a prop.
SetZoneHittable Makes a zone a target - it catches the shots and swings that reach it.
IsZoneHittable Whether a zone is a target (SetZoneHittable).
AttachZoneToEntity Lets a zone ride an entity - a moving target, a zone around a cart.
DestroyZone Removes a zone.
IsPlayerInZone Whether the player is inside a zone, as of the last tick’s test.
IsPointInZone Whether a point lies inside a zone.
GetZonePlayers The players inside a zone right now.
GetPlayerZones The zones a player is inside right now.
GetZones Every zone the mode has made.
GetZoneInfo A zone’s shape.
SetZoneData Stores a value on a zone, private to the server.
GetZoneData A value stored on a zone with SetZoneData.

The world - clock, weather, terrain, the navmesh, the geometry

Section titled “The world - clock, weather, terrain, the navmesh, the geometry”

The server owns the world clock and the weather: every client follows them, so the whole server sees one time of day and one sky ([world] in server.toml sets the start). The clock is hours since midnight (13.5 = 13:30) and runs at a ratio of game seconds per real second; the weather is a preset name or one of the level’s own sky profiles (Weather); the rain is a lever on top. The terrain height comes from the level’s heightmap when the server has one, and the navigation mesh - the game’s own, when the operator exported it (World data) - answers for walks, floors and reachability: the NPC actors walk around walls on it by themselves. The collision geometry

  • the level’s walls, roofs, floors and trees, exported from the game’s own physics world - answers rays: what is in the way, whether two points see each other, the true floor under a point. The doors the server knows are open let a ray through.
Function What it does
GetWorldTime The world clock, in hours since midnight.
SetWorldTime Sets the world clock for everyone.
FormatWorldTime Hours as HH:MM.
GetTimeRatio How fast the world clock runs - game seconds per real second.
SetTimeRatio Sets how fast the world clock runs.
GetRain The rain every client shows.
SetRain Forces rain on every client, or hands the rain back to the weather.
GetWeather The sky profile every client follows.
SetWeather Changes the sky for everyone - by a preset name or a level profile.
GetWeatherPresets The preset names and the profiles they stand for.
SetWeatherChances How often each kind of weather comes up in the server’s rotation, and how long a sky stays.
GetWeatherChances The rotation’s chances and how long a sky stays.
GetTerrainHeight The terrain height at a point, from the level’s heightmap.
HasNavmesh Whether the server has the level’s navigation mesh.
FindPath The corners of a walk between two points on the navigation mesh.
IsReachable Whether a walk joins two points on the navigation mesh.
GetNavmeshHeight The navigation mesh’s floor at a point.
NearestNavmeshPoint The nearest point on the navigation mesh.
HasCollision Whether the server holds the level’s collision geometry.
RayCast The nearest surface along a line.
IsLineOfSight Whether nothing stands between two points.
GetGroundZ The surface under a point.
SetStoryQuests Lets the game’s own story quests run in the players’ games, or keeps them asleep (the default).
GetStoryQuests Whether the players’ games run the game’s own story quests.

The level’s own doors, stashes and the loose items on its tables and shelves are in sync on every client whatever the mode does: a door one player opens swings on every screen; a chest one player loots is emptier for the next; a bowl one player takes from a table is gone for everyone. A door’s state of record is written by whoever uses it. A container’s contents are the server’s from the start: the first time anyone opens a chest its contents are rolled from the game’s own loot tables - the loot preset the level placed that chest with, the way the single-player game fills it - or it opens empty when the server is set that way ([containers] loot). One player holds a container at a time (“Someone is rummaging in it.” for the next), what they leave in it is what the next opener finds, and a chest somebody touched is rolled again after its restock period ([containers] restock; world days on the server’s clock). Stashes the game links to one master inventory share one record, and a mode may link any keys itself (LinkContainers). A loose item the level placed (an item slot) works the same way: taken by one player, that item - and only that one, never its neighbours on the shelf - is removed for the others, and the level’s own item comes back where it lay after the period; a mode can put items back at any time (ResetWorldItem, ResetWorldItems). Every player’s world follows the server’s record: one who stays connected through a server restart sees the items the record no longer holds taken come back. Doors, chests and taken items survive a restart (the server’s own database, made on the first start, nothing to configure). The key of a door, a container or an item slot is the entity’s level name - AnimDoor[Door/door_village_left32_77d417c2-...], Stash7[Stash/stash_shelf_...] - listed per level in Levels, and shown in the game to an admin by /objectinfo (a label over every object around them); GetNearestDoor names “the door I stand at” without a key in sight. Where a level gives one name to several containers or item slots (Stash96 stands five times in kutnohorsko), one of them keeps the name as its key and each other one is the name with its place in whole metres, Stash96@3160,787,57 - the key OnPlayerOpenContainer gets is that of the container the player stands at. A mode needs nothing for the sync; it may veto (OnPlayerUseDoor, OnPlayerOpenContainer, OnPlayerTakeWorldItem) or drive it (SetDoorState, SetContainerItems, SetContainerPreset, RollLoot). The loot tables come with the tables export (Exporting the game’s tables); without it every chest opens empty and /restock has nothing to fill from.

Callback When
OnPlayerUseDoor A player opened, closed, locked or unlocked a door - return false to refuse; for a checked door, before it moves.
OnPlayerInteractDoor A player used your own row on a door (SetDoorPrompt) - the door itself did not move.
OnPlayerUnlockContainer A player unlocked a chest with its key or a lockpick - return false to keep it locked.
OnPlayerOpenContainer A player wants to open a container - return false to refuse.
OnPlayerCloseContainer A player closed a container; the record holds what they left in it.
OnContainerRestock A touched chest’s restock period ran out and somebody is opening it - return false to hold it.
OnPlayerTakeWorldItem A player’s game took a loose item the level placed on a table or a shelf - return false to take it back.
Function What it does
GetDoors Every door anyone touched.
GetDoorState A door’s state of record - the shared one, or a virtual world’s own.
SetDoorState Opens, closes, locks or unlocks a door on every client - or in one virtual world’s own doors.
SetVirtualWorldOwnDoors Gives a virtual world doors of its own - what its players open or lock there stays in it.
HasVirtualWorldOwnDoors Whether a virtual world keeps doors of its own (SetVirtualWorldOwnDoors).
SetDoorCheck Decide before a door moves - the player’s game waits for OnPlayerUseDoor.
IsDoorChecked Whether a use of the door waits for the mode.
SetDoorPrompt Puts a row of your own on a door (“Knock”, “View the house”) - its use reaches OnPlayerInteractDoor.
GetDoorPrompt A door’s row of your own (SetDoorPrompt).
SetDoorLockSides Makes a locked door locked from both sides - its bolt’s side asks for the key too.
GetDoorLockSides Whether a door is locked from both sides (SetDoorLockSides).
SetDoorKey Makes one of your tagged items the key of a door - its holder unlocks the door the game’s own way.
GetDoorKey The tagged item that is a door’s key (SetDoorKey) - every world’s, or the one for a virtual world.
SetContainerLocked Locks or unlocks a chest on every screen - the game’s own lock, picked or opened with its key.
GetContainerLocked A chest’s lock as the server keeps it.
SetContainerLockedFor One player’s own view of a chest’s lock - locked for them, open for them, or back to everyone’s.
GetContainerLockedFor A player’s own lock on a chest (SetContainerLockedFor).
SetContainerKey Makes one of your tagged items the key of a chest - its holder unlocks the chest the game’s own way.
GetContainerKey The tagged item that is a chest’s key (SetContainerKey).
GetContainers Every container anyone opened.
GetContainerItems A container’s contents of record.
SetContainerItems Rewrites a container’s contents; the next opener sees the new list.
GetContainerUser Who has a container open right now.
RollLoot Rolls one of the game’s loot presets into a list of stacks.
HasLootPreset Whether the loot tables have a preset of that name.
GetContainerInfo What the server knows of a container beyond its contents.
GetContainerPreset The loot preset the level places a stash with.
SetContainerPreset Gives a container a loot preset and fills it from it now.
RestockContainer Rolls a container’s preset again now.
LinkContainers Makes several stashes one - they share the first one’s record.
GetTakenWorldItems Every loose item slot somebody emptied.
GetWorldItem A taken loose item’s slot - what it held, where, who took it, when it comes back.
RespawnWorldItem Puts a pickup of the server’s own where a taken loose item lay.
ResetWorldItem Gives the level its own loose item back, in its place, on every client.
ResetWorldItems Gives the level back every taken loose item, or those near a point.
GetWorldItemsNear The level’s loose item slots around a point - what each holds and whether it is taken.
SetWorldItemInteractable Switches one loose item of the level off - it stays where it lies, and nobody can pick it up.
IsWorldItemInteractable Whether a loose item of the level is switched on.
TakeWorldItem Empties a loose item slot by script.
GetWorldSeconds The world clock the restock timers run on.
GetDoorPosition Where a door stands, from the tables export.
GetLevelDoors Every door of the level, touched or not.
GetContainerPosition Where a container stands, from the tables export.
GetWorldItemPosition Where a loose item’s slot stands, from the tables export.
GetNearestDoor The door nearest to a point, within a radius.
GetNearestContainer The container nearest to a point, within a radius.
GetNearestWorldItem The loose item slot nearest to a point, within a radius.

The plants and mushrooms a player picks from the ground - chamomile, nettle, sage, boletus and the rest - are the server’s: a herb one player picks is gone on every screen, and it grows back for everyone at the same moment. The game’s gathering takes every plant of one kind within a small circle around the one picked (wider with the herbalism skill); the server keeps that circle as a picked spot and tells the players near it. Their games take the same plants away and only the server’s word brings them back - after the kind’s regrow time (the game’s own hours at the server’s clock speed - GetHerbRegrowTime; a mode sets its own with SetHerbRegrowTime), or when the mode says so (ResetHerb, ResetHerbs). A spot grows back out of sight, the way the game’s own herbs do: once nobody stands within ten metres of it.

A mode needs nothing for the sync. It may judge every pick (OnPlayerPickHerb: refuse it, or give another amount of the item), switch herbs off by kind and place (SetHerbsEnabled - the plants are gone and cannot be picked there), take herbs away itself (TakeHerbs) and plant its own where it wants them (CreateHerb: the kind’s plant with a “Pick” prompt). A kind is named by its item - "herb_chamomile", "boletus" - its class GUID, or "*" for every kind; the kinds, what each gives and its regrow time are in the list of herbs and GetHerbKinds.

The sync rides with the level’s loose items: it needs [containers] world_items (on by default - with it off every game keeps its own herbs, as before), and [containers] persist keeps the picked spots across a restart. A player whose game is older than the server’s herbs keeps their own herbs, and what they pick is judged like any item their game makes.

Callback When
OnPlayerPickHerb A player picked herbs or mushrooms - return false to refuse, or a number to give that many of the item.
Function What it does
SetHerbRegrowTime How long a kind of herb takes to grow back, in real seconds.
GetHerbRegrowTime A kind’s regrow time in real seconds.
GetHerbKinds Every kind of herb and mushroom.
SetHerbsEnabled Switches a kind of herb off - or on again - on the whole level or within a circle.
GetHerbZones Where herbs are switched off.
TakeHerbs Takes away every herb of a kind within a circle, as a pick would - for its regrow time, a time of the mode’s, or for good.
ResetHerb A picked spot grows back now, for everyone.
ResetHerbs Every picked spot grows back now - or every one within a circle.
GetHerbsNear The picked spots and the mode’s herbs within a circle, nearest first.
CreateHerb Plants a herb of the mode’s - the kind’s plant with a “Pick” prompt, wherever the mode wants it.
RemoveHerb Takes a herb of the mode’s away for good - or lets go of a picked spot (it grows back at once).

Your own recordings played in the world through the game’s own sound: a line an actor speaks (a voice you recorded or made with a text-to-speech service), a song at a tavern, a bell at a place. Put the files in a sounds/ folder next to your game mode (gamemodes/myrp/sounds/ for gamemodes/myrp/myrp.lua, or the folder [client] sounds names) and name each by its path in that folder: "herald_01.ogg", "voices/elder_greeting.ogg".

  • The kinds: .ogg (Vorbis), .opus, .wav, .mp3 and .flac. A file may be up to [client] sound_max_mb (8 MB unless the server owner sets it, at most 16 MB). For music and long lines Opus or Ogg gives the best sound for the size.
  • When players get them: a file is sent to a player only when a sound of it reaches them, the first time it does - nobody downloads a server’s whole collection at the join. Their game keeps it, so the next time it starts at once. The first time, the sound starts on their screen once the file has arrived, where the others are in it by then (a short line arrives in a moment; a song of several megabytes takes a few seconds). PreloadSound sends a file ahead so it starts at once - a song before the bard plays, the lines of a scene as a player walks in. With [client] sounds_cdn the players’ games fetch the files from the server owner’s own web host instead of from the server.
  • How it sounds: positional, from the actor’s mouth or the place; in the place’s reverb (a church echoes); muffled by the walls between the sound and the listener, as players’ voices are; on the game’s master and sound effects volume (as the NPCs’ own lines). With lip sync (the default for an actor) the actor’s mouth moves with the sound.
  • Who hears it: every player within range metres who sees the actor. A player who comes into range while it plays hears the rest of it from where it is. The server reads each file’s length and tells you its end in OnEntitySoundEnd.
Callback When
OnEntitySoundEnd A sound of PlayEntitySound or PlaySoundAt is over.
Function What it does
PlayEntitySound Plays one of your sound files at an actor, an animal or another entity, through the game’s own sound.
PlaySoundAt Plays one of your sound files at a place, through the game’s own sound.
PreloadSound Sends one of your sound files ahead into a player’s game, so a sound of it later starts at once.
StopSound Ends a sound now on every screen.
StopEntitySounds Ends every sound playing at an entity.
IsSoundPlaying Whether a sound still plays.
GetSoundLength How long one of your sound files plays.

The server keeps no accounts: a name is whoever typed it, and the server remembers nothing about a player between visits. A mode that wants accounts builds them on its own database - a table of names and password hashes, a /register and a /login of its own - with three helpers from here: SetSecretCommand (the clients mask the password as it is typed), HashPassword and VerifyPassword. The shipped freeroam.lua is the worked example; the databases guide walks through it. Admins are the mode’s too: SetPlayerAdmin in OnPlayerConnect (or after the mode’s own login) unlocks the server’s admin-only built-in commands and whatever the mode gates on it - from a list in the script, a column in the mode’s database, any rule the mode likes. Bans are the one thing about a person the server itself keeps: a name or an address, in the server’s own database, across restarts.

The audit ([audit]) compares what a player’s game says with what the server knows happened, in two halves. The item check holds what a player carries - the purse too - against the server’s records: the spawn outfit, GivePlayerItem, pickups, takes from containers, sales to a shop, the game’s own making. An item nothing explains is removed from the player’s game - never a kick, never a violation - and the mode is asked first (OnPlayerAuditViolation; OnPlayerNativeItem for what the game made itself). The progression check judges levels, XP, perk points and perks, the nourishment and the energy, and what a player carries (OnPlayerProgressViolation, GetPlayerProgressAudit, GetPlayerWeight). Both start in observe, which only logs and takes nothing away; [audit] mode = "enforce" acts (the server configuration says what each does). A violation is a cheat the server can prove - a game that ignores an order, forges a claim or goes silent - and OnPlayerCheatDetected hears it, with every hint, before [audit] action decides what happens to the player.

Callback When
OnPlayerAuditViolation The item check found items the server cannot explain - return false to vouch for them.
OnPlayerNativeItem The player’s game made an item of its own - return true to adopt it, false to have it removed.
OnPlayerCheatDetected A sign of cheating - return false to tolerate a proven one.
Function What it does
IsPlayerAdmin Whether the player is an admin.
SetPlayerAdmin Makes the player an admin for the session - or takes it back.
SetSecretCommand Declares a chat command secret - the clients mask its argument as it is typed.
HashPassword Hashes a password for the mode’s own accounts - one text to store as it is.
VerifyPassword Whether a password made a hash text from HashPassword.
Ban Kicks the player and bans their name and address.
BanName Bans a name; whoever is on under it is kicked.
BanAddress Bans an address; whoever is on from it is kicked.
Unban Lifts every ban on a name or an address.
IsBanned Whether a name or an address is banned right now, and why.
GetPlayerAuditViolations How many times the item check took unexplained items out of the player’s game this session.

The level’s gates - the animated defensive pieces, a portcullis that drops and a drawbridge that lifts - belong to the server. The game gives players no hand on them (its own story moves them through cutscenes), so nothing happens to a gate unless a mode or an admin’s /gate asks for it; every client then plays the motion from the server’s clock, a newcomer sees the gate wherever its cycle stands, and a gate turned round mid-way carries on from where it is rather than snapping to an end. A gate has a cycle: closed, opening, open, closing. Open always means passable - a portcullis raised, a drawbridge lowered - and every gate starts a server run that way; a change survives a restart with the doors (world.json). The key is the entity’s level name. The retail levels have seven gates. On kutnohorsko: the Suchdol fortress portcullis (suchdol_fortres_gate_bars3, a full open takes about 12 s, a close about 5 s), the Malesov drawbridge (malesov_drawbridge1, about 8 s either way - the game ships one clip for it, so lowering runs the lifting backwards), the Malesov courtyard gate (malesov_courtyard_gate, the wooden double gate barred by a latch), the gate of Raborsch fortress (raborsch_gate) and the gate of Ruthard Palace in Kuttenberg (ruthard_palace_gate). On trosecko: the door in Trosky castle’s south gate (trosky_south_gate) and the gate of Nebakov fortress (nebakov_gate). The last five have no animation: in the story the game swaps their shut and open halves as the campaign goes, so here they are at the other end at once (no opening / closing); their halves are level layers (SetLevelLayer). The story starts them shut, but a server starts them open like the other two, so a mode that never names them needs nothing for its players to walk through. klaster has none.

A mode that wants them otherwise drives them like the others. On a trosecko server, Trosky’s south gate shut from the first start, an admin’s /castlegate to open it or shut it again, and everyone told when it moves:

function OnGameModeInit()
-- the gate's end is kept across a restart: once shut, this is refused with "is already closed"
SetGateState("trosky_south_gate", false)
end
function OnPlayerCommandText(pid, cmd, args)
if cmd == "castlegate" then
if not IsPlayerAdmin(pid) then
SendClientMessage(pid, COLOR_RED, "Only the castle's admins move its gate.")
return true
end
local ok, opening, reason = ToggleGate("trosky_south_gate")
if not ok then SendClientMessage(pid, COLOR_RED, "The castle gate " .. reason .. ".") end
return true
end
end
function OnGateChange(key, cycle, pid)
-- a gate with no motion fires once, "open" or "closed", the moment it is switched
if key == "trosky_south_gate" then
SendClientMessageToAll(COLOR_YELLOW, cycle == "open" and "The gate of Trosky stands open." or "The gate of Trosky is shut.")
end
end

The same lines with another key drive the others: nebakov_gate on trosecko, malesov_courtyard_gate, raborsch_gate or ruthard_palace_gate on kutnohorsko.

Callback When
OnGateChange A gate’s cycle changed - it started moving, or came to rest.
Function What it does
GetGates Every gate of the level.
GetGateInfo What the server knows of a gate - its kind, cycle, openness and place.
SetGateState Starts a gate towards open (passable) or closed.
ToggleGate Sends a gate the other way - from the end it rests at, or back from the way it is moving.
GetNearestGate The gate nearest a point, within a radius.

The retail levels are full of story layers: parts of the level the single-player story shows and hides as it goes - a gate shut or open, a wall whole or broken, a camp that appears for a chapter. A mode switches any of them on or off for every player at once, the scenery and whatever stands in it together. The server remembers the layers it switched and gives them to everyone who joins later; a layer it never touched stands as the level has it. A switch lasts for the run: after a restart every layer is back as the level has it, so switch yours again when the mode starts (OnGameModeInit). The gates made of layers - the Malesov courtyard gate, the gates of Raborsch and Ruthard Palace, the door in Trosky’s south gate and the gate of Nebakov - are driven through SetGateState, which remembers its end across restarts.

A name is the layer’s full name as the level lists it, a GUID and all (gate_open_a12b1f05-20f2-4d96-825c-57aea7eec798); every level’s list is its own leveldata.xml inside the level’s level.pak in the game folder. A name the level does not have changes nothing - the player’s game writes a line about it in its log. An admin tries a name in the game with /layer <name> on|off.

The story’s doors and gates that open as the campaign goes are such pairs: a shut layer and an open one at the same spot. Show one and hide the other. The five gates above are already SetGateState’s and start a server open, whatever the last column says - leave their layers to it, or the gate’s end of record no longer matches what the players see; the rest are a mode’s to switch:

Level Where (x, y, z) Shut layer Open layer At the story’s start
kutnohorsko 492, 397, 110 - the Malesov courtyard gate gate_closed_7521eeb3-a073-4ed0-a6b0-c4f28662ce64 gate_open_a12b1f05-20f2-4d96-825c-57aea7eec798 shut
kutnohorsko 625, 939, 97 _gateClosed_333eeddb-75c8-46ba-b198-a34b782af916 _gateOpened_6a4f3cb1-4ec5-4fab-ae0d-b2668bae693b open
kutnohorsko 1424, 3856, 118 - the gate of Raborsch _enviro_8c959192-3590-486e-9ba3-7710220b81f9 and its barrier gateBarrier_42dacb18-e0a1-4d4a-af1d-0d0c3a740a8d _enviro_704db1e3-9f9d-485a-9903-d750465211c5 shut
kutnohorsko 1572, 2742, 198 ammoStandingDoorsClosed_3f7e6a2e-52b6-42eb-af72-0be68b24a30c ammoStandingDoorsOpened_d5ae0f36-333b-48c8-89c9-a521bc8adf42 shut
kutnohorsko 3004, 681, 52 - the gate of Ruthard Palace (Kuttenberg) _enviro_b47eca21-382f-4139-b6f0-035f6b00e645 _enviro_c016c439-3032-4d4e-aced-c21f4e0eb777 shut
kutnohorsko 3160, 705, 59 closed_7e695498-0e5b-44d8-a709-d5b9db956b48 open_e12f7609-72e9-4986-9a60-7fb2f70f00bc shut
kutnohorsko 3273, 711, 49 series_M33_closed_03a2dccf-5915-4b8a-806a-c075adf17d49 series_M33_open_7312e5b6-d00a-4a9a-9158-25bddcf88fb5 open
trosecko 2522, 2593, 178 - the door in Trosky’s south gate closed_58e73ca0-b151-4782-8256-c27cff2faafd open_f84fd4ff-472b-4fa8-b321-3453e8e46480 shut
trosecko 2435, 2650, 200 - Trosky closed_382af151-34ff-4593-b7a3-47b8f86e9601 open_d2670ef8-8b5f-4888-9619-71c6e59220f5 open
trosecko 2402, 2606, 208 - Trosky closed_a7e0becc-3434-48e0-a50c-4d45766b7216 open_35b343c5-06b9-411a-a469-43acbd2d7207 open
trosecko 2327, 2067, 111 closed_20789307-18df-4f59-b9d9-2482b5d7d8de openworld_afe1facd-5750-4825-9cbb-09879bbc5f19 open
trosecko 1884, 1208, 49 - the gate of Nebakov _enviro_b47cb32f-a357-454f-9d82-f14a5304db9e _enviro_e42466fa-a77d-4eda-bc30-3054d72409e1 shut
trosecko 1631, 1571, 78 - Semine closedGate_e7fb589e-a824-45d9-9a28-081f9c682f70 openGate_d141e039-f6c8-4d65-aabb-78f7d8876736 open
klaster 1290, 1050, 26 closed_8125ceb2-6277-41b8-93a2-82a31e8258d8 opened_f96643f2-c3fe-4e7a-be82-f2d019c1d490 open

The story’s quests stay asleep unless a mode wakes them (SetStoryQuests), and every player’s game still sets the level’s story layers the way the story’s start leaves them - the switches here start from there. Switch layers with care: some bring the story’s own people or objects with them, and a layer that belongs to a cutscene can put things where nothing makes sense outside it. Try a layer on a test server first.

Finding a layer. Stand at the wall, fence or heap you are after and type /layer near [radius] (10 m by default): it lists the layers with a solid piece around you, the nearest first; a mode asks the same with GetLevelLayersNear. Both need the game’s tables exported with this version or later (they carry where each layer’s pieces stand). Then try the name with /layer <name> off. When a layer is switched off, the server’s own collision leaves its pieces out as well, so shots, the ground and line of sight no longer stop at a fence the players walk through.

Some stretches of wall or fence are a layer of their own and can simply be taken away - Suchdol’s wooden fence around its moat, for one, which every player’s game puts up at the story’s start:

Level Where (x, y) Layer
kutnohorsko Suchdol’s fence, north of the moat (752-781, 3390), about 30 m _enviro_42bc6bcf-ee00-462b-9e13-feb67caf65f7
kutnohorsko Suchdol’s fence, west side (717, 3328-3371), about 45 m _enviro_85efbddf-dbac-4b30-8175-593702607b9d
kutnohorsko Suchdol’s fence, east side (784, 3344-3354), about 10 m _enviro_63144b81-9459-4649-95b2-7c7086e18b46

A siege that breaks a stretch down after a few hits counts the shots in OnSiegeImpact - a whole stretch goes at once:

local NORTH_FENCE = {layer = "_enviro_42bc6bcf-ee00-462b-9e13-feb67caf65f7", x0 = 750, x1 = 783, y0 = 3387, y1 = 3393, hits = 0}
function OnSiegeImpact(id, x, y, z, shooter, shot, what, target)
local f = NORTH_FENCE
if x >= f.x0 and x <= f.x1 and y >= f.y0 and y <= f.y1 then
f.hits = f.hits + 1
if f.hits == 3 then
SetLevelLayer(f.layer, false) -- the fence comes down for everyone
SendClientMessageToAll(COLOR_YELLOW, "The north fence of Suchdol is down!")
end
end
end

The levels also fence players off with invisible barriers: walls no one sees that stop a player at deep water (“you cannot swim”), at the edge of the map and along some story paths. A mode lifts them in a circle of its choosing with SetLevelBarriers - so a siege’s attackers can wade Suchdol’s moat to their ladders - and puts them back the same way. A barrier piece that reaches into the circle is lifted whole, so keep the circle small near the map’s edge. Like the layers, the areas last for the run.

Function What it does
SetLevelLayer Switches one of the level’s story layers on or off for every player.
GetLevelLayer A layer as this server switched it.
GetLevelLayers Every layer this server has switched.
GetLevelLayersNear The level’s story layers with a solid piece near a point.
SetLevelBarriers Lifts or puts back the level’s invisible barriers in a circle, for every player.
GetLevelBarriers The areas where the level’s invisible barriers are lifted.

An area is a named piece of the level - a box, a cylinder, a sphere or a polygon standing on the ground - that the server checks every player against ten times a second. A mode hears OnPlayerEnterArea and OnPlayerLeaveArea by the area’s name and builds its rules on them: a town where nobody fights, a market that takes a tax, a race’s finish line, a plot that belongs to a player. Areas live in the server’s map like its placed objects: written, there after a restart and after a mode reload (a mode’s own with persist = false last for its run only). An admin draws one with /map area in the game.

An area may carry the mode’s own values (SetAreaProperty: an owner, a tax, pvp = false), kept with it. Its label is shown to every player who comes in when it is public (“Kuttenberg market”). An area on a map layer that is switched off holds nobody (SetMapLayer). Places are in metres; a box is at most 2 km across and 500 m high.

An area can also be a trespass zone of the game’s own kind: inside it the game shows its trespass icon - blue for someone’s home, red where nobody may go - and the mode hears OnPlayerTrespassChange (SetAreaTrespass, SetPlayerAreaTrespass for one player, SetPlayerTrespass anywhere). The level’s own houses, keeps and camps carry the game’s trespass too; a mode switches them off (SetLevelTrespass) or makes one public for its owner. Nobody reacts on their own in multiplayer - a fine, a warning or a guard’s call are the mode’s. And an area can be a roof: SetAreaRain caps the rain a player inside sees (0 = dry), for the buildings put up with the map editor.

Callback When
OnPlayerEnterArea A player came into one of the map’s areas.
OnPlayerLeaveArea A player left one of the map’s areas.
OnPlayerTrespassChange The trespass level a player’s game shows changed.
Function What it does
CreateArea Makes one of the map’s areas.
SetArea Gives an area a new shape, label, colour or layer.
DeleteArea Takes an area off the map; whoever was in it leaves it.
GetArea An area as it stands.
GetAreas Every area of the map, by name.
GetAreasAt The names of the areas holding a point.
IsPlayerInArea Whether a player is in an area now.
GetPlayerAreas The areas a player is in now.
SetAreaProperty Keeps one of the mode’s values on an area.
GetAreaProperty One of the mode’s values on an area.
SetAreaTrespass Makes an area one of the game’s trespass zones.
SetPlayerAreaTrespass An area’s trespass level for one player.
SetPlayerTrespass One player’s trespass level wherever they stand.
SetLevelTrespass Switches the level’s own trespass areas on or off.
IsLevelTrespassOn Whether the level’s own trespass areas are on.
SetPlayerLevelTrespass The level’s own trespass areas for one player.
GetPlayerTrespass The trespass level a player’s game shows now.
SetAreaRain The most rain a player inside an area sees.
SetPlayerRain The most rain one player sees, wherever they stand.
GetPlayerRain The rain a player’s game shows now.

The server’s map is what the server adds to the level and takes out of it: the game’s own meshes placed anywhere - a house, a wall, a fence, barrels, a market’s stalls - turned every way and scaled, and parts of the level itself removed - a house, a wall, a rock, a tree, one of its entities. It lives on the server ([[docs:getting-started/server-config.md|[world] map]]): every player’s game downloads it when they join - before they appear in the world - keeps it for the next join, and gets every change at once. Players walk through what was removed and stand on what was placed, and the server’s own collision follows both.

Admins build it in the game with the map editor (/editor - Using the map editor) or with /map (/map place <mesh>, /map near, /map move, /map turn, /map scale, /map delete, /map layer); a game mode builds it with the functions below. Besides meshes the map holds the game’s working things - lights, particle effects, sounds (CreateMapLight, CreateMapEffect, CreateMapSound, /map place light|effect <name>|sound <trigger>) and markers only the mode reads (CreateMapMarker, GetMapMarkers) - and any object may carry a use prompt that players see with the game’s own hint (OnPlayerUseMapObject, /map use <id> <prompt>). What either makes is written into the map and is there after a restart - unless the mode passes persist = false: such a record lasts for the run of the mode only, is never written, and goes when the mode is reloaded, so a mode that places its own set pieces in OnGameModeInit never doubles them.

The owner’s own pictures (PNG files in the map folder’s pictures/) and the web interface’s surface pages hang on boards (CreateMapPicture, CreateMapSurface); any object may sit on another (attach) and move with it.

Every object and removal belongs to a map layer ("base" unless named): a layer switched off takes everything in it out of every game at once and back when it is switched on - an event’s build, a winter market. A mesh is named by its path in the game’s files ("objects/manmade/common_furniture/barrels/barrel_a.cgf" - the meshes list). Places are in metres; a turn is yaw (about the up axis, as a player’s yaw: 0 faces +Y), pitch (the front tipped up) and roll (leaned sideways), in degrees.

Callback When
OnPlayerMapReady A player’s game has the server’s map - or could not get it.
OnMapEdit A player’s edit in the in-game map editor, before it is made - return false to refuse it.
OnPlayerUseMapObject A player pressed the use key on a map object with a use prompt.
Function What it does
SetPlayerEditor Opens the in-game map editor for a player - with what they may do - or closes it.
GetPlayerEditor What a player’s open map editor may do.
CreateMapObject Places one of the game’s meshes on the level, for every player.
SetMapObject Changes a map object - moves, turns, scales it, or anything else it has.
DeleteMapObject Takes a map object off the level for everyone.
GetMapObject A map object as it stands.
GetMapObjectsNear The map objects around a point, nearest first.
CreateMapPicture Hangs one of the map’s pictures on the level - a poster, a banner, a painting, a shop’s sign.
CreateMapSurface Hangs one of the web interface’s surface pages on the level as a map object - a notice board that stays with the map.
GetMapObjectSurface The web surface a “surface:” map object shows.
GetWebSurfaceMapObject The map object a web surface of the map shows.
GetMapPictures The map’s pictures - the PNG files of its pictures folder.
ReloadMapPictures Reads the map’s pictures folder again - a picture added, changed or taken away.
CreateMapLight Places a light on the level, for every player.
CreateMapEffect Places one of the game’s particle effects on the level - a fire, smoke, a candle’s flame - for every player.
CreateMapSound Places a sound of the game’s - a crackling fire, a brook, a smithy’s loop - on the level, for every player.
CreateMapMarker Places a marker - a point only the editor and the mode know - on the level.
CreateMapDoor Places one of the game’s doors on the level - it opens, closes and locks for everyone.
CreateMapSeat A place to sit or a bed to sleep in, on any object - players use it with the game’s own Sit and Sleep.
GetMapMarkers The map’s markers of a tag.
RemoveLevelObject Takes a part of the level out on every player’s game - a house, a wall, a tree, an entity.
RestoreLevelObject Puts a removed part of the level back for everyone.
GetLevelRemovals Every part of the level the map takes out.
SetMapLayer Switches a map layer on or off for every player.
GetMapLayers Every map layer and whether it is on.
GetMapInfo The server’s map - what it holds and where it stands.
SaveMap Writes the map to its folder now.
ExportMap Writes the map as one file, to keep or to carry to another server.
GetMapExports The exports in the map’s folder, newest first.
ImportMap Brings an export into the map - merged beside what is there, or replacing it.
BackupMap Writes a backup of the map now.
ImportSandboxLayer Adds a layer saved from the Sandbox editor to the map.
SetPlayerMapLayer Shows (or hides) a map layer to one player alone.
GetPlayerMapLayers The map layers a player sees otherwise than everyone.
ResendPlayerMap Sends one player the map again, as at their join.
GetMapPrefabs The map’s prefabs - sets of objects saved under a name.
SaveMapPrefab Saves map objects as a prefab, to place again anywhere.
PlaceMapPrefab Places a prefab’s objects as new map objects.
CreateMapPrefab Places a prefab as one unit - one map object drawn as the prefab’s objects, that follows the prefab.
GetMapPrefabParts A prefab unit’s objects as they stand on the level.
UnpackMapPrefab Turns a prefab unit into the prefab’s objects, each a map object of its own.
DeleteMapPrefab Takes a prefab off the list (its placed objects stay).
CreateNavLink Lets the server’s actors go between two points their walk cannot join - a jump down, a gap, a ladder.
DeleteNavLink Takes a nav link off the map.
GetNavLinks The nav links with an end near a point.

The server resolves the game’s things by id, name or GUID through the tables export ([combat] tables): items (the item catalogue), souls (the souls), buffs (the buff list) and meshes (the meshes; GetMeshPath and FindMeshes are with the props). Every function that takes an item, a soul or a buff accepts any of the keys; these look them up, search them and turn one key into another. The id is the row number of the name-sorted export - stable for one export of one game build, so keep the name or the GUID in anything durable. Without the export only GUIDs pass, unchecked.

Function What it does
GetItemClass The class GUID an item key stands for.
GetItemName The game’s name of an item key.
GetItemInfo The catalogue’s entry for an item key.
FindItems Items whose name, English name or category holds every word of a pattern.
GetHorseSoul The soul GUID a horse key stands for - the Horse archetype only.
GetSoulInfo The soul catalogue’s entry for a key, of any archetype.
FindSouls Souls whose name or archetype holds every word of a pattern.
GetBuffGuid The GUID a buff key stands for.
GetBuffInfo The buff catalogue’s entry for a key.
FindBuffs Buffs whose name, English name or class holds every word of a pattern.

Players grouped with a leader (v38, the guide): the server keeps the group, the invitation with its timeout and the toast on the target’s screen, the party frames every member sees (the others’ name, health, stamina, wounds, at any distance and in any world) and the no-friendly-fire rule. The server ships no party commands: /invite, /accept, /p and every rule around them - who may invite, a level gate, leader-only invitations - are the mode’s, written around these callbacks and functions (the shipped freeroam mode carries the plain ones). A party is a number; ids count up and are never reused while the server runs. A party exists with two or more members and ends when it falls to one - there is no party of one. One party and one pending invitation per player. [party] in the server’s configuration holds the size (5), the invitation’s timeout (30 s), the frames’ default, what the leader’s leaving does and the friendly fire.

Callback When
OnPartyInvite A player wants to invite another; return false to refuse.
OnPartyInviteResponse An invitation was answered - or ran out, or fell through.
OnPartyCreate A party came into being.
OnPlayerJoinParty A player joined a party - the leader too, at the party’s birth.
OnPlayerLeaveParty A member is gone from the party.
OnPartyLeaderChange The lead changed hands.
OnPartyDisband The party is over.
Function What it does
InviteToParty Sends a party invitation - the mode’s /invite.
AcceptPartyInvite Accepts the player’s pending invitation - the mode’s /accept.
DeclinePartyInvite Declines the player’s pending invitation - the mode’s /decline.
GetPlayerPartyInvite The player’s pending invitation.
AddPlayerToParty Puts a player into another’s party without an invitation.
RemovePlayerFromParty Takes a player out of their party - the mode’s /leave and /pkick.
SetPartyLeader Hands the lead to a member - the mode’s /leader.
DisbandParty Ends a party.
GetPlayerParty The party the player is in.
GetPartyLeader The party’s leader.
GetPartyMembers The members, in join order.
GetPartySize How many members the party has.
IsPartyFull Whether the party is at [party] max_size.
ArePartyMembers Whether two players are in one party.
GetParties Every party on the server.
SetPartyName The party’s title, shown over the members’ frames.
GetPartyName The party’s title.
SetPartyMemberLabel A line under the member’s name in the frames - a role, a score.
GetPartyMemberLabel The member’s label.
ShowPartyFrames Whether this player sees the party frames.
SendPartyMessage One chat line to every member - the mode’s /p.
SetPartyData The mode’s private storage on a party.
GetPartyData A value of the mode’s private storage on a party.

A shop is a thing the server keeps: a title, the items it sells with a price and a stock, what it buys from the players and at what price, and its purse. Put a shop on an NPC actor - CreateVendor makes one in a single call, SetActorShop puts a shop on an actor you have - and it becomes a vendor: “Trade” shows under its name within reach and the use key opens the game’s own trade screen, the one a merchant opens in the story - the player’s things on one side, the vendor’s shelf on the other, a basket, the prices and both purses along the bottom, “Close deal”. Haggling is off. A deal closes the screen, as in the story; the use key opens it again. Open a shop on a player outright with OpenShop - from a command, a zone, a chest - and it shows on the shop panel instead: a list in the game’s own look with a Buy tab and a Sell tab, driven with the keys (W / S move, A / D set the quantity, Tab switches the tabs, Enter buys or sells, Esc closes); SetShopScreen keeps a vendor on the panel too.

Every transaction is the server’s. A deal - the panel’s one line or the trade screen’s basket - is checked as a whole: the stock, what the player carries, and the purse that changes hands, where the sales pay for the purchases (what the player carries and their purse are what the server’s records explain - GetPlayerMoney, GetPlayerInventory; under [audit] mode = "observe" what their game holds). A sale takes the exact items the trade screen named, and an item the game will not let go of - a quest item - is not for sale. Under enforce a deal in the first seconds of a visit, before the server follows the player’s bag, is turned down with “Not now: your items are still being checked.” The mode may refuse each line in OnPlayerBuy / OnPlayerSell and the whole in OnPlayerShopDeal; one no calls it all off. The items and the money then move by the same road as GivePlayerItem: the purchase is a gift, the sale an exact order, so the item check explains them, and a sold item is final even if the player’s game claims to have kept it. Prices are Groschen (12.5 is fine). What a shop buys: sellFactor of an item’s catalogue price (GetItemInfo price, which the game keeps in tenths of a Groschen - a torch is 60) - never more than the shop itself asks for an item it sells - narrowed to some categories with SetShopBuyCategories and priced class by class with SetShopBuyPrice; the trade screen offers the vendor exactly that and nothing else. The screen closes when the player walks 4 m from the vendor, the vendor dies or goes, the player dies or leaves, the mode says CloseShop, or they close it. A reload takes every shop down. A shop is a number; ids count up.

Callback When
OnPlayerBuy The player is about to buy from a shop - return false to refuse.
OnPlayerSell The player is about to sell to a shop - return false to refuse.
OnPlayerShopDeal A deal is about to be done - every line at once; return false to call it off.
OnPlayerOpenShop A shop screen is about to open on a player - return false to keep it closed.
OnPlayerCloseShop The shop screen closed on a player.
Function What it does
CreateShop Makes a shop - a title, whether it buys, its purse.
DestroyShop Removes a shop; the screens on it close, the vendors selling it stop.
IsValidShop Whether a shop id names a shop.
SetShopItem Puts an item on the shelf - or changes its price and stock.
RemoveShopItem Takes an item off the shelf.
SetShopTaggedItem Puts one of your tagged items on the shelf - a prize, a charter, a key - under its own name.
RemoveShopTaggedItem Takes a tagged row off the shelf (SetShopTaggedItem).
GetShopItems The shelf - every row with its price and stock.
GetShopMoney The shop’s purse in Groschen.
SetShopMoney Sets the shop’s purse.
GetShopTitle The shop’s title.
SetShopTitle Renames the shop; open screens show the new title.
OpenShop Opens the shop screen on a player.
CloseShop Closes the shop screen on a player.
GetPlayerShop The shop open on a player’s screen.
CreateVendor Makes a vendor - an NPC actor nobody can hurt, selling a shop.
SetShopScreen Which screen a vendor’s shop opens on - the game’s trade screen or the panel.
GetShopScreen The screen a vendor’s shop opens on.
SetShopBuyPrice What a shop pays for one item class, whatever its sell factor says.
GetShopBuyPrice What a shop pays for one piece of an item now.
SetShopBuyCategories The item categories a shop buys at its sell factor.
GetShopBuyCategories The item categories a shop buys at its sell factor.

A dialogue is a conversation a game mode holds with one player, one page at a time: who speaks, their line, and 1 to 8 choices for the player’s answer, shown on their screen in the game’s own conversation look - the line as the game’s subtitle (“Watchman: Halt! …”), the choices in the game’s list with its gold highlight - while their movement is held. The player moves with W / S (or the arrows), picks with E, Enter or Space (or a row’s number, 1-8) and leaves with Esc; a greyed-out choice is skipped and cannot be picked. The usual start is an NPC actor with a Talk prompt (SetActorPrompt) and ShowPlayerDialogue from OnPlayerInteractActor; any command, zone or timer may open a page too.

Each page carries a number of the mode’s choosing, dialogid, which comes back with the answer in OnDialogueResponse - the SA-MP way. A pick closes the page unless the callback shows the next one, so a conversation is a chain of pages the mode walks through. A choice may be shown greyed out (enabled = false): something the player sees but cannot pick yet. With an actor the page closes when the player walks 5 m away from it, or it dies or goes; a death or leaving the server closes it too, and the mode hears why.

Callback When
OnDialogueResponse A player answered a dialogue page - the choice they picked, or 0 when it closed.
Function What it does
ShowPlayerDialogue Shows a dialogue page on a player’s screen - who speaks, their line and the choices.
HidePlayerDialogue Closes the dialogue page open on a player.
GetPlayerDialogue The number of the dialogue page open on a player’s screen.

A player’s gesture for everyone around - a wave, a bow, a cheer, a dance. Players hold G for the emote wheel (the mouse picks, letting go of G plays it; a quick tap leaves the wheel open for a click, the number keys pick directly) and hold T to point - the arm stays out while T is down, and the player can walk meanwhile; the others see their body make it and the player sees it in first person. The server checks every pick - the player alive, standing still on foot, no weapon out, not fighting - and ends a looping one (the dance) when the player steps away, crouches, draws, mounts, is hit or dies; a player who comes into view later still sees a dance, or a point held.

The built-in emotes: wave, bow, cheer, clap, dance (loops), point (the upper body alone: it plays while the player walks or crouches; T holds it), salute, come, nod, sit (on the ground: the player sits down, stays seated and stands up again when it ends), armscrossed (the arms folded until the player moves), drink (a gulp from a tankard, the upper body alone - the one a sip from a tankard in the hands plays, SetCarryItemDrink, and the others see when a player drinks from the bag). The wheel shows wave, bow, cheer, clap, dance, come unless the [emotes] section of server.toml names others - or SetEmoteWheel does; the owner’s own emotes go in [emotes.custom], a mode’s through AddEmote. OnPlayerEmote can refuse a pick, PlayPlayerEmote makes a player perform one.

A chat command for them is the mode’s: the server has none of its own. The shipped modes answer /anim <name>, /anim stop and /anim (the list) with PlayPlayerEmote, StopPlayerEmote and GetEmotes - the example under PlayPlayerEmote is the whole command, to copy under any name.

Callback When
OnPlayerEmote A player picked an emote; return false to refuse it.
Function What it does
GetEmotes The names of every emote this server knows.
GetEmoteWheel The emotes on the wheel, in its order (clockwise from the top).
SetEmoteWheel Puts other emotes on everyone’s wheel.
AddEmote A new emote, or a new look for a known one.
PlayPlayerEmote Makes a player perform an emote - the heart of an emote command.
StopPlayerEmote Ends a player’s emote on every screen.
GetPlayerEmote The emote a player is making now.

A player’s look is the parts of the game’s characters their body wears: the skin (body), the face (head), the hair and its color, and the beard. Each part is named as the game names it - m_body_tan_02, m_head_004, m_hair_005_blonde, m_beard_03 - and GetLookParts lists what a man’s body may wear, or a woman’s (the look parts are the same lists on paper). A look is a Lua table {body = ..., head = ..., hair = ..., beard = ...}; a part left out is the one the body’s soul gives it (the spawn’s appearance, SetSpawnInfo).

A woman’s body: gender = "female" in the table ("gender=female" in the one-line form) makes the player a woman - her own skeleton, her walk and her voice in combat - with a woman’s face, hair and skin (f_head_013, f_hair_004_blonde, f_body_pale_01; a woman has no beard). A look whose parts are all a woman’s is a woman’s without saying so. The two bodies’ parts never mix. Everything a man wears a woman may wear too, with its protection; the game has no women’s armour, so a woman’s dress stands in for a man’s clothes and armour on her body (its cut from what she wears), his hoods and helmets are left off (her own hair and face show), his boots show as they are and his scabbards without their waist belt.

The rejoin on a new body: a player’s own game changes its own body only while the map loads. A player whose look turns from a man’s into a woman’s (or back) while in the world - a new character made in the mode’s creator, a look changed later - is asked once to restart: the game closes, joins the same server again under the same name on the new body and remembers it for that server, so every later visit loads on it at once. The others see the new body at once and never restart. A new character’s first visit always joins on a man’s body (the game loads before the mode knows the character), so a new woman is asked once, after her creation. The restart is the player’s game’s own; what a mode does about it: it keeps the look, gender with it, in its own database and gives it back with SetPlayerLook at every login (a player who rejoined as a woman and gets a man’s look back is asked again); it gives the look as early as it can - at the login, before the player plays - so the question comes at once; and it treats the rejoin as a plain leave and join, OnPlayerDisconnect and then OnPlayerConnect with nothing to tell them apart: what the mode keeps (the place, what the player carries, the horses) is saved on the leave as always, and a mode with its own login asks for it again. The shipped basicrp.lua does all of this.

SetPlayerLook gives a player a look: everyone who sees them gets it at once, their own game too (their own body, the inventory’s figure), and it lasts through every respawn until the next call or the end of the visit. The server remembers no look past a visit - a mode that keeps them saves the look in its own database: LookToString turns it into one line for a text column and SetPlayerLook takes that line back. SetActorLook dresses an NPC actor’s body the same way.

A character creation screen is the mode’s own: its client half draws the menu, shows the choices on a preview body only the player sees (ShowLookPreview) and asks for the look it settles on (RequestLookChange); the server checks the parts and hands the ask to OnPlayerLookChange, and the look is the player’s once the mode takes it. A mode without that callback takes no look from a player. The shipped basicrp.lua has a whole creator: it opens for a new character and on /look, and keeps the look with the account. The character creator guide walks through building one.

Callback When
OnPlayerLookChange A player asks for a new look; return false to refuse it.
Function What it does
SetPlayerLook Gives a player a look - the skin, the face, the hair and the beard - on every screen.
GetPlayerLook A player’s look.
SetActorLook Gives an NPC actor a look.
GetActorLook An NPC actor’s look.
GetLookParts The parts of one kind a man’s look may name - or a woman’s.
GetLookPartInfo What a part name is.
LookToString A look as one line - what a database column keeps.
LookFromString A look’s one line back into its table.

The game’s own dice game between two players - the tables in the taverns, the dice, the keys, the scoring and the animations of single player. Two players stand together at a dice table; the mode starts a match with StartDiceMatch (the shipped modes answer /dice <name> [bet] and /dice accept), and both games walk their player to the table and seat the other across it. Each player plays on their own screen: the throw is automatic, they pick their dice and press F to score and throw the rest, or Q to score and pass; the other player’s picks appear one by one on the other side of the table. The challenger throws first.

The server keeps the two games the same and fair: it deals every throw, checks every move against the game’s scoring, keeps the totals and holds the stakes - the bet leaves both purses when the match starts and the winner takes both. A match ends when a player reaches the goal on a pass (“goal”), gives up (Esc in the game, “gave up”), leaves (“left”), dies (“died”) or lets a move wait longer than the match’s turn timeout (“timeout”, StartDiceMatch) - that player loses. A match is called off and the stakes go back when a fight breaks out, a player walks away or rides off, a game could not set the table up (“failed” - no dice table near the two players) or a move does not fit the dice (“out of step”). OnDiceMatchEnd hears every ending.

The game type sets the goal: 0 the beggar’s game (1500 points), 1 the wagoner’s (2000), 5 the craftsman’s (3000), 9 the courtier’s (4000) - the ones played without badges; the players’ own dice are not used yet (every throw is a fair one of plain dice).

The rules are the mode’s, not the server’s: there is nothing about dice in server.toml. Whether players may play at all, the goal, how long a move may take and how far apart the two may stand at the start are what the mode passes to StartDiceMatch - the shipped modes keep them in a DICE table at the top of their dice command, for the owner to change.

Scoring, as the game counts it: a single one 100, a single five 50; one to five 500, two to six 750, one to six 1500; three of a kind 1000 for ones and the face times 100 for the others, and every further die of the kind doubles it. Only dice that score can be kept, and a throw with none is a bust - the points of that turn are lost.

Callback When
OnDiceMatchStart A dice match started.
OnDiceMatchEnd A dice match ended - who won, or why it was called off.
Function What it does
StartDiceMatch Starts a match of the game’s dice game between two players - the heart of a dice command.
EndDiceMatch Ends a running dice match, with a winner or without one.
GetPlayerDiceMatch The dice match a player is in.
GetDiceMatchInfo The state of a running dice match - the players, the stake, the goal, the totals, whose turn it is.

Things carried in the hands the way the game’s own people carry them - a sack on the shoulder, a basket in both hands, a bucket, a crate - with the game’s own pickup, its carry walk and its put-down, and every player who has the carrier in view sees the same. A carry item is a world entity of kind ENTITY_CARRY: it lies in the world where the mode made it (CreateCarryItem) or where a player put it down, until someone picks it up. It is nobody’s property and it never enters an inventory.

The players’ own pickup is off until a mode switches it on (SetItemCarrying): then a carry item shows the game’s “Pick up” prompt to a player within reach whose hands are free, and the mode has the last word on each (OnPlayerPickUpCarryItem). The mode’s own orders - PickUpCarryItem, GivePlayerCarryItem - work either way.

One item per player, one player per item. Sacks, baskets, buckets and jugs are carried with the game’s own carry: he walks (no running or sprinting with a sack or a basket), his hands are busy - no weapon, no doors, no horse - and the game’s put-down key (the use key) lays the item down in front of him, or greys out where there is no room. Everything else - a crate, a tool, a lantern, the torch tool, a tankard or a stein - goes straight into his hands the way the game’s people hold it (a lantern in the left; a tankard or a stein with the game’s own reach for it and set it down, the rest with no pickup animation), and holding the use key a moment puts the item down in front of him. A carry item can be any item of the game, but the ones made to be carried or held look right: the sacks (mlynaruvUcen_sackcarryable, kejkliri_sackcarryable, sack_miller …), the baskets (basket_b_apples, basket_b_bread, laundryBasket, basket_full_wood …), the buckets (waterBucket, milkBucket), the crate_with_silver, the tools (shovel, lumberjack_axe, normalHammer, fishing_rod), the jugs, tankards and steins (jug_pewter_small_copper, wooden_tankard, wooden_stein) and the lanterns (lamp_tool, lamp_toolFancy, torch_tool). A barrel, a pitchfork or a broom does not: no animation of the game’s holds one well while walking.

The carry ends when the carrier puts the item down, when the game knocks it out of his hands, when the mode says so (DropPlayerCarryItem, TakePlayerCarryItem), or on anything the server does to him: a death, a disconnect, a teleport (SetPlayerPos), a respawn, a ride (MountPlayer), a cart seat, a flight (SetPlayerFlying), a knock-out, another virtual world - then the item drops where he stood. A pickup that never finishes is cut after eight seconds. OnPlayerPutDownCarryItem says why it ended and where the item lies. A player whose game cannot carry things (an older build) is never given one.

Reserved state keys. The prompt is shown through the world state key carryitems ("1" while SetItemCarrying is on) and the entity state keys carry ("0" on an item SetEntityCarryable took out of the prompt) and carry_use (an item whose left button SetCarryItemUse gave the mode). Do not set them with SetGlobalState or SetEntityState yourself. A mode reload (ReloadGameMode) switches the pickup off again with the default rules; an item in someone’s hands stays there.

Callback When
OnPlayerPickUpCarryItem A player reaches for a carry item with the “Pick up” prompt - return false to refuse.
OnPlayerPutDownCarryItem A carry item left a player’s hands - it lies at x, y, z.
OnPlayerUseCarryItem A player pressed or let go of the left mouse button while holding a carry item the mode made usable.
Function What it does
SetItemCarrying Switches the players’ own pickup of carry items on or off, with its rules.
GetItemCarrying Whether the players’ own pickup of carry items is on, and its rules.
CreateCarryItem Lays a carry item in the world - a sack, a basket, a bucket to be picked up and carried.
PickUpCarryItem Has a player pick up a carry item - the mode’s own order.
GivePlayerCarryItem Makes a new carry item and puts it in a player’s hands.
DropPlayerCarryItem Makes a player let go of what he carries - at once, where the mode says.
TakePlayerCarryItem Takes away what a player carries, for good.
GetPlayerCarryItem What a player carries in his hands, if anything.
GetCarryItemHolder Who holds a carry item, if anyone.
SetCarryItemDrink Fills a tankard or a stein - what a sip from it gives and how many sips are left.
GetCarryItemDrink What a carry item holds to drink.
SetCarryItemUse Makes the left mouse button the mode’s while a player holds a carry item - one item, or every item of a class.
GetCarryItemUse Whether the left mouse button on a carry item, or on an item class, is the mode’s.

The game’s own grab, carry and put-down: a player - or an NPC actor the mode makes - takes a body that lies down over the shoulder, walks with it and puts it down, and every player who has both bodies sees the same. The body can be a character that lies dead (an NPC actor’s, or a dead player’s when [combat] corpse_seconds keeps it), a knocked-out player (SetPlayerKnockedOut) or a knocked-out NPC actor (SetActorKnockedOut); a mode can also have any player or actor carried (CarryPlayer, CarryEntity), who then shows knocked out for the carry and wakes after it. A new guide walks through it: Knocking a player out and carrying them.

The players’ own grab is off until a mode switches it on (SetCarrying): then the game’s “grab” prompt shows on a body that lies down, within reach, as far as the rules allow, and the mode has the last word on each (OnPlayerCarry). The mode’s own orders - CarryPlayer, CarryEntity, ActorCarryEntity, ActorCarryPlayer - work either way.

One carry per carrier, one carrier per body. The carrier’s pace is held to the carry’s speed (a quarter above it is allowed: the games’ positions are a few frames old) and he cannot sprint, jump, fight, ride, take a cart seat, make an emote or start a dice match; a carried player’s own game is carried by the carrier’s body, so the server does not judge his position meanwhile, and he cannot fight or act. After the put his first moments - his game puts him down a metre or two from where the server has him - pass the movement checks within four metres, for three seconds.

A carry ends when the carrier puts the body down, when the game breaks it off (a blow on the carrier), when StopCarry says so, or on anything the server does to one of the two: a death, a disconnect, a teleport (SetPlayerPos), a respawn, a ride (MountPlayer), a cart seat (PutPlayerInCart), a flight (SetPlayerFlying), another virtual world (SetPlayerVirtualWorld, SetEntityVirtualWorld), the body or the carrying actor removed (DestroyEntity) - then every screen lets go at once. A grab or a put that never finishes is cut after eight seconds. OnPlayerCarryEnd says why. A put ordered while the grab still goes on (StopCarry) waits for the grab to finish, then plays. A body the game could not grab stays where it lay. Where a carrier puts a body down is the game’s own put as long as it lies within a few metres of him, on his level, on the ground and not behind a wall; otherwise the server lays it a step ahead of him. A player’s game that cannot carry (an older or unsupported build) takes no part in a carry: the server starts nothing with it. A dead player’s corpse (corpse_seconds) is a body like any other: it is carried, searched where it lies after the put, and it goes when its time runs out. The server keeps at most two corpses of one player, and a quarter of [world] max_entities in all, as bodies that can be carried - a new one past a limit takes the oldest one’s place - so that nobody can fill the world’s entity table with them.

A knocked-out player’s health stays as it is; they drop, their screen goes dark, they cannot fight, ride, act, make an emote or start a dice match, and they are carried the way a corpse is. The knock-out ends when its timer runs out, when the mode says so, or with a death, a disconnect or a respawn (OnPlayerWake).

Reserved state keys. The grab’s prompt is shown through two state keys the server writes: the world state carry ("1" while SetCarrying is on, cleared when it is off) and the entity state carry ("0" on a body SetEntityCarryable took out of the grab). Do not set carry with SetGlobalState or SetEntityState yourself - the next SetCarrying or SetEntityCarryable overwrites it, and a "1" with the grab off shows a prompt that every ask then refuses. A mode reload (ReloadGameMode) takes the grab down with the old mode: it is off with the default rules and every body is carryable again until the new mode’s OnGameModeInit calls SetCarrying (a carry that runs goes on).

Callback When
OnPlayerCarry A player reaches for a body with the game’s grab - return false to refuse.
OnPlayerCarryStart A player began carrying a body - the grab starts.
OnPlayerCarryEnd A carry is over - the body lies at x, y, z.
OnPlayerKnockedOut The player was knocked out.
OnPlayerWake The player is no longer knocked out.
Function What it does
SetCarrying Switches the players’ own grab on or off, with its rules.
GetCarrying Whether the players’ own grab is on, and its rules.
CarryPlayer Has a player carry another player over the shoulder - the mode’s own order.
CarryEntity Has a player carry an NPC actor’s body - or a dead player’s corpse - the mode’s own order.
StopCarry Puts down the carry of a player - the carrier or the carried one.
IsPlayerCarrying Whether the player carries a body or another player.
IsPlayerCarried Whether another player or an NPC actor carries the player.
GetPlayerCarrying Whom or what the player carries.
GetPlayerCarriedBy Who carries the player.
GetEntityCarrier Who carries the body.
SetEntityCarryable Takes a body out of the players’ grab, or puts it back.
ActorCarryEntity Has an NPC actor carry a body - a guard dragging a corpse.
ActorCarryPlayer Has an NPC actor carry a player.
ActorPutDown Has an NPC actor put down what it carries.
SetPlayerKnockedOut Knocks a player out, or wakes them - the game’s own knock-out, health as it is.
IsPlayerKnockedOut Whether the player is knocked out.
SetActorKnockedOut Knocks an NPC actor out, or wakes it.
IsActorKnockedOut Whether the NPC actor is knocked out.

Discovery - the map and the places a player found

Section titled “Discovery - the map and the places a player found”

What a player discovered is what the game’s own map and journal remember about them: the places they found - the named locations (villages, towns, camps), the points of interest and the kinds of them - the books they read and how far they studied each, the map pin and legend switches they set, and the parts of the world map they uncovered (the fog of war, on a server that keeps it). By default a server keeps none of it: nothing they find outlives the visit. A game mode that wants a character to keep what it found turns tracking on, saves what the server records, and puts it back at the next login - the same way it keeps the character’s progression.

Kinds. "places", "reading", "ui" (the map pin and the legend) and "fog" (the uncovered map) - the constants DISCOVERY_PLACES, DISCOVERY_READING, DISCOVERY_UI and DISCOVERY_FOG are the same words. Wherever a set of kinds is taken it is true (every kind), a name, or a list of names; nil, false and {} are none, except where a function says otherwise (ForgetPlayerDiscovery, SetPlayerDiscoveryTracking). The places, the pin and the fog are kept per level; the reading is global (the game keeps the books once for the whole game, so its record is the same whatever the level).

The fog. With [ui] map_fog = true in the server’s settings the world map stays clouded where a player has not been, and the clouds lift as they walk. Tracking "fog" keeps what each character uncovered, so a returning player sees the parts of the map they explored; without map_fog every player’s map is revealed whole at each spawn, and the fog’s record is simply the whole map. RevealPlayerMap uncovers the whole map, and a saving mode then saves the whole map: call it only for a character that should keep it.

Tracking is off unless the mode turns it on. SetDiscoveryTracking names the kinds the players’ games report, usually in OnGameModeInit; SetPlayerDiscoveryTracking gives one player a set of their own. With nothing tracked no message is sent and no player’s game does any work: a mode that never calls these functions sees no change at all.

The record. The server keeps, for each player, what their game reports: a block per kind, sent when it changed and again after every spawn. The record is a union: it only grows. Every report is added to what the record holds - a place found, a book studied further - and nothing a report leaves out is taken away, so a restore that went wrong halfway, a report that arrives late, or a player’s game that has forgotten something can never shrink what the mode saves. (The map pin and the legend are the player’s own marks, not discoveries: the newest report replaces them, and a restore of them replaces what the game shows.) GetPlayerDiscovery reads the record. Each block is data the server keeps for you: a base64 text of a fixed, versioned format (format says which), up to about 64,000 characters, ready to save as it is in a text column and to hand back to SetPlayerDiscovery later; saved records stay readable across server updates. Treat the text as opaque: do not edit it.

Saving a character. Save the record when OnPlayerDiscoveryChange says it grew (at most once a kind every few seconds, so a long walk is a few calls), on a timer and in OnPlayerDisconnect; put it back with SetPlayerDiscovery when the player logs in. What a player found in their last seconds is in the record you read in OnPlayerDisconnect: a change still waiting for its window is told to OnPlayerDiscoveryChange just before the goodbye (and when the mode is reloaded or the server stops), so a mode that saves what it was told misses nothing; a mode can also save every kept kind at the goodbye. Write only the blocks that differ from what you saved last. Never write before the restore has gone out: until then the record holds only what the player found since they joined, and saving that over the stored character loses the rest. For a character with nothing saved yet, make the first save once IsPlayerDiscoveryKnown says the game has reported, so the first rows hold what the game knows rather than an empty record.

Restoring. SetPlayerDiscovery takes the record at once - GetPlayerDiscovery right afterwards answers it - and sends it to the player’s game, which adds it to what it already holds, exactly and silently, without the notices of a discovery in play. A restore made before the player is in the world waits for their spawn. The game answers every restore, applied or given up (OnPlayerDiscoveryRestore). A restore never takes anything the player found since they joined: pass replace only for a mode that switches one game between characters, and call ForgetPlayerDiscovery (or SetPlayerDiscovery with replace) at each switch.

A labelled map. A revealed map shows the land and no names. RevealPlayerMap with "places" (or "all") shows one player the whole map and also finds the places of the level, so the revealed map is labelled - provided the player’s game can do it. No player’s game does it in this version: the map is revealed without the names, and the places the player found - or a restore put back - show theirs as ever.

Several characters in one game. A mode that lets a player switch characters without leaving calls ForgetPlayerDiscovery at the switch - every kind, the places too - and then SetPlayerDiscovery with the next character’s record; or SetPlayerDiscovery with replace, which forgets the kinds it carries first. The second character’s map then shows only what it found.

Limits. The game’s own story quests, if the mode runs them (SetStoryQuests), can undo places the player found: keep them off in a mode that saves places. A player whose game cannot read a kind - an unknown version of the game, or an older KCD:MP - reports nothing of it and applies nothing of it; capable in the record says which kinds their game can do.

Callback When
OnPlayerDiscoveryChange What the player discovered grew - the moment to save it.
OnPlayerDiscoveryRestore The player’s game answered a restore - it applied it, or gave up.
Function What it does
SetDiscoveryTracking Chooses which kinds of discovery the players’ games report to the server.
GetDiscoveryTracking The kinds of discovery the server asks every player’s game for.
SetPlayerDiscoveryTracking Gives one player a set of tracked kinds of their own, over the server-wide one.
GetPlayerDiscoveryTracking The kinds the player’s game is told to report.
GetPlayerDiscovery The record of what the player discovered, ready to save.
SetPlayerDiscovery Puts a saved record back - the player’s game takes what it was not holding.
ForgetPlayerDiscovery The player has found nothing again - the record emptied and the game told to forget.
IsPlayerDiscoveryKnown Whether the record of a kind is the player’s game’s own.

The pieces of a player’s screen that KCD:MP draws - the chat, the scoreboard, the name plates over heads, the party frames, the notices, the emote wheel and the rest - are components, and a mode decides how each one looks for each player. There are two things to change about a component, for one player or for everyone:

  • who draws it - the drawer: "native" is KCD:MP’s own piece and the default; "hidden" draws nothing and its keys stop working (a hidden scoreboard still takes Tab), while what the piece does behind the scenes carries on (a hidden chat still collects its lines, a hidden scoreboard still knows who is on the server). Only chat, scoreboard, notices, party, emotes, hudtext, sleep, nameplates and compass can be hidden;
  • how it is laid out - the options of a component: the chat’s corner, width and number of lines, whether the scoreboard is held or toggled with Tab, where the party frames sit, the colour of the name plates, and a few more.

The components are chat, scoreboard, notices, party, death, dialog, emotes, loading, hudtext, shop, voice, sleep, nameplates, compass and hud. Change the interface lists what each one is, what hidden does to it, and every option with its range and default.

What a player sees is their own setting if the mode made one for them, else the setting made for everyone, else the default. The setters answer true, or false and the reason in words a person can read; a call with any bad word in it changes nothing at all, not even the good keys next to it. Several calls in one tick reach the player as one change, and a call that changes nothing sends nothing.

A reload of the mode puts every component back to native with the default options, so a mode sets its interface where it is made again: for everyone in OnGameModeInit (the settings then hold for whoever joins later), for one player in OnPlayerConnect. A player who leaves and comes back starts again from the settings made for everyone.

Function What it does
SetPlayerInterface Says who draws a component of one player’s screen - "native" or "hidden".
GetPlayerInterface Who draws a component of a player’s screen - what was asked for and what draws it.
SetInterfaceForAll SetPlayerInterface for everyone - and for whoever joins later.
SetPlayerInterfaceOptions How a component is laid out for one player - the chat’s corner and lines, the scoreboard’s mode, and so on.
SetInterfaceOptionsForAll SetPlayerInterfaceOptions for everyone - and for whoever joins later.
SetScoreboardColumns Adds columns to the scoreboard - kills, score, a rank - whose cells are the players’ state values.

The game’s own pickpocketing between players: the “Rob” prompt on a body (hold E), the charge and the tile game of single player, played on the thief’s screen - over what the server offers from the victim’s pockets, and what the game takes is moved by the server. The mode decides whether it exists at all, who may rob and be robbed, and what a caught thief or a robbed player gets: the consequences are the mode’s (OnPlayerPickpocketEnd).

It is off until a mode switches it on (SetPickpocketing); then every player’s body shows the prompt to every other player, until the mode says otherwise for a player (SetPlayerPickpocketable takes a player’s pockets out of it, SetPlayerCanPickpocket takes the right to rob from a player). An NPC actor shows the prompt when the mode gave it pockets (SetActorPocket).

How a robbery goes. The thief’s game asks. The server checks that the thief and the victim stand in the world, in view of one another, in one virtual world, on foot, within the rules’ range (and behind the victim, if the rules say so, and with no wall or closed door between them when [validation] line_of_sight is on and the server has the level’s collision geometry), that neither is busy - riding, in a cart, flying, in a dice match, at a shop, in a dialogue, searching a body, knocked out, carried or carrying, in a fall or a pull-down, in a fight - that nobody else is robbing the same victim, that the same thief did not rob the same victim in the last cooldown seconds, and finally asks the mode (OnPlayerPickpocketStart). A refusal reaches the asker alone, with a line in his chat (each line at most once in fifteen seconds).

Then the server makes the offer: what the victim carries - not what they wear or hold in a hand - up to max_items stacks (never more than 11 - the game’s wheel has no more places), shuffled, at most max_stack of one class; quick-slot containers, item aliases, NPC tools and key rings are never in a pocket, and the rules’ deny keeps out anything else by class, name or catalogue category. With money the victim’s purse joins the same pool as one entry (a share of it, up to a cap), so max_items counts it too and a full bag can leave it off the wheel. The thief’s game plays the minigame over exactly that; the game’s own roll can catch him in the charge, and the tile game can be failed. When it ends it says which of the offered stacks it took. The server refuses a claim that names a stack the offer did not hold, one twice, more than was offered, one that comes sooner than min_seconds after the grant, or one after ninety seconds - nothing moves then. Otherwise each stack goes to the mode (OnPlayerPickpocket: false leaves it), is cut to what the victim still holds, and moves: the victim’s game gives it up the way a searched body’s does, the thief gets it from the server - so the inventory audit explains both, and neither is a violation. A thief the game caught takes nothing. OnPlayerPickpocketEnd hears every ending.

A session ends when the thief’s game says so (it took something, nothing, was caught, or broke off), and by the server’s own word when either player dies, leaves, respawns, is teleported (SetPlayerPos), mounted, put in a cart, flies, is knocked out or carried, goes to another virtual world, walks more than a metre past the range, when a fight begins with either, when ninety seconds pass without a word from the thief’s game, or when the mode says so (CancelPickpocket, SetPickpocketing off, SetPlayerPickpocketable or SetPlayerCanPickpocket taking the right away, SetActorPocket taking the pockets away). The thief’s game then ends its minigame at once; the mode hears "cancelled" with the reason. An NPC actor that dies or is removed ends the session before its body goes. A woman’s character robs, and is robbed, as a man’s does. A player’s game that cannot play the minigame (an older or unsupported build) cannot rob: the server grants it nothing.

The rules are the mode’s, not the server’s: there is nothing about pickpocketing in server.toml. The shipped modes keep them in a table at the top of their file, for the owner to change.

Reserved state keys. The prompt is shown through state keys the server writes: the world state pocket ("1" while SetPickpocketing is on), a player’s pocket ("0" while SetPlayerPickpocketable took them out) and steal ("0" while SetPlayerCanPickpocket took the right away), and an NPC actor’s pocket ("1" while it has pockets). Do not set pocket or steal with SetGlobalState, SetPlayerState or SetEntityState yourself. A mode reload (ReloadGameMode) takes all of it down with the old mode: pickpocketing is off with the default rules, everyone robbable and able to rob, the actors’ pockets gone and a session that runs ended without a word to the mode; the new mode’s OnGameModeInit sets what it wants.

Callback When
OnPlayerPickpocketStart A player reaches for another’s pockets with the game’s “Rob” - return false to refuse.
OnPlayerPickpocket The thief’s game took a stack - return false to leave it.
OnPlayerPickpocketEnd A pickpocket session is over - what came of it.
Function What it does
SetPickpocketing Switches pickpocketing between players on or off, with its rules.
GetPickpocketing Whether pickpocketing is on, and its rules.
SetPlayerPickpocketable Takes a player’s pockets out of pickpocketing, or puts them back.
IsPlayerPickpocketable Whether the player’s pockets may be picked.
SetPlayerCanPickpocket Takes the right to rob from a player, or gives it back.
CanPlayerPickpocket Whether the player may rob others.
SetActorPocket Gives an NPC actor pockets a thief may take from.
GetActorPocket What an NPC actor’s pockets hold now.
CancelPickpocket Ends the pickpocket session a player is in - nothing is taken.
GetPickpocketTarget Whom a player robs now.

A server can give its players a web interface: pages of HTML, CSS and JavaScript - a menu, a shop window, a login screen, a new chat - that the players’ games draw over the game. The pages are the files of the mode’s interface folder, and its ui.toml names each frame (one page, drawn in a layer of its own) and says what the frame may do. A player’s game downloads the folder when they join. The server configuration says where the folder is and how big it may be; the pages’ own side is documented with the web interface SDK, and the guide Make a web interface puts a first frame on the screen from start to finish.

A mode drives its frames from here:

The server keeps no picture of a player’s screen. A call answers true when the request was handed to the player’s game, not when it was done: the frame’s focus setting, the player’s own switches and a page that failed can still turn it down afterwards. A call that cannot even be handed over answers false and the reason in words, the same few everywhere: "no such player", "no web interface" (this server has none), "the player has no web layer" (their game runs none, or it failed) and "no such frame" (the name is not a frame of the interface in force). What comes back from a player’s game - its state, a page’s report, a page’s event - is that game’s word: check it as you would any other input from a player.

A reload of the mode leaves the players’ frames where they are: the pages stay on screen with their state and the new mode hears OnPlayerWebStatus and, for each frame that is ready, OnPlayerWebReady again.

Callback When
OnPlayerWebStatus A player’s web layer changed state - or the state it had when the player joined.
OnPlayerWebReady A frame of a player’s web interface has loaded its page and is listening.
OnPlayerWebError A page of a player’s web interface raised a script error.
Function What it does
IsPlayerWebReady Whether a player’s game runs the web layer and it is ready.
IsPlayerWebFrameReady Whether a frame of a player’s web interface has loaded its page and is listening.
ShowPlayerWebFrame Shows a frame of the web interface on a player’s screen.
HidePlayerWebFrame Takes a frame of the web interface off a player’s screen without closing it.
DestroyPlayerWebFrame Closes a frame of the web interface on a player’s screen and frees the memory its page used.
SetPlayerWebFocus Gives a frame the keyboard and the mouse cursor, or takes them back.
SetPlayerCursor Brings the player’s cursor up in the world, or takes it away.
SendPlayerWebMessage Sends one page a message - a table, a text, a number or a boolean.
JsonEncode A value as JSON text.
JsonDecode JSON text as a value.
RegisterUiFallback Gives a screen the mode has twice - a web frame and a client script’s own - one name to be sent events by.
SetPlayerLoadingHandover Gives a player’s loading page data of the mode’s while the level loads - a table, a text, a number or a boolean.
ClosePlayerLoadingScreen Ends a player’s loading screen - one that the interface asked to keep up until the mode says so.

A web surface is a page of the mode’s web interface drawn in the world - a notice board, a shop sign, a screen on a wall - instead of over the game. Its page is declared in the interface’s ui.toml under [surfaces.<name>] (its pixels, how many pictures a second it paints, how near a player must be); the mode places surfaces that show it with CreateWebSurface. Every player near a surface sees the page on a board, lit and shadowed by the world like the game’s own signs - and each player’s game draws its own copy of the page: what one copy shows is what the mode sent that player.

[surfaces.board]
page = "board/index.html"
width = 768 # pixels, 64-1024 (512 unless it says)
height = 512
fps = 2 # pictures a second at most, 1-30 (10)
range = 30 # metres from the player, 5-100 (30)
events_out = ["board.read"] # the events its page may send ("board.*" unless it says)

Nobody clicks or types on a surface page. A player whose game runs no web layer sees no surfaces at all. The page side is documented with the web interface SDK (“Pages on surfaces in the world”), and the server folder’s sdk/web/examples/notice-board/ is a working example.

Callback When
OnPlayerWebSurfaceReady A player’s copy of a surface’s page has loaded and is listening.
OnPlayerWebSurfaceEvent A player’s copy of a surface’s page sent the mode an event.
OnPlayerUseWebSurface A player pressed the use key on a surface’s prompt.
Function What it does
CreateWebSurface Places a web surface - a page of the web interface drawn on a board in the world.
SetWebSurfacePos Moves and turns a web surface.
SetWebSurfaceSize Makes a web surface’s board bigger or smaller.
SetWebSurfaceGlow How much a web surface shines by itself.
SetWebSurfaceTransparent Whether the world shows through a web surface’s see-through parts.
GetWebSurfaces Every web surface in the world.
GetWebSurfacePage Which surface page of the interface a web surface shows.
SendWebSurfaceMessage Sends every copy of a surface’s page a message - a table, a text, a number or a boolean.
SendPlayerWebSurfaceMessage Sends one player’s copy of a surface’s page a message.

A mode that wants a key of its own - “open the map”, “whistle for the horse”, “raise a hand” - does not know which keys a player has free. It declares a key binding instead: a name, a line saying what it is for and the key it starts on. Every player’s game is told the list when they join (and again when it changes), and the mode hears the presses:

  • The server - OnPlayerKeyBinding, with the player, the binding’s name and whether the key went down or came up.
  • The player’s game - a client script’s OnKeyBinding, and the pages of the web interface through KcdMp.onKeyBinding, each with the same name and the same press.

A key that is bound belongs to the mode: the game does not see it while it is bound. Some keys can never be bound - F9, F12, Esc, Tab, Enter, the Windows keys, G and T (the emote wheel), the keys that walk, jump, crouch and sprint, the player’s push-to-talk key, the key that switches to third person (F3 unless the player chose another), the voice level key (left Ctrl unless the player chose another) and the two keys that scroll the chat - and a binding is silent while the chat box or the F9 window is open, one of the game’s own menus is up, or a page or a client script holds the keyboard.

A player can bind another key for any of the mode’s bindings - the game keeps the choice for each server. A default key that is one of the keys above leaves the binding without a key until the player picks one. There is no menu for picking yet: a player uses the console command KcdMp_bind in the F9 window, when the server has opened it, so a mode chooses its defaults as the keys most players will use.

A press is heard at most 20 times a second from one player; more is dropped and never counts against them. A release is never dropped: the mode hears one for every press it heard, so it never holds a key down for good. The server does not tell a mode which keys a player holds now: a mode that needs that keeps its own record.

Callback When
OnPlayerKeyBinding A player pressed or let go of a key the mode declared.
Function What it does
RegisterKeyBinding Declares a key the mode wants - a name, what it is for and the key it starts on.

The game lists the keys that do something right now in the corner at the bottom right - “Inventory I”, “Get up W” while seated, “Pick up E” in front of an item. A mode adds lines of its own to that list, for one player at a time, drawn the game’s way: the key’s cap, the text beside it, the hold mark for a key that is held, a second key for a combination, a faint line for something not possible right now. The game’s own lines stay as they are; the mode’s are added to them each time the game changes its list, so they stay up until the mode takes them away.

A line is only a hint: the key does whatever the game or the mode does with it. Pair a line with a key binding to hear the key - and name the binding in the line’s options, so the line shows the key the player actually uses for it, even after they bind another one.

Each line has an id of the mode’s choosing; adding a line with an id that is already there changes it in place. The lines last through deaths and respawns until the mode removes them or the player leaves; a reload of the mode takes them all away.

Function What it does
AddPlayerActionHint Adds a line of the mode’s own to a player’s key hints in the corner, or changes it.
RemovePlayerActionHint Takes one of the mode’s lines away from a player’s key hints.
ClearPlayerActionHints Takes every line of the mode’s away from a player’s key hints.
GetPlayerActionHints The mode’s lines in a player’s key hints.

A mode’s quests appear in the game’s own journal: in its Main, Side and Task lists, with the description and a line for each objective in its diary. The HUD announces them the game’s way (“Side quest started”, an objective done, “Quest completed”), and an objective’s marker shows as a lettered quest marker on the compass and the world map. Every player sees their own journal: the mode defines a quest once and then moves each player’s progress on its own.

A definition is a table: a key (the mode’s own name for the quest, below), a name, a description (the diary’s text), a kind ("main", "side" or "task") and up to 16 objectives. An objective is its text alone, or a table with the text, the diary’s line for each state (log while it is active, updatedLog, doneLog, failedLog), an optional marker and active = true for the ones a player starts with (none marked: the first). A marker is a point {x =, y =, z =} (metres), a world entity {entity = id} or a player’s body {player = pid}; a marker on an entity or a player follows them as they move. A marker shows while its objective is active or updated and the player tracks the quest in the journal.

A player’s progress is a quest state - "active", "done" or "failed" - and a state for each objective: "hidden" (not in the journal yet), "active", "updated", "done" or "failed". Objectives are numbered from 1 in the order of the definition. Every function that changes a player’s progress takes silent last: true changes the journal without the HUD’s banner.

A player holds at most 8 main, 32 side and 16 task quests at once; a finished quest counts until it is removed. A player whose game cannot show quests (an older version of the game client) still has them on the server; CanPlayerShowQuests tells.

Saving a player’s quests. The server forgets a player’s quests when they leave, and a quest’s id only lasts until the server restarts (the ids follow the order the mode makes its quests in). So give every quest a mode keeps a key - a name of your own such as "abbots_errand": 1-64 letters, digits and _ . : -, one quest’s at a time. Save each quest of GetPlayerQuests by its key (with its state and objectives) when the player leaves, and give them back at the next login with SetPlayerQuest, which is silent unless told otherwise. Every function here takes a quest’s id or its key, and GetQuestByKey turns a key into this run’s id.

Function What it does
CreateQuest Defines a quest - its name, description, kind and objectives.
UpdateQuest Gives a quest new texts, a new kind or other objectives.
DestroyQuest Removes a quest from every journal and forgets it.
GetQuests The ids of every quest the mode made.
GetQuestByKey The id of the quest with a key.
GetQuestInfo A quest’s definition.
StartPlayerQuest Puts a quest into a player’s journal.
SetPlayerQuestObjective Sets one objective’s state for a player.
CompletePlayerQuest Finishes a quest for a player.
FailPlayerQuest Fails a quest for a player.
RemovePlayerQuest Takes a quest out of a player’s journal.
SetPlayerQuest Sets a player’s whole record of a quest at once - a restore at a login.
SetPlayerQuestMarker A player’s own marker for one objective.
GetPlayerQuest A quest as a player has it.
GetPlayerQuests Every quest a player holds, in the order they got them.
CanPlayerShowQuests Whether a player’s game shows quests in its journal.

Every text the game shows from its own tables has a key: a place on the world map (location_opatovice is “Opatowitz”), the fast travel’s question (ui_fasttravel_kut_opatovice_question), a Codex entry’s title (ui_codex_name_opatovice) and its page (ui_codex_cont_opatovice), the map legend’s lines, an item’s name, a quest’s line. A mode gives a key its own text and every player sees that text wherever the game shows the key, while they are on the server - nobody installs anything, and leaving the server gives the game its own texts back.

A text is for every language or for one - a code ("en", "de", "cs", "ru", "zh-cn", "zh-tw" …) or the game’s own name for it ("english", "german", "chineses"). A player sees their own text first (SetPlayerTextOverride), then the one for their game’s language (GetPlayerLanguage), then the one for every language, then the game’s own.

A whole file goes in at once with LoadTextOverrides: a translation’s own table - the game’s text_ui_*.xml format, so the rows of a localisation mod can be used as they are - or a small JSON file of key to text. Changes reach the players at once; a screen that is open shows them the next time it opens (the world map names only the places the player has discovered, as the game always does). The texts are the mode’s: a reload clears them, so set them in OnGameModeInit.

The keys are the game’s: the world map’s place names, its legend and the fast travel are listed in the map texts and each Codex entry’s two keys in the Codex entries. A text may use the game’s own markup, as its texts do (<h> for a highlighted word, <paragraph> in a Codex page). A text that starts with @ names another key of the game’s.

Function What it does
SetTextOverride Shows the mode’s own text for one of the game’s texts, for every language or one.
GetTextOverride The mode’s text for a key and a language, if it gave one.
ClearTextOverrides Takes away every text the mode gave, or every text of one language.
LoadTextOverrides Reads a file of texts - the game’s own table format or a JSON object - for every language or one.
SetPlayerTextOverride One player’s own text for a key - theirs alone, over the server’s.
GetPlayerTextOverride The player’s own text for a key, if the mode gave one.
GetPlayerLanguage The language the player’s game shows its texts in.

The game’s Codex - its book of people, places, crafts and history - shows the entries a character has unlocked. Each entry is one of the game’s perks: the Codex entries lists all of them with the perk’s GUID and name, the page it is on, and the keys of its title and its page.

A mode decides which entries each player has: SetPlayerCodexEntry unlocks one (with the game’s “new Codex entry” notice, or silently) or locks it again - a reveal in the middle of a roleplay scene. An unlocked entry is part of the player’s progress: GetPlayerProgress and GetPlayerPerks list it with their other perks, so a mode that saves those saves the Codex too.

A mode also decides what the game unlocks by itself: the game gives every character sixteen entries at the start and unlocks more as places are discovered or the story moves. SetCodexEntryHidden stops that for an entry - a player who has it loses it, unless the mode gave it to them.

Your own words in an entry: its title and its page are texts of the game, worded with SetTextOverride - give an entry you do not need a title and a page of your own and unlock it when the story calls for it.

Function What it does
SetPlayerCodexEntry Unlocks a Codex entry for a player, or locks it again.
HasPlayerCodexEntry Whether a player has a Codex entry unlocked.
SetCodexEntryHidden Stops the game from unlocking a Codex entry by itself - or lets it again.
IsCodexEntryHidden Whether the mode hides a Codex entry from the game.
GetHiddenCodexEntries Every Codex entry the mode hides from the game.

The game’s own player screens - the inventory, the character screen, the world map, the Codex and the journal - are one screen with tabs, each opened by its own key. A mode opens one of them on a player’s screen (OpenPlayerScreen), closes them (ClosePlayerScreens - the loot and trade screens with them), and refuses some to a player for a while (SetPlayerScreenBlocked): no inventory for a player in shackles, no map in a blindfold. A refused screen does not open by the player’s key or its tab, and closes when it is open.

OnPlayerScreenChange says which of them a player opened, switched to or closed. The screens are named "inventory", "character", "map", "codex" and "journal"; "other" is another of the game’s screens of that kind (crafting, a horse’s saddlebags). The refusals last the player’s visit and a reload clears them.

Callback When
OnPlayerScreenChange A player opened one of the game’s player screens, switched to another or closed them.
Function What it does
OpenPlayerScreen Opens one of the game’s player screens on a player’s screen.
ClosePlayerScreens Closes the game’s player screens on a player’s screen - and the loot and trade screens.
SetPlayerScreenBlocked Refuses one of the game’s player screens to a player - or allows it again.
IsPlayerScreenBlocked Whether a screen is refused to a player.
GetPlayerScreen Which of the game’s player screens a player has open.

A player holds the use key on a bed and their character lies down with the game’s own animation. By default the game then shows its circular sleep wheel over a black screen: the player picks the hours, the clock stays the server’s, and the character gets the Rest those hours would give.

A mode with its own sleep - a page with a timer, Rest coming back in real time - leaves the wheel out for a player (SetPlayerSleepWheel with shown false): the bed lays them down with the game’s animation and they stay lying, the world and the HUD in view, until the mode gets them up (EndPlayerSleep, the game’s own get-up animation) or - unless the mode says otherwise - they press their forward key (W). No Rest is given meanwhile: the mode gives it with SetPlayerEnergy.

OnPlayerSleep says when a player lay down in a bed and when they got up, wheel or not; IsPlayerSleeping reads it. The rule lasts the player’s visit and a reload gives everyone the wheel back. A player whose game cannot (an unknown game version) keeps the wheel.

Callback When
OnPlayerSleep A player lay down in a bed, or got up again.
Function What it does
SetPlayerSleepWheel Leaves the game’s sleep wheel out for a player - or gives it back.
EndPlayerSleep Gets a player lying in a bed up, with the game’s own get-up animation.
IsPlayerSleeping Whether a player is lying in a bed.