Fundamental Scripting Guide: Difference between revisions

From The DarkMod Wiki
Jump to navigationJump to search
(Created page with "''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 ma...")
 
No edit summary
Line 8: Line 8:




=== Contents ===
== Anatomy of a script ==
'''Anatomy of a script'''


Basic terms
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.


Script functions
=== Basic terms ===


Rudimentary script: message to console
{| class="wikitable"
|-
| 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.
|}


Basic script: simple cutscene
=== Script functions ===
===== Example script function 1 =====
This is a very basic script function which instructs the script to wait for 3s:


sys.wait(3);


'''*More scripting basics'''
Here's a closer look at its components:


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


TDM Script Reference


Troubleshooting (i.e. closeup texture after mistake)
* 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.




'''Setting up script files'''
* ;
** 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.


Map scripts


General scripts
===== 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');


'''*How to call scripts'''
* $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".


From other scripts


Target_callscriptfunction


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


Stim/response
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).


Frob_action_script
void test_script()
{
sys.println(“Test message.”);
}


Objective system
* 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.




'''Variables'''
* 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.


Data types


Creating new variables
*{}
** Curly brackets mark the beginning and end of the body of the script.


Example usage: puzzle with max 3 attempts


* 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.


'''Scripts with input variables'''


Example useage: multiple func_movers and buttons, movement in various directions
===== 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
}


'''"Get"ting information from the map'''
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.


Getting spawnargs
* //
** 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.


Example usage: checking current health of an AI for an objective


* 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.


'''Conditionals'''


Comparisons
* 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.


Checking true or false


Multiple conditions
* $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.
Chains of conditions
 
 
'''Looping/repeating scripts'''
 
Looping with thread
 
Looping with while()
 
Repeating with for()
 
Repeating with do + while()
 
 
'''*Scriptobjects'''
 
Applications
 
Setup
 
Entity defs
 
 
'''*Special methods'''
 
Going through all targets of an entity
 
Sounds
 
Trigger_touch
 
AI variables
 
Spline movers
 
 
'''*Practical examples'''

Revision as of 21:48, 13 December 2020

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.