A Beginner's Guide to Scripting

From The DarkMod Wiki
Jump to navigationJump to search

written by Fidcal


WORK IN PROGRESS....


Introduction

This is a simplified guide for beginners to dark mod scripting. It makes only two assumptions:

  • You have done some mapping so know what is meant by 'entity', spawnarg, trigger, target, etc.
  • You have some interest in programming and so have at least dabbled in another language and have some idea what variables (x=99), conditions (IF A=B), loops (FOR N=1 TO 10), and subroutines, procedures or functions are (GOSUB, PROC, CALL) and so on. These are common to all programming languages and only the syntax and terms and way used need be learned to start scripting.

This guide is likely to omit advanced material so do not think it fully comprehensive.

I'll describe how to write short scripts demonstrating all of the above basic essentials by example so starting with a blank sheet you will at the end have working scripts and understand how you can use them in your maps. In addition there is a keyword reference index so you can quickly review or find new controls and commands to include and to extend your scripting ability.


Learn by Doing

You can just read any parts of the following you want, especially if you already have some knowledge of scripting but a complete beginner should at least study it all. But to get the best out of it you ought to build the test maps and scripts as you go along. They only take a few minutes and you will absorb more and be confident you understand because you can see that you, yourself, have got them working. You can also modify the scripts to see the effects and some of them will be of use to copy and paste into scripts you can use in your missions.


Create a Test Map

Create a test map or use one you have. Any name or size but for this guide I will assume you have built a reasonably big one-room map named testScripts.map


Creating a Script File

Using a plain text editor create a blank file with the same name as your map, eg, testScripts.script and save it in the same folder as your map.


Script File Format

If you are familiar with 'C'-like languages then you can skim over the next few sections to #Sending Text to the Console to Test and Debug


Instruction Lines

Script code consists of lines of instructions which are carried out in order:

Do this
Do That
Do Something else

Each instruction line can spread over more than one text line in the file like so:

Do this
Do That
Do Something
else

So because the end of the instruction line is not necessarily the end of the text line, each instruction line must end in a semi-colon to denote its end:

Do this;
Do That;
Do Something
else;

In practice, most instruction lines fit on one text line anyway.


Grouping Structure

Almost all instruction lines are grouped together as functions, conditional structures, loops, etc. each within curly brackets with a preceding header. These must NOT have a semi-colon after them like the instruction lines.

It is crucial that there be an opening curly bracket and a closing bracket always in pairs for each group so common practice is to indent text (typically a tab space) within these groups to make it easier to read:

header
{
	Do this;
	Do That;
	Do Something else;
}

Note the semi-colons at the end of the instruction lines but NOT after the header or curly brackets.

Technically it does not matter how they are placed on the text lines so the above could be written like this and still work:

header{	Do this;
	Do That; Do more;

Do Something else;}

Most commonly, groups are written like this with the first curly bracket at the end of the header line:

header{
	Do this;
	Do That;
	Do Something else;
}

You'll see that a lot when studying other scripts but in this tutorial I'll be putting the curly brackets on their own lines for clarity.

Groups can be placed inside groups, and more nested inside those so long as every group starts with a header and left curly bracket and ends with a curly bracket:

header
{
	Do this;
	Do That;
	Do Something else;

	AnotherHeaderInsideTheFirstGroup
	{
		Do even more;
		Do it better;
	}

	Do a bit more;
}


Functions

Almost all scripting is within functions which are group structures as described in the preceding sections. The function header is always preceded by its type name and followed by two normal brackets containing any data (arguments) separated by commas needed to be sent to the function, ie...

type FunctionHeaderName(arg1, arg2, arg3.....)

If no arguments are needed then use empty brackets:

type FunctionHeaderName()

The 'type' is the type of value returned by the function, eg, number, string of characters, etc. (more later.) If there is no value being returned then use 'void' instead thus...

void FunctionHeaderName()

So a typical function would look like:

void FunctionHeaderName()
{
 Do this;
 Do That;
 Do Something else;
}

Sending Text to the Console to Test and Debug

This is the first real script and is useful to check that your script is actually working at all and also to show real information that will help you test that it is working correctly.

Creating a Function

Firstly, as described in the previous sections, you need to create a function group structure to put the script in. We can give it almost any sensible header name. Let's call it 'SendToConsole'. So type the following into your script file and save it...

void SendToConsole()
{

}
  • What you might call a 'command' in other languages is similar to what in Dark Mod scripting is called a 'script event'.
  • The command or script event to send text to the console is 'print'.
  • In scripting these script events always need to be associated with an entity.
  • Event and entity are written together with the entity first, then a period (full stop) then the event, ie, entityname.event.
  • If there is no specific entity like with 'print' then the sys entity is used.

So in this case to send text to the console we need sys.print.

  • The data (the text we want to print in this case) to be used by the event follows it within ordinary brackets () ie, entityname.event(data).
  • We can print numbers or we can print strings of characters within double quote marks.
  • Use \n within double quotes to force a linefeed, eg, "Line1\nLine2"
  • Use the plus sign to combine different strings and numbers and variables, eg, ("\n"+x+" green bottles")

Here is the instruction line...

	sys.print("\n\nYour script is running");

Remember the semi-colon on the end. The two "\n\n" are not crucial - just to do a couple of linefeeds so its easier to spot our line amongst the other console stuff. Type it into your script file within the curly brackets of the empty function you already created and save it. It should look like this...

void SendToConsole()
{
 	sys.print("\n\nYour script is running");
}

Running the Function

On its own the function will do nothing. There are several ways to get it to start working. This is how we'll do it here:

  • In your map, create a target_tdm_callscriptfunction entity.
  • Give it the property/value: call SendToConsole (Function names are case-sensitive so sendtoconsole won't work - it must be exactly how you typed it in the script file.)

You need to trigger that any way you like; we'll make a lever and target the above:

  • Create a model: models/darkmod/mechanical/switches/switch_rotate_lever.ase
  • Change its classname to atdm:mover_lever
  • Give it the property/values:
    • rotate 0 0 -45
    • target <name of target_tdm_callscriptfunction entity>

Try the map; frob the lever then check the console to see if it has printed the debug test text.


Troubleshooting

Note: To reload your script after changes, reload the map. If you use the command reloadScript in the console it exits the map anyway.

If you can't see the script output text in the console then enter 'clear' and try again. If no text then carefully recheck your work with the preceding sections. Some things you can try to debug:

  • Any relevant error message in the console?
  • Is your script file actually in the same folder as your map?
  • Is it precisely the same name as your map?
  • Does it really' have the suffix .script and not .txt or .script.txt?
  • Add a light to your map and target it with your lever to make sure your lever is working.

Comments, Remarks