Fundamental Scripting Guide

From The DarkMod Wiki
Revision as of 21:48, 13 December 2020 by Dragofer (talk | contribs)
Jump to navigationJump to search

Author - Dragofer

This is a (work in progress) resource written primarily for mappers with no background in scripting or coding, though also more experienced scripters may find practical guidance in adapting to TDM's scripting system. This is the large majority of what I've picked up over the years through experimentation, looking at existing scripts and interacting with other forum members.

My aim is for the tutorial to be both comprehensive and down to earth, using many examples and avoiding unnecessary technical terms. There will be some overlap with existing wiki articles, since this aims to have everything in one place out of one hand.

The concept will be to start with teaching some basic script literacy, then introduce scripting principles one after another. Towards the end, practical examples


Anatomy of a script

This section will define essential terms, then look at some basic scripts of slightly increasing complexity to demonstrate what a script is made up of.

Basic terms

Script function Script functions perform an action of some kind, i.e. waiting x seconds or triggering an entity. They are the basic building blocks of scripting.
Script When one writes a "script", one actually writes a new script function, often containing multiple existing script functions. In this guide, "scripts" refer to the new script functions that we write, while "script functions" refer to those that are already part of the base game.
Scriptobject This is a powerful set of scripts that are applied to single entities. This allows you to write code once, but let it apply to an unlimited number of entities without conflicts. An example is the tdm_light_holder scriptobject, which controls the skin, particle, lit state etc. of its candle.
Variables Variables are another basic building block and allow a script to store data for further processing and to have variable effects. Each variable must be named and given a data type.
Data types Every variable and every input/output of a script function needs to have a data type to inform the engine whether it should be read as a text, number, vector etc. Script functions won't work if they're given the wrong type of data.

Script functions

Example script function 1

This is a very basic script function which instructs the script to wait for 3s:

sys.wait(3);

Here's a closer look at its components:

  • sys.
    • Every script function must be called on an entity. For very generic functions like "wait", sys is typically used, shorthand for system.


  • wait(3)
    • This is the actual script function. Every script function must be accompanied by input brackets, even if they're left empty. In this case, "3" is the input.


  • ;
    • A semicolon is needed to mark the end of a line of instructions. Forgetting these is a common mistake that stops the map from loading.


Example script function 2

This is another simple script function. It's called on player1 and teleports (sets the origin of) him to the position '0 150 0'.

$player1.setOrigin('0 150 0');
  • $player1
    • Notice the $ sign: this means the script function should look for a specific entity in the game with that name. The player is always called "player1".


Scripts

Example script 1: rudimentary script for sending a message to the console

Script functions don't work on their own, they need to be part of a script (technically a "script" is still a "script function". See "Basic terms" for a reminder of the distinction I make).

void test_script()
{
	sys.println(“Test message.”);
}
  • void
    • This defines what type of result the script puts out to other scripts: "void" means nothing while i.e. "float" would mean a number. In the large majority of cases you'd use void.


  • test_script()
    • This is the name of the script: "test_script".
    • Like with script functions, input brackets are mandatory. For a script that damages various entities by various amounts, you could define an entity input and a float (number) input.
    • Note that no semicolon is needed at the end of this top line.


  • {}
    • Curly brackets mark the beginning and end of the body of the script.


  • sys.println("Test message");
    • This is a script function which prints a text to the console and then leaves a line (ln), so that every text is on its own line.


Example script 2: basic script for a simple cutscene
void simple_cutscene()
{
	sys.fadeOut('0 0 0', 2);		//fade to black (colour vector '0 0 0') in 2s
	sys.wait(2);				//wait 2s for the fadeOut
	sys.trigger($speaker_narrator);	        //trigger a speaker with a narrator's voice
	$camera.activate($player1);		//activate a camera to disable player controls

	sys.wait(10);				//wait narrator is speaking
	sys.fadeIn('0 0 0', 2);			//fade back in from a black screen in 2s
	$camera.activate($player1);		//return player controls
}

This scripts a basic cutscene: fade to black, activate a speaker, fade back in. At both ends a camera is toggled so that the player can't move while the screen is black.

  • //
    • This is a comment for the reader: anything behind a double slash gets ignored. This is a useful habit for helping others and your future self understand how your script works.


  • sys.fadeOut('0 0 0', 2);
    • This script function uses 2 different inputs:
      • '0 0 0' is a vector defining the colour to which the screen should fade. Every number represents the intensity of red, green or blue colour.
      • 2 is a float (number) defining how long the fadeout should take.


  • sys.trigger($speaker_narrator);
    • This is a script function to trigger a specific entity called "speaker_narrator", which would simply be a speaker in the map with a custom soundshader.


  • $camera.activate($player1);
    • This is an alternative way to trigger, aka activate, an entity. This is needed when you want one entity to be triggered by another entity, instead of "sys". In this case, player1 is the activator who activates the camera. Another example would be the player activating a teleporter entity.