Sounds and game files
Resources can play the game's sounds, play their own .ogg files as speech, and add or replace game
files such as models, textures, sounds and animations.
Playing the game's sounds
kcds.world.Audio is client-only and plays sounds on that one machine. For a sound everyone should
hear, have the server tell all clients to play it:
// server kcds.core.Events.broadcast('bells:ring', { x: 1998, y: 2498.75, z: 116 });
// client kcds.core.Events.on('bells:ring', (spot) => { kcds.world.Audio.playAt('a_o_bell_kkut_kostelni', spot); });
| Call | What it does |
|---|---|
play(trigger) | plays at the local player |
playAt(trigger, position) | plays at a point |
playFrom(trigger, entityId) | plays on an entity and follows it |
stopFrom(trigger, entityId) | stops that sound |
setSoundParameter(entityId, name, value) | sets one of the game's audio parameters |
setSoundSwitch(entityId, name, value) | sets one of the game's audio switches |
triggerExists(trigger) | true when the game's audio data has this name |
// client const { Audio } = kcds.world; Audio.play('v_horse_whistle'); Audio.setSoundParameter(horseId, 'horse_speed', 0.5); Audio.setSoundSwitch(playerId, 'sword_mat', 'mat_metal');
Each call returns whether the game accepted it. You get false before a world has loaded, for a name
the game does not have, and for an entity that is not there. Names can be up to 256 bytes, and
positions must be within 16 km of the map's origin.
Speech from a file
Audio.playFile(file, entityId, purpose?) plays an .ogg on an entity like a spoken line. It comes
from that position, fades with distance and follows the player's voice volume.
// client: your file is stream/sounds/kcds/guards/halt.ogg kcds.world.Audio.playFile('sounds/kcds/guards/halt', guardId, '20');
file is a game path, with or without .ogg. It can be a file you ship, where
stream/sounds/kcds/<resource>/line.ogg becomes sounds/kcds/<resource>/line, or one of the game's
lines under Localization/dialog/.... A path with a backslash, a drive, a leading / or .. throws.
A file the game cannot find plays nothing.
purpose sets how it sounds:
| Value | Meaning |
|---|---|
inner | an inner voice |
10, 20, 35, 50, 100, 200 | heard up to that many metres; default is 50 |
sfp_dialog, sfp_cutscene, sfp_music | the game's own sound categories |
One file per entity can start every 0.1 s.
Voice chat
KCDS has no voice chat yet, so players talk over Discord or a similar program. It is planned as its own milestone.
Adding game files: stream/
Your resource's stream/ folder holds new files at their game paths, in a folder named after your
resource: stream/<top folder>/kcds/<resource>/.... Each player running the resource receives them, and
the game loads them by path like its own.
resources/
furniture/
package.json
server.js
stream/
objects/kcds/furniture/chair.cgf
objects/kcds/furniture/chair.cgfm
sounds/kcds/furniture/creak.ogg// server: spawn the chair by its full path kcds.world.Prop.spawn('objects/kcds/furniture/chair.cgf', new kcds.math.Vector3(1650, 2150, 37));
// client: check whether this game has it yet if (kcds.core.Assets.has('objects/kcds/furniture/chair.cgf')) { console.log('the chair is here'); }
stream/andreplace/always reach clients, whateverfilessays.- A file outside
<top folder>/kcds/<resource>/is refused, so a streamed file cannot take the place of a game file or another resource's file. - To play a
.cafanimation you ship, useplayer.playAnimation('', { clip }); see Animations.
Replacing game files: replace/
A file at replace/<game path> is used in place of the game's file at that path, for every client
running the resource:
replace/objects/manmade/task_specific_props/household/cooking_eating/eating_tools/wooden_scoop.cgf
Keep in mind:
- A model the game loaded before your resource started stays as it was until the game loads it again.
kcds.core.Assets.hasdoes not count replaced files.- Every player who joins downloads these files, so replace only what your server needs.