A client script is a Lua file the server sends to every player who joins and their game runs, in a sandbox - the mode’s
own half on the screen: a marker, a sound, a bit of UI, a value read from the game. It is written the way a game mode is:
the script defines callbacks by name (OnServerEvent, OnFrame, OnPartyChange …) and calls functions
(ShowInfoText, CreateUiText, SendServerEvent …) - the server’s names without the pid, because on this side the
player is always yourself. It talks to the server’s game mode through script events and reads the mode’s state
bags; everything else it does is the game’s own Lua, as far as the sandbox lets it. The
guide says how a script reaches the player and what the game gives it.
| Guide |
|
| Getting started |
what a client script is, how the server sends it, what of the game’s Lua the sandbox gives it, limits and logging |
Named events with a string payload, both ways between the game mode and the client script: the mode’s SendClientEvent
lands in the script’s OnServerEvent; SendServerEvent goes up into the mode’s OnClientEvent. The payload is
whatever string the two halves agree on - a number, a comma list, JSON.
| Callback |
When |
OnServerEvent |
The game mode sent an event to this player’s game. |
| Function |
What it does |
SendServerEvent |
Sends an event to the game mode’s OnClientEvent. |
The game mode’s state bags as every client sees them: string keys and values the mode set with SetGlobalState,
SetPlayerState and SetEntityState. The global and the players’ bags arrive whole when the client joins and every change
arrives at once; an entity’s bag comes with the entity when it enters view and goes when it leaves. Values are strings
("3", "true"); a removed key reads nil. OnStateChange tells a script about changes.
Who this player is and where, the level, the frame hook a script draws from, and a few readings of the world. Everything
else a client script does - drawing, sounds, reading the player entity - is the game’s own Lua, described in the
guide.
| Callback |
When |
OnFrame |
Every frame - where a script draws. |
| Function |
What it does |
GetPlayerId |
This client’s own player id. |
GetPlayerName |
This client’s own player name. |
GetPlayerPos |
Where this player stands. |
GetInventory |
What the player carries, with each item’s condition. |
GetLevelName |
The name of the level the game runs. |
GetLookTarget |
What the player looks at - the point, the thing and its surface. |
SetCamera |
Puts this player’s view at a point, looking at another - the client side of the game mode’s camera. |
ResetCamera |
Gives the player their own view back. |
IsCameraSet |
Whether a camera of the script’s or the game mode’s holds the view. |
CountEntities |
How many entities of a class the level holds. |
GetEntityCensus |
The entity classes of the level with the most instances. |
SetLabelOcclusion |
Whether the labels over the other players and the NPC actors hide behind walls. |
The client adds a few commands to the game’s console. A player reaches them through the F9 window of the KCD:MP overlay -
a line typed there is a console command, and a line starting with lua runs Lua directly. The window is closed unless the
server opens it ([client] console in its configuration; a development server does, a public one has no reason to) or the
game runs offline with -KcdMp_console. A script the server sent has no console at all - the sandbox keeps
System.ExecuteCommand away from it - and talks to the server through the script events. To try a script while writing it,
put it in the mode’s client/ folder and type /reload on the server; the server’s [gamemode] watch setting does the same by
itself whenever a client file changes on disk. Two things to know about the game’s console:
it splits a line on ; and treats a=b as a variable assignment, so a text with either has to avoid them (the script events
encode their payload for exactly this reason).
| Command |
What it does |
KcdMp_hud |
Shows a toast in the game’s own HUD by hand, to see each slot. |
KcdMp_chat |
Shows or hides the chat on this client. |
KcdMp_chat_bubbles |
Whether a player’s chat line shows over their head. |
KcdMp_compass |
Whether the party’s and the game mode’s blips show on the compass. |
KcdMp_compass_span |
How many degrees the compass strip shows across, for the blips’ placing. |
KcdMp_log |
Writes a line into the KCD:MP client log. |
KcdMp_say |
Sends a chat line, as if typed. |
KcdMp_net |
The connection’s figures - snapshots decoded, bytes, the acknowledgement. |
KcdMp_bind |
Lists the keys the game mode declared and the key each is on - or puts one on a key of your own. |
KcdMp_hud_pieces |
Which pieces of the game’s HUD the server has hidden right now. |
KcdMp_lipsync |
Whether the faces of players who talk on the voice chat move with their voices. |
KcdMp_tpv |
Asks for the third-person view or the first person, the way the third-person key does. |
KcdMp_tpv_collision |
Whether the third-person camera is kept out of walls. |
The party this player is in, as the server keeps it - the members with their labels and the others’ vitals at any
distance - for a script that draws its own frames or reacts to the group. The server draws the standard frames unless the
mode hides them per player (ShowPartyFrames on the server); a script that draws its own reads GetParty and defines
OnPartyChange. The invitation box and its keys (Y / N, KcdMp_party_keys changes them) are the client’s own.
| Callback |
When |
OnPartyChange |
The party changed - membership, leader, name, labels, the frames switch, or a vitals update. |
| Function |
What it does |
GetParty |
The party as the server last sent it. |
The game’s own toasts from a client script: the info line under the compass, the short notification at the top, a game-log
line, the quest-style objective banner and the tutorial box - the same slots the server’s
ShowInfoText family reaches from the game mode, here without a round trip
and without the pid. They show nothing while the HUD is down (a level load, the main menu).
A script composes into the game’s own HUD: empty clips to hang things under, lines of text in the game’s typeface and
filled rectangles, in a space 1080 rows high whose width follows the screen’s shape (GetScreenSize says it; a 16:9
screen is 1920 wide) - so a panel lands in the same place at every resolution. Every element has a name of your own
(a word of letters, digits and _); a name used again replaces the old element, a parent’s removal takes its children with it,
a reload of the scripts and the end of the session take everything down. The elements survive a level change by themselves:
they are records the game redraws whenever its HUD comes back. Colors are 0xRRGGBB here, with the alpha apart as
0 .. 100 (SetUiAlpha, the rectangle’s own argument): the game’s Lua keeps its numbers as 32-bit floats, and a
server-style 0xRRGGBBAA loses its last byte on the way. For the game’s own toasts see ShowInfoText and its family.
| Callback |
When |
OnKey |
A key was pressed or released. |
OnTextInput |
A character was typed while the script has the keyboard. |
OnCursorChange |
The player’s cursor came up or went away. |
OnCursorClick |
A mouse button was pressed while the player’s cursor is up. |
OnMouseButton |
A mouse button went down or came up while the player’s cursor is up. |
OnMouseMove |
The player’s cursor moved. |
OnMouseWheel |
The mouse wheel turned while the player’s cursor is up. |
OnMouseLook |
The mouse moved while the cursor is down - the moves the game turns the view with. |
OnKeyBinding |
A key the game mode declared was pressed or released. |
A look is a table {body = the skin, head = the face, hair = the hair and its color, beard = the beard}, each part named as
the game names it (m_body_tan_02, m_head_004, m_hair_005_blonde, m_beard_03); a part left out is the one the body’s
soul gives it. gender = "female" makes it a woman’s body, with a woman’s parts (f_head_013, f_hair_004_blonde,
f_body_pale_01; no beard). The server owns the look everyone sees - the mode’s SetPlayerLook; a script can only
show a look on this screen and ask for it:
ShowLookPreview puts a body in front of the player, dressed as they are, wearing the look - a character creator’s or a
barber’s mirror that nobody else sees; call it again with every change the player makes, HideLookPreview when done;
RequestLookChange asks the server for the look; the mode’s OnPlayerLookChange decides, and the look comes back
through OnLookChange when the mode took it;
GetPlayerLook is the player’s look as the server last said.
The parts to offer come from the mode - its GetLookParts lists the game’s, and a script event carries the mode’s choice
to its client half. SetKeyboardCapture gives a menu the keyboard. The
character creator guide builds a whole screen; the shipped BasicRP mode has one.
The player’s own body loads with the level: when the mode makes the player a woman (or a man again) while they play, the
game asks them once whether to restart and join again on the new body, and remembers it for the next join to the server.
A script cannot swap the player’s own model while they play: the game refuses the change (a call of SetActorModel or
LoadCharacter on the player) and notes the script’s line in the client log.
| Callback |
When |
OnLookChange |
The player’s own look changed - the server’s word. |
The server’s web interface is a set of pages - HTML, CSS and JavaScript the server sends with its client scripts -
that the game draws over the screen; each page is a frame named in the interface’s ui.toml. A client script is the
page’s neighbour inside the player’s game: it shows and hides the frames, sends them messages, hears what they ask for and
answers, and takes the keyboard and the mouse cursor for them. The other half of the conversation is the page’s
own JavaScript (KcdMp.onMessage, KcdMp.post; the web interface SDK), and the guide
Make a web interface shows the whole of it.
Every one of these exists in every player’s game: with no web layer (an older game, a player who switched server
interfaces off, a server without an interface) a function does nothing and answers false and the reason - "no web layer",
"no web interface" (the server has none) or "no such frame" - and the Is functions answer false, so a script written
for the web interface also runs without it. An answer of true means the request was handed over; the game decides
after that (a frame’s focus setting, the player’s own switches), and IsWebFocused says what came of it. Frames are the
server’s interface’s own: a script can only name frames of the interface that is in force.
| Callback |
When |
OnWebEvent |
A page of the web interface asked the script something - the value returned is the page’s answer. |
OnWebFrameReady |
A frame’s page has loaded and is listening. |
| Function |
What it does |
SendWebMessage |
Sends a frame’s page a message - a table, a text, a number or a boolean. |
ShowWebFrame |
Shows a frame of the web interface. |
HideWebFrame |
Takes a frame of the web interface off the screen without closing it. |
DestroyWebFrame |
Closes a frame of the web interface and frees the memory its page used. |
SetWebFrameZ |
Sets which frame is drawn above which. |
SetWebFocus |
Gives a frame the keyboard and the mouse cursor, or takes them back. |
SetWebFocusKeepInput |
Lets the game keep the player’s keys while a frame has the keyboard. |
IsWebFocused |
Whether a frame - or any frame - of the web interface has the keyboard or the mouse cursor. |
IsWebFrameReady |
Whether a frame’s page has loaded and is listening. |
IsWebAvailable |
Whether this game runs the web layer with the server’s interface in force. |
JsonEncode |
A value as JSON text. |
JsonDecode |
JSON text as a value. |
The game’s own player screens - the inventory, the character screen, the world map, the Codex and the journal - opened and
closed from a script: OpenScreen with "inventory", "character", "map", "codex" or "journal", CloseScreens,
and GetOpenScreen / OnScreenChange for the one open. A screen the server refuses the player stays shut. A mode that
opens and refuses the screens itself does it from the server (its OpenPlayerScreen, SetPlayerScreenBlocked).
| Callback |
When |
OnScreenChange |
One of the game’s player screens opened, the player switched to another, or they closed. |
| Function |
What it does |
OpenScreen |
Opens one of the game’s player screens. |
CloseScreens |
Closes the game’s player screens - and the loot and trade screens. |
GetOpenScreen |
Which of the game’s player screens is open. |