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 - colours, 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 |
4 callbacks, 30 functions |
| Chat and commands |
2 callbacks, 3 functions |
| Vitals, stats and skills |
17 functions |
| Combat |
5 callbacks, 5 functions |
| Buffs and the drink |
2 callbacks, 10 functions |
| Items and inventory |
2 callbacks, 4 functions |
| GameText and HUD |
16 functions |
| Effects and sounds |
3 functions |
| Script events |
1 callback, 2 functions |
| State bags |
9 functions |
| Storage and persistence |
9 functions |
| World entities |
14 functions |
| Horses |
2 callbacks, 4 functions |
| Props |
5 functions |
| Dogs |
4 functions |
| NPC actors |
5 callbacks, 15 functions |
| Zones |
2 callbacks, 11 functions |
| The world - clock, weather, terrain, the navmesh, the geometry |
20 functions |
| Doors and containers |
3 callbacks, 7 functions |
| Accounts, admins, bans and the audit |
2 callbacks, 11 functions |
| Catalogues |
10 functions |
| Parties |
7 callbacks, 23 functions |
The mode’s own lifecycle, the server’s facts, timers and the log. Everything a mode does happens on the simulation thread,
one tick at a time, thirty times a second - the callbacks run inside a tick, the timers run in the tick they fall due, and a
slow callback delays the tick for every player (Getting started).
| Callback |
When |
OnGameModeInit |
The script is loaded and the API is ready - the place to create zones, HUD texts, timers and actors. |
OnGameModeExit |
The server shuts down or the mode is about to be reloaded. |
OnTick |
Every simulation tick, with the time since the last one. |
| Function |
What it does |
SetGameModeText |
Names the mode in the server log and the server browser. |
GetServerTick |
The number of the simulation tick being processed. |
GetServerTime |
The server’s clock in milliseconds. |
GetMaxPlayers |
How many players the server holds ([server] max_players). |
GetLevel |
The name of the level the server runs. |
GetLevelName |
The level as a player reads it. |
Log |
Writes a line to the server log, prefixed [lua]. |
SetTimer |
Calls a function after a delay, once or repeatedly. |
KillTimer |
Stops a timer. |
ReloadGameMode |
Reloads this mode at the end of the tick, without restarting the server. |
A player is a pid from 0 to GetMaxPlayers() - 1, given at the handshake and reused after a disconnect: keep the
pid while a player is on, and check IsPlayerConnected before trusting a pid kept across ticks. Readers return nil for a
pid that is not connected; setters return false. Positions are metres, yaw is degrees (0 = facing +Y, counter-clockwise);
a mounted player’s position and velocity are the horse’s.
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. /register, /login, /fight and /peace are the server’s and are answered
before the mode sees them. The mode’s own lines go out with SendClientMessage and SendClientMessageToAll.
| 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. |
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. Stats and skills are the game’s own character levels, raised by the server and kept on the record.
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, 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. |
OnFightStart |
Two players are in a fight from now on. |
OnFightEnd |
A fight between two players is over. |
| Function |
What it does |
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. |
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 consumed an item - the server is about to apply its effect; return false to cancel. |
OnPlayerDrunk |
The player got drunk, or sobered up. |
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). Items the server hands out - the spawn outfit,
GivePlayerItem, a pickup taken, a take from a chest - are the ones the inventory audit can explain.
| Callback |
When |
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. |
| Function |
What it does |
GetPlayerEquipment |
What the player’s client reports as equipped - clothing, armour, the weapons in the slots. |
GetPlayerInventory |
The player’s whole inventory as their client last reported it. |
GivePlayerItem |
Puts items in the player’s inventory - or takes them out. |
CreatePickup |
Puts an item on the ground for everyone to see and anyone to take. |
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.
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. |
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, KcdMp.send_event 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.
| Callback |
When |
OnClientEvent |
A player’s client script sent an event. |
String keys and values the mode sets on the world, a player or an entity, and every client’s script reads -
KcdMp.state.global[key], KcdMp.state.player[pid][key], KcdMp.state.entity[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.
Three 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. Saved data is written to the player’s record under their name ([persistence] file,
data/players.json) and is there on their next visit, next to the visits, the play time and the last position the server keeps
by itself. Server data is one key/value store for the mode, persisted in data/server.json. What every client should read
is the state bags instead.
| 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. |
GetSavedPlayer |
What the server remembers about the player’s name between visits. |
GetSavedData |
A value the mode saved on the player’s name. |
SetSavedData |
Saves a value on the player’s name - it is there on their next visit. |
GetServerData |
A value of the server-wide store. |
SetServerData |
Saves a value in the server-wide store (data/server.json). |
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) - 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 and actors have their own.
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.
| 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. |
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.
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. 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.
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 in straight lines, 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.
[actors] in server.toml tunes how it fights. Not yet: paths around obstacles (a straight line through a wall stops at the
wall), riding.
| Callback |
When |
OnActorArrive |
An actor 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. |
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.
| 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. |
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 override. |
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. |
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. |
The level’s own doors and stashes 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 door’s state of record is written by whoever uses it; a
container’s contents are the server’s - the first opener’s own loot seeds the record, one player holds a container at a time
(“Someone is rummaging in it.” for the next), and what they leave in it is what the next opener finds. The key of a door or a
container is the entity’s level name - AnimDoor[Door/door_village_left32_77d417c2-...], Stash7[Stash/stash_shelf_...] -
listed per level in Levels. A mode needs nothing for the sync; it may veto (OnPlayerUseDoor,
OnPlayerOpenContainer) or drive it (SetDoorState, SetContainerItems).
| Callback |
When |
OnPlayerUseDoor |
A player’s game opened, closed, locked or unlocked a door - return false to put it back. |
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. |
A name is open until a player claims it with /register <password>; from then on whoever joins under it plays as a guest -
held in a world of their own, no record, no admin flag - until /login <password>, and is kicked after [accounts] login_grace_seconds without it. Admins are the logged-in owners of the names on [accounts] admins, or players the mode
promotes for the session; the flag unlocks the server’s admin-only built-in commands and whatever the
mode gates on it. Bans are kept in data/bans.json beside the player records - a plain list an admin may edit by hand. The
inventory audit ([audit]) compares what a player holds with what the server can explain - the spawn outfit, GivePlayerItem,
pickups, takes from containers - and calls the mode before it acts on a discrepancy.
| Callback |
When |
OnPlayerLogin |
The player proved a registered name, or just registered it. |
OnPlayerAuditViolation |
The inventory audit found items the server cannot explain - return false to vouch for them. |
| Function |
What it does |
IsPlayerRegistered |
Whether the player’s name has a password on record. |
IsPlayerLoggedIn |
Whether the player proved their registered name this session. |
IsPlayerAdmin |
Whether the player is an admin. |
SetPlayerAdmin |
Makes the player an admin for the session - or takes it back. |
GetAdminNames |
The names on the server’s admin list. |
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 audit violations were acted on for the player this session. |
The server resolves the game’s things by id, name or GUID through the tables export ([combat] tables): items
(the item catalogue), souls (the souls), buffs (the buff
list) and meshes (the meshes; GetMeshPath and FindMeshes are with the props). Every function
that takes an item, a soul or a buff accepts any of the keys; these look them up, search them and turn one key into another. The
id is the row number of the name-sorted export - stable for one export of one game build, so keep the name or the GUID in
anything durable. Without the export only GUIDs pass, unchecked.
| Function |
What it does |
GetItemClass |
The class GUID an item key stands for. |
GetItemName |
The game’s name of an item key. |
GetItemInfo |
The catalogue’s entry for an item key. |
FindItems |
Items whose name, English name or category holds every word of a pattern. |
GetHorseSoul |
The soul GUID a horse key stands for - the Horse archetype only. |
GetSoulInfo |
The soul catalogue’s entry for a key, of any archetype. |
FindSouls |
Souls whose name or archetype holds every word of a pattern. |
GetBuffGuid |
The GUID a buff key stands for. |
GetBuffInfo |
The buff catalogue’s entry for a key. |
FindBuffs |
Buffs whose name, English name or class holds every word of a pattern. |
Players grouped with a leader (v38, the guide): the server keeps the group, the invitation with its
timeout and the toast on the target’s screen, the party frames every member sees (the others’ name, health, stamina, wounds,
at any distance and in any world) and the no-friendly-fire rule. The server ships no party commands: /invite,
/accept, /p and every rule around them - who may invite, a level gate, leader-only invitations - are the mode’s, written
around these callbacks and functions (the shipped freeroam mode carries the plain ones). A party is a number; ids count
up and are never reused while the server runs. A party exists with two or more members and ends when it falls to one - there
is no party of one. One party and one pending invitation per player. [party] in the server’s configuration holds the size
(5), the invitation’s timeout (30 s), the frames’ default, what the leader’s leaving does and the friendly fire.