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 |
Server and timers
Section titled “Server and timers”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. |
Players
Section titled “Players”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. |
Chat and commands
Section titled “Chat and commands”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 -
SendChatMessageandSendChatMessageToAllsend a line made of pieces that differ in colour, weight and slant (spans), on a channel of the mode’s choice;ClearPlayerChatempties a player’s chat. -
Channels -
RegisterChatChanneladds 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.UnregisterChatChanneltakes one away andRefreshChatChannelstells the players’ chats to look again after a rule of the mode changed. -
Commands -
RegisterCommandgives 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.AddChatSuggestionandRemoveChatSuggestiondo the same for commands the mode still answers inOnPlayerCommandText.UnregisterCommandtakes one away. -
Where it sits and how big it is - the chat is a component of the interface:
SetPlayerInterfaceOptions(one player) andSetInterfaceOptionsForAll(everyone) move it to any corner or edge (anchor,margin_x,margin_y), size it (width,linesfrom 4 to 20,font_scale) and set its backing;SetPlayerInterfacehides 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 everyoneSetInterfaceOptionsForAll("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). |
Dirt and blood
Section titled “Dirt and blood”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. |
Vitals
Section titled “Vitals”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. |
Combat
Section titled “Combat”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. |
Recipes
Section titled “Recipes”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. |
Stats, skills, XP and perks
Section titled “Stats, skills, XP and perks”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. |
Buffs and the drink
Section titled “Buffs and the drink”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. |
Items and inventory
Section titled “Items and inventory”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. |
GameText and HUD
Section titled “GameText and HUD”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. |
Compass markers
Section titled “Compass markers”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. |
Effects and sounds
Section titled “Effects and sounds”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. |
Map icons
Section titled “Map icons”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. |
Script events
Section titled “Script events”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. |
State bags
Section titled “State bags”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. |
Storage and persistence
Section titled “Storage and persistence”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. |
The game mode’s database
Section titled “The game mode’s database”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. |
World entities
Section titled “World entities”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. |
Horses
Section titled “Horses”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
Section titled “Siege engines”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. |
Voice chat
Section titled “Voice chat”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. |
NPC actors
Section titled “NPC actors”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,SetActorInvulnerableandDestroyEntitywork on them as on an actor. - Hunting them: a player’s blow or arrow hurts one (
OnActorDamagemay 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,SetActorPocketand the like answerfalse). It bleeds but is never injured:OnActorInjurynever runs for an animal andGetActorInjuriesstays empty. - Animals that attack and flee: left alone an animal does nothing by itself.
SetAnimalHostilesets 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 andOnActorAttack);SetAnimalFleeruns it from a player.SetAnimalBehaviorgives 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.SetAnimalAttacktunes the bite,GetAnimalStatesays what it is doing. - What a kill is worth: a dead animal gives nothing by itself.
OnActorDeathruns for it with the player who killed it (-1when 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), andDestroyEntitythe 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. |
Actor life
Section titled “Actor life”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:
MountActorputs 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;MoveActorthen rides - the speed picks the gait (about1.8a walk,4a trot,7a canter,11a gallop) and the horse walks around walls on the navigation mesh like a walking actor;DismountActorgets 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:
PlayActorBarksays one line of one of the game’s barks ("greeting","farewell","self_talk","work_sigh","market_call","pray","pain"…),PlayActorVoiceone line by its id,PlayActorConversationa 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 (SetActorVoicegives it another), else in a voice of its gender. The lines: the voice lines. - Seats, beds and work spots:
GetSmartObjectslists 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 - andSetActorUsesends an actor to one: it walks there, sits down (kneels, leans, starts work) with the game’s own animation, stays untilStopActorUseor aMoveActor, and gets up before it walks away.SetActorUseAtdoes an activity anywhere. The activities: the activities. - Pairs:
PlayActorPairAnimstands 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. |
Doors and containers
Section titled “Doors and containers”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. |
Herbs and mushrooms
Section titled “Herbs and mushrooms”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). |
Sound files
Section titled “Sound files”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,.mp3and.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).
PreloadSoundsends 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_cdnthe 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
rangemetres 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 inOnEntitySoundEnd.
| 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. |
Accounts, admins, bans and the audit
Section titled “Accounts, admins, bans and the audit”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 endend
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.") endendThe 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. |
Level layers
Section titled “Level layers”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 endendThe 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. |
The map’s areas
Section titled “The map’s areas”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
Section titled “The server’s map”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. |
Catalogues
Section titled “Catalogues”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. |
Parties
Section titled “Parties”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. |
Shops and vendors
Section titled “Shops and vendors”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. |
Dialogue
Section titled “Dialogue”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. |
Emotes
Section titled “Emotes”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. |
Looks and character creation
Section titled “Looks and character creation”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. |
Carry items
Section titled “Carry items”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. |
Carrying
Section titled “Carrying”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. |
Interface
Section titled “Interface”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). Onlychat,scoreboard,notices,party,emotes,hudtext,sleep,nameplatesandcompasscan 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. |
Pickpocketing
Section titled “Pickpocketing”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. |
Web interface
Section titled “Web interface”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:
- Whether the player has the web layer - a player’s game may run without it (an older game, a player who switched server
interfaces off, a layer that failed to start):
IsPlayerWebReadyandOnPlayerWebStatus. - What is on their screen -
ShowPlayerWebFrame,HidePlayerWebFrame,DestroyPlayerWebFrameandSetPlayerWebFocusfor the frames,IsPlayerWebFrameReadyandOnPlayerWebReadyfor the moment a page listens, andSetPlayerCursorfor the player’s own cursor. - What passes between the mode and a page -
SendPlayerWebMessageto one frame; the events ofSendClientEventto every page whoseevents_inlets it receive the name; a page’semitServer, which arrives inOnClientEventwith the frame’s name as itssource; andJsonEncodeandJsonDecodefor the JSON on this side. - The loading screen -
SetPlayerLoadingHandovergives the interface’s loading page the mode’s data while the level loads, andClosePlayerLoadingScreenends a loading screen that the interface asked to keep up until the mode says so. - Keys - the keys a mode declares with
RegisterKeyBindingreach the pages as well asOnPlayerKeyBinding: a page’sKcdMp.onKeyBindinghears the press and the release.
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. |
Web surfaces
Section titled “Web surfaces”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 = 512fps = 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)- Placing -
CreateWebSurfaceputs one at a point, facing a way, at a size in metres, tilted, glowing, see-through and with a use prompt as its options say;SetWebSurfacePos,SetWebSurfaceSize,SetWebSurfaceGlowandSetWebSurfaceTransparentchange it,DestroyEntityremoves it,GetWebSurfacesandGetWebSurfacePagelist them. A surface is an entity ofENTITY_SURFACE: it is inGetEntitiesandSetEntityPromptgives it a prompt. - Feeding the pages - a player’s copy loads when they come near it and is closed when they go away (or when closer
surfaces take its place: a game draws the 8 nearest live).
OnPlayerWebSurfaceReadyruns each time a copy has loaded: send it what it should show withSendPlayerWebSurfaceMessage;SendWebSurfaceMessagesends every copy there is now. - Hearing them - a page’s
KcdMp.emitServerarrives inOnPlayerWebSurfaceEvent; the use key on a surface’s prompt inOnPlayerUseWebSurface(and on that player’s copy, in itsKcdMp.onSurfaceUse).
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. |
Key bindings
Section titled “Key bindings”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 throughKcdMp.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. |
Key hints
Section titled “Key hints”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. |
Quests
Section titled “Quests”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. |
The game’s texts
Section titled “The game’s texts”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 Codex
Section titled “The Codex”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 screens
Section titled “The game’s screens”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. |
Beds and sleep
Section titled “Beds and sleep”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. |
