Players
kcds.players.Player represents one connected player, and the object stays the same for the session. Values such as
health, position and buffs are what the player's game last reported. Changes you make go to their game and take effect a
moment later.
const { Events } = kcds.core; const { Player } = kcds.players; Events.on('playerReady', (player) => { console.info(`${player.nickname} (${player.id}) is at ${player.position}`); }); Events.on('playerCommand', (player, command, args) => { if (command === 'heal') { player.heal(); } if (command === 'tp' && args[0]) { const [target] = Player.find(args[0]); if (target) { player.teleport(target.position); } } });
Finding players
| Call | Returns |
|---|---|
Player.all() | everyone connected, including those still loading |
Player.getById(id) | one by network id, or null |
Player.find(text) | what a command argument names: an id, or matching nicknames |
Player.inRadius(position, radius, options?) | players with a body in the world, nearest first |
Player.nearest(position, options?) | the closest player with a body in the world |
The options are dimension, except to leave one player out, and radius for nearest.
An id is unique while the server runs and is never reused. playerIndex is the connection slot, which is reused.
Position
position, which moves them when assigned,rotation,velocityandgazeready: their body is in the worldteleport(position, label?): moves them on their next framespawn(position, rotation): used insideplayerSpawningto choose where they appear when joining
Drawing things on a body: in a client script, another player's position moves in steps as network updates arrive,
40 to 150 ms apart, while the game draws the body smoothly. For anything attached to the body, ask where the game is
drawing it:
renderPosition: where this machine is drawing the body, ornullbefore it is herejointPosition(joint): where a joint is being drawn, ornullif the body lacks it. Use'Bip01 Head','Bip01 R Hand', or the game's names,'Head'and'RightHand'
// client: a rope between a guard's hand and a prisoner's neck const { Player } = kcds.players; const hand = new Player(data.guardId).jointPosition('Bip01 R Hand'); const neck = new Player(data.prisonerId).jointPosition('Bip01 Neck'); if (hand && neck) { console.log(`rope ${hand.distance(neck).toFixed(2)} m`); }
Dimensions
Players and entities see each other only in the same dimension. Dimension 0 is the shared world everyone starts in. Use others for instances, interiors, minigames or an admin's own space.
player.setDimension(1000 + player.id); // a dimension of their own player.showOnlyTo(admin); // one other player can still see them
Most spawn calls, such as Npc.create, Prop.spawn and Vfx.spawn, also take a dimension.
Health and condition
Read: health, maxHealth, healthPercent, stamina, exhaust, hunger, bleeding, drunkenness, poisoning,
alive, knockedOut, ableToAct, injuries.
Change: setStat, addStat and fillStat with a PlayerStat name, setHealth, setHunger,
and heal(), the game's own cure.
Knock-outs: a fatal blow knocks a player out and fires playerDied, and revive() gets them up. Only knockedOut,
setHealth(0) and revive() control a knock-out. player.buffs does not list the unconsciousness and addBuff refuses
it, so a saved buff list cannot hold a player down at their next login. setKnockoutVision(percent) sets how much they see
while down, and lootable sets whether others can search them.
Looks and body
setAppearance({ gender, body, head, hair, beard })takes names from Appearances.setOutfit(preset)dresses them in one of the game's outfits.setVisible(false)hides the body, andsetDisguise(model)draws it as a prop.clean()andsoil()change dirt and blood, andgrimereads them.playAnimation(fragment, options)andstopAnimation()play and stop animations.
A woman is put on the female skeleton, on her own screen and everyone else's, so she moves, holds weapons and rests her hands as a woman. She keeps what she wore and held. The game's rule keeping women from alchemy tables, the grindstone, horses, carrying bodies and pickpocketing does not apply to players.
Removing players
kick(reason)ends their session with "You were kicked from the server: ...".disconnect(text, { quit })lets them go without the word "kicked". The main menu showstextas written, or withquit: truetheir game closes.playerDisconnectfollows, where you can save them. On the client,kcds.core.Game.quit()closes the game in the same way.ban(reason)bans them from this server by their identifiers except the address, on the list KCDS-Admin keeps. They leave with "You are banned from this server: <reason>." and are refused when they return.
For players who are not online, use Bans.add(identifiers, reason). Bans.remove(idOrIdentifier) unbans, and Bans.find and
Bans.list read the list. A script's ban never ends by itself, so for a three-day ban, store the end date and call
Bans.remove when it comes.
Restricting a player
| Member | Effect |
|---|---|
setCuffed(true) | hands behind the back; they can only walk and look, and only the upper body takes the pose |
noclipAllowed = false | no flying with NoClip; true by default and again on rejoining, so set it in playerJoin (Free camera) |
frozen = true | held in place; see below |
putInPillory(name?), releaseFromPillory() | the pillory |
setPace(mode) | forbids running or sprinting |
stopFight(opponent) | ends a fight |
setInteraction(name, allowed) | the game's interactions for this player; see Server rules |
frozen works like Npc.frozen. Their game lets through only looking around and menus, and a modified game that moves
the body anyway is put back within a second. A script's teleport moves the spot where they are held. It ends when they leave
the server.
Carrying
carrying, heldBy and putDown() cover carrying. holdItem(item) and dropHeldItem() are for items in the arms. Any
item the game can carry in the arms works, including the game's quest sacks, such as rasuvUcen_sackcarryable. When put down,
it is laid as a GroundItem on all screens.
Attaching to another player
attachTo(other, options) keeps a body next to another player, like a rider on a horse. detach() ends it, and it also ends
when either player leaves. attachedTo reads the other player.
| Option | Meaning |
|---|---|
offset | { x right, y forward, z up } in metres, seen from other |
rotation | degrees to turn the body; it otherwise faces the way other faces |
look | 'free' (default) looks around up to 120 degrees either side; 'follow' keeps the view on the body's direction |
animation, otherAnimation | { fragment, ...playAnimation options }, looping by default, stopping when the attachment ends |
otherAnimation is upper-body unless it says otherwise, so other can walk. A cuffed player keeps the cuffed pose, and
animation does not play on them. The attached player's game lets through only the menus, plus looking around with 'free'.
The two keep their distance on all screens and do not collide. The attached body is carried, though, so its legs do not walk
unless you play an animation, and it passes through walls and furniture. Teleport it to a free spot if it may be inside
something when you detach it. For a prisoner walking on their own legs, use Follow with a distance.
Items, skills and buffs
giveItem,takeItem,getInventory()anddropAll(): see InventoryaddXp,setLevel,addPerkand others: see ProgressionaddBuff,removeBuff,hasBuff: see Custom buffs
Reference: Player.