158 lines
7.0 KiB
TeX
158 lines
7.0 KiB
TeX
\documentclass[12pt]{article}
|
|
\usepackage{listings}
|
|
\usepackage{underscore}
|
|
\lstloadlanguages{C++}
|
|
\lstset{language=C++, frame=trBL, aboveskip=15pt, belowskip=15pt, xleftmargin=20pt, xrightmargin=20pt}
|
|
\title{Warzone2100 JavaScript Scripting API}
|
|
\date{}
|
|
\begin{document}
|
|
\maketitle
|
|
|
|
\section{Introduction}
|
|
|
|
Warzone2100 contains a scripting language for implementing AIs, campaigns and some of the game
|
|
rules. It uses JavaScript, so you should become familiar with this language before proceeding
|
|
with this document. A number of very good guides to JavaScript exist on the Internet.
|
|
|
|
The following hard-coded files exist for game rules that use this API:
|
|
|
|
\begin{description}
|
|
\item[multiplay/skirmish/rules.js] Default game rules - base setup, starting research, winning and losing.
|
|
\item[multiplay/script/scavfact.js] Scavenger AI. This script is active if scavengers are.
|
|
\end{description}
|
|
|
|
For ordinary AI scripts, these are controlled using '.ai' files that are present in the 'multiplayer/skirmish'
|
|
directory. Here is an example of an '.ai' file that defines an AI implemented using this API:
|
|
|
|
\begin{lstlisting}
|
|
[AI]
|
|
name = "Semperfi JS"
|
|
js = semperfi.js
|
|
\end{lstlisting}
|
|
|
|
It references a '.js' JavaScript file that needs to be in the same directory as the '.ai' file.
|
|
|
|
The code in a javascript file is accessed through specially named functions called 'events'. These are defined below.
|
|
An event is expected to carry out some computation then return immediately. The game is on hold while an event is
|
|
processed, so do not do too many things at once, or else the player will experience stuttering.
|
|
|
|
All global variables are saved when the game is saved. However, do not try to keep JavaScript objects that are
|
|
returned from API functions defined here around in the global scope. They are not meant to be used this way, and
|
|
bad things may happen. If you need to keep static arrays around, it is better to keep them locally defined to a
|
|
function, as they will then not be saved and loaded.
|
|
|
|
One error that it is easy to make upon initially learning JavaScript and using this API, is to try to use
|
|
the 'for (... in ...)' construct to iterate over an array of objects. This does not work! Instead, use code
|
|
like the following:
|
|
|
|
\begin{lstlisting}
|
|
var droidlist = enumDroid(me, DROID_CONSTRUCT);
|
|
for (var i = 0; i < droidlist.length; i++)
|
|
{
|
|
var droid = droidlist[i];
|
|
...
|
|
}
|
|
\end{lstlisting}
|
|
|
|
The above code gets a list of all your construction droids, and iterates over them one by one.
|
|
|
|
The droid object that you receive here has multiple properties that can be accessed to learn more about it.
|
|
These propertie are read-only, and cannot be changed. In fact, objects that you get are just a copies of
|
|
game state, and do not give any access to changing the game state itself.
|
|
|
|
Any value written in ALL_CAPS_WITH_UNDERSCORES are enums, special read-only constants defined by the
|
|
game.
|
|
|
|
\subsection{Challenges}
|
|
|
|
Challenges may load scripts as well, if a [scripts] section is present in the challenge file, and has the keys
|
|
"extra" or "rules". The "extra" key sets up an additional script to be run during the challenge. The "rules"
|
|
key sets up an alternative rules file, which means that the "rules.js" mentioned above is \emph{not} run. In
|
|
this case, you must implement your own rules for winning and losing, among other things. Here is an example
|
|
of such a scripts section:
|
|
|
|
\begin{lstlisting}
|
|
[scripts]
|
|
rules = towerdefense.js
|
|
\end{lstlisting}
|
|
|
|
You can also specify which AI scripts are to be run for each player. These must be given a path to the script,
|
|
since you may sometimes want them from the AI directory ("multiplay/skirmish/") and sometimes from the challenge
|
|
directory ("challenges/"). If you do not want an AI script to be loaded for a player (for example, if you want
|
|
this player to be controlled from one of your challenge scripts), then you can give it the special value "null".
|
|
Here is an example if a challenge player definition with its AI specified:
|
|
|
|
\begin{lstlisting}
|
|
[player_2]
|
|
name = "Enemy"
|
|
team = 1
|
|
difficulty = "Medium"
|
|
position = 4
|
|
ai = multiplay/skirmish/semperfi.js
|
|
\end{lstlisting}
|
|
|
|
\section{Common Objects}
|
|
|
|
Some objects are described under the functions creating them. The following objects are produced by
|
|
multiple functions and widely used throughout, so it is better to learn about them first.
|
|
|
|
Note the special term \emph{game object} that is used in several places in this document. This refers
|
|
to the results of any function returning a Structure, Droid, Feature or Base Object as described below.
|
|
Some functions may take such objects as input parameters, in this case they may not take any other kind
|
|
of object as input parameter instead.
|
|
|
|
\input{objects}
|
|
|
|
\section{Events}
|
|
|
|
\input{events}
|
|
|
|
\section{Globals}
|
|
|
|
\begin{description}
|
|
\input{globals}
|
|
\end{description}
|
|
|
|
\section{Functions}
|
|
|
|
\input{functions}
|
|
|
|
\section{Gotchas / Bugs}
|
|
|
|
\subsection{Case sensitivity}
|
|
Due to a bug that is not so easy to fix in the short term, variables defined in global must be case insensitive.
|
|
Otherwise, they may collide on savegame loading. This is only for variables defined in your script. There is no
|
|
need to maintain case insensitivity in regards to variables defined in global by the game itself, such as 'FACTORY'
|
|
(you can safely define your own 'factory' variable) -- the only exception to this is 'me'.
|
|
|
|
\subsection{Global objects}
|
|
You must never put a \emph{game object}, such as a droid or a structure, on global. You only get a snapshot of their state,
|
|
the state is not updated, and they are not removed when they die. Trying to store them globally then using them
|
|
later will fail.
|
|
|
|
All variables stored on global (in global scope) are stored when the game is saved, and restored when it is
|
|
loaded. However, this may not work properly for complex objects. Basic arrays and basic types are supported,
|
|
but it is generally not recommended to put objects on global, even though simple ones may work. Since the game
|
|
can't be saved while a function is running, you don't need to worry about local variables.
|
|
|
|
Const definitions are not stored in savegames, and are therefore recommended over variables to hold information
|
|
that does not change.
|
|
|
|
\subsection{Object states}
|
|
Most object states that are changed from the scripts are not in fact changed, but queued up to be synchronized
|
|
among clients. This means that you cannot check the state later in the same script invokation and expect it to
|
|
have changed. This includes such things as giving orders to droids, setting production to structures, and so on.
|
|
Instead, if for example you want to mark droids that have been ordered to do something, you can mark them by
|
|
adding a custom property. Note that this property will not be remembered when it goes out of scope.
|
|
|
|
\subsection{Early research}
|
|
You cannot set research topics for research labs directly from eventStartLevel. Instead, queue up a function
|
|
call to set it at some later frame.
|
|
|
|
\subsection{Cyborg construction}
|
|
Cyborg components are inter-linked, and cannot be passed in as lists as you can with ordinary droids, even
|
|
though they might look that way.
|
|
|
|
\end{document}
|
|
|