Difference between revisions of "SCM language"

From GTAMods Wiki
Jump to navigation Jump to search
m (Added an important notice on top.)
Line 1: Line 1:
<center><span style="color: #CC0000">'''Announcement''': This article is currently being reworked. Check out the progresses by visiting [http://pastebin.com/raw/YfLWLXJw this] link from time to time. Contact [http://www.gtaforums.com/index.php?showuser=172776 Wesser] for any suggestion.</span></center>
+
Test link (please, submit changes with "Show preview"): http://www.gtamodding.com/index.php?title=SCM_language&action=edit (login required)
{{This|This section deals with the native SCM syntax of GTA 3 series, nothing other than [[GTA 3|III]], [[GTA VC|VC]], [[GTA SA|SA]], [[GTA LCS|LCS]] and [[GTA VCS|VCS]].<br/>
 
It may contain non-standard SCM definitions as R* hasn't published enough documentation about it yet.}}
 
{{TocRight}}On the occasion of the ''GTAIII's Tenth Anniversary'', after a long period of darkness where we fell about the real ''SCM'' syntax, R* finally treated us by attaching part of its own original source code into the ''GTAIII Anniversary'' game, available for ''iOS'' and ''Android'' devices. As far back as 2001, a snip of some debugging scripts has been already provided with ''main.sc'' and ''debug.sc'' files. However, many secrets are unrevealed yet, thus some things cannot be documented fully and so they can be only guessed. The ''SCM'' format abbreviation is one of countless proofs of this inconvenience, which may stand for ''Script Multifile''. Other doubts come with source files, whose ''SC'' extension appears to be very close to ''Mission SCript''. Although we have enough information to suppose the currently unknown mysteries of the used language, we still have no safe clue about which was its original denomination. Furthermore, it is a matter of fact that R* developers have been left untouched the ''miss2'' executable name of the ''GTA 3 series'' compiler since the chapter 2. In this connection, we could imagine the new language is a variant or an evolution of the '''GTA2script'''. In the ancient documentation by ''DMA'' (at present ''Rockstar North''), ''GBH'' sound like the initials of the codename or the primordial name of ''GTA2'', as the former is expressly stricken and overwritten by the latter (''<del>GBH</del><ins>GTA2</ins>'' occurs twice, whereas ''<del>GBHscript</del><ins>GTA2script</ins>'' only once), while ''GBHscript'' and ''GTA2script'' are quite recurring. Therefore, we are almost sure to say the language name is most likely '''GTA3script'''. However, it is definitely based on [[Wikipedia:BASIC|BASIC]].
 
  
 +
{{This|This section deals with the native script language syntax of GTA 3 series, nothing other than [[GTA 3|III]], [[GTA VC|VC]], [[GTA SA|SA]], [[GTA LCS|LCS]] and [[GTA VCS|VCS]].<br/>
 +
It may incorporate nonstandard specifications due to the fact R* hasn't published enough documentation about yet.}}
 +
{{TocRight}}On the occasion of the ''Grand Theft Auto III's 10th Anniversary'', after a long period of darkness where we fell about the real scripting language syntax, R* finally treated us (or was it, as it seems, a ''War Drum Studios'' sloppy oversight?) by attaching part of its own original source code into the mobile release, available for ''iOS'' and ''Android'' devices. As far back as 2001, a snip of some debugging scripts has been already provided with ''main.sc'' and ''debug.sc'' files that were allegedly meaningful for a sort of script version checker uncut on debug builds. Nonetheless, many secrets are still unrevealed, thus some things cannot be fully documented and so they can be merely guessed. The .scm format abbreviation is one of countless proofs of this inconvenience, which may stand for '''Script Multifile'''; .scc, in turn, might be the short form of '''Script Compiled''' though we would better predilige the '''Combinedfile''' wording. No doubt come with source files, whose .sc extension is the contraction of '''Mission Script'''. Although we have enough information to suppose the currently unknown mysteries of the used language, we still have no safe clue about what was its original denomination. Furthermore, it is a matter of fact that R* developers have been left untouched the '''miss2''' executable filename of the third generation compiler since the chapter 2. In this connection, we could imagine the newer scripting language is a variant or an evolution of the '''GTA2script''' (sometimes referred to as '''GBHscript'''), which label expressly popped up in the ancient documentation by ''DMA Design Ltd'' (at present ''Rockstar North''). Therefore, we are almost sure to say the language name is most likely '''GTA3script''' (as-is casing). However, it is definitely based on [[Wikipedia:BASIC|BASIC]].
  
<span style="font-size: 14pt">Preliminary remarks</span>
 
----
 
This article makes use of formatted codes to improve the reading comprehension. Note that:
 
 
* ''Square brackets'' mean everything inside may be omitted;
 
* ''Curly brackets'' denote the presence of useful codes but not necessarily needed;
 
* ''Vertical bars'' divide what can be chosen alternatively.<br/><br/>
 
 
=Fundamentals=
 
=Fundamentals=
  
 
==Comments==
 
==Comments==
 +
Codes are usually self-explanatory for the author but large sources can compromise everyone's management capability, that means some annotation can save much time on the long-term particularly when being stuck trying to understand old stuff which should never happen in the first place, not to mention team mates would certainly blame the original writer on each revision and slow down the completion of cooperative projects. Sometimes, it is also required to temporarily/permanently disable code lines for testing purposes. Fortunately, the language supports the following typologies of comments:
  
A ''comment'' is an additional text that may be helpful for the code writer or other users, in short for the reader. It is the only part of the source code which gets always ignored when compiling.
+
* ''Single-line'' comment, prefixed with // (two forward slashes), which extends till the end of the line. Everything is ignored inside: <code>// Some comment.</code>;
 
+
* ''Multi-line'' comment, enclosed with a pair of /* (a slash plus an asterisk) and */ (the other way around), which covers a cricumscribed text area. Several blocks can be nested together: <code>/* Some /* comment */ . */</code>.
===Inline===
 
 
 
An ''inline comment'', denoted by '''//''' (two slashes), makes everything that follows some plain text:
 
 
 
[...] // Some inline comment
 
 
 
===Multiline===
 
 
 
A ''multiline comment'' embraces a particular area of the source code, starting by the opening tag '''/*''' (slash and asterisk) and ending with '''*/''' (asterisk and slash):
 
 
 
[...]
 
/*
 
  * Some multiline comment
 
  * ...
 
  */
 
[...]
 
Currently, more than one multiline comment is allowed per line:
 
 
 
[...] /* Some inline comment */ [...] /* Some inline comment */ [...]
 
 
 
;Note
 
:R* compiler allows multiline comments nesting.
 
 
 
==Highlighters==
 
 
 
''Highlighters'' behaviour sounds trivial, that's to say they simply highlight one or more arguments per [[#Commands|command]] within ''round brackets'', individually or together. In {{icon|3}}, they appear to be used only for '''SETUP_ZONE_PED_INFO''' (in a various order) and ''GXT keys'':
 
 
 
SETUP_ZONE_PED_INFO FISHFAC DAY (0) 0 0 0 (0 0 0 0) 0
 
PRINT_BIG (T4X4_1) 5000 2
 
 
 
;Limits
 
:Opening and closing round brakets are treated as blank spaces;
 
:An optional ''comma'' can be used as well to distinguish each argument, processed as a space.
 
 
 
==Scopes==
 
 
 
''Scopes'' are delimited by ''curly brackets'' (or ''multiline brackets'') which act like a [[#Local|local]] [[#Variables|variable]] [[#Scope|scope]]. Essentially, they enclose the code where local variables are used, including [[#Timers|timers]]. They can be opened and closed many times in a [[#Structure|script]]:
 
 
 
{
 
    [...]
 
}
 
 
 
;Limits
 
:Scopes cannot be nested;
 
:Opening and closing curly brakets are real commands.
 
 
 
==Labels==
 
 
 
A ''label'' is a ''sequence of characters'' which identify the reference of a location of the source code useful for ''gotoes''. It can be accessed by any part of the source code. To define a label just append ''':''' (colon) to its name:
 
 
 
[...]
 
 
{lblname}:
 
[...]
 
 
 
At the compiling time, they are automatically converted into an [[#Offsets|offset]].
 
 
 
==Variables==
 
 
 
A ''variable'' is a ''storage location'' assigned to a ''symbolic name'' which contains a ''value'' of any ''type''.
 
 
 
===Value===
 
 
 
A ''value'' represents ''any data of any type'' it is.
 
 
 
===Scope===
 
----
 
The usage of a variable depends on the ''scope'', that is the context where a specific variable is declared. At this point, we can distinguish the ''global'' and ''local'' scope.
 
 
 
====Global====
 
 
 
The ''global scope'' grasps the ''whole source code''. Variables defined as ''globals'' are visible in ''any [[#Structure|script]]''. They are declared by appending the '''VAR''' prefix.
 
 
 
====Local====
 
----
 
The ''local scope'' wraps a ''localized part of the source code''. Variables defined as ''locals'' are visible only in the ''code enclosed by curly brackets''. You can put them everywhere and as many times as you want in the source code. They are declared by appending the '''LVAR''' prefix.
 
 
 
=====Timers=====
 
 
 
A ''timer'' is an ''unique local variable'' whose value rises automatically. It starts incrementing since the beginning of the script where it has been placed and grows endlessly. There are ''2 usable timers'' which are already defined as '''TIMERA''' and '''TIMERB''', therefore they do not need to be declared.
 
 
 
===Data types===
 
----
 
Among the available data types, some are equivalent to those of the most known programming languages. Their length is up to 4, 8 and 16 bytes. Each type is appended as a suffix in the ''variable declaration''.
 
 
 
====LABEL====
 
 
 
The '''LABEL''' type handles ''variable-length strings''. It can refer to either a ''[[#Labels|label]] name'' or a ''file name''.
 
 
 
;Notes
 
:While inside a script file, R* compiler treats it unambiguously as a label;
 
:R* compiler allocates 32 bytes per label.
 
 
 
;Limit
 
:'''LABEL''' variables aren't available.
 
 
 
====INT====
 
 
 
The '''INT''' type handles ''32-bit signed integers''. It is also used to store [[#Value|values]] with less bytes, such as a [[Wikipedia:Primitive_data_type#Booleans|bool]], a [[Wikipedia:Character_(computing)#char|char]] and a [[Wikipedia:Integer_(computer_science)#Short_integer|short int]].
 
 
 
====FLOAT====
 
 
 
The '''FLOAT''' type handles ''32-bit floating-points''. As it normally does, decimal precision of a [[Wikipedia:Floating_point|float]] is usually stuck to 6-7 digits beyond which it may get lost.
 
 
 
;Notes
 
:R* compiler also accepts ''f'' and ''F'' suffixes for the immediate value.
 
 
 
====TEXT_LABEL====
 
 
 
The '''TEXT_LABEL''' type handles ''8-byte strings''. Generally, a [[Wikipedia:String_(computer_science)|string]] is an ''array of 1-byte characters''. It requires ''7 characters plus the [[Wikipedia:Null_character|null-terminator]]'' (a blank byte meaning the ''end of the string''). It is used to hold ''GXT keys'' (those of ''town zones'', ''interiors'', ''help textes'' or ''dialogue subtitles'') ''script names'' or any short string. Literal only '''TEXT_LABEL*''' strings are probably marked by ''single quotation marks'' to distinguish them from variable and constant identifiers:
 
 
 
PRINT_BIG 'GXT_KEY'
 
 
 
;Limit
 
:'''TEXT_LABEL''' variables are supported in {{icon|sa}} and {{icon|vcs}}.
 
 
 
====TEXT_LABEL16====
 
 
 
The '''TEXT_LABEL16''' type handles ''16-byte strings''. Like the previous, this type holds ''15 characters plus the null-terminator''. It is used to store ''model and texture names of player clothes'', ''animation names'' or any long string.
 
 
 
;Limit
 
:'''TEXT_LABEL16''' variables and values are supported only in {{icon|sa}}.
 
 
 
====TEXT_LABEL32====
 
 
 
The '''TEXT_LABEL32''' type handles ''32-byte strings'' or larger, depending on how many continuous parameters of the same type there are, each of which occupies 32 bytes. It can hold up to ''127 characters plus the null-terminator'', after which another '''TEXT_LABEL32''' argument may begin. Strings of such type must be put within ''double quotation marks'':
 
 
 
SAVE_STRING_TO_DEBUG_FILE "32B-128B TEXT"
 
 
 
;Limits
 
:'''TEXT_LABEL32''' values are supported since {{icon|vc}};
 
:'''TEXT_LABEL32''' variables aren't available.
 
 
 
====TEXT====
 
 
 
The '''TEXT''' type handles ''N-byte strings''. It holds ''N characters plus the null-terminator''. Strings of this type mustn't exceed 255 characters (including the null-byte).
 
 
 
;Limits
 
:'''TEXT''' values are supported since {{icon|sa}};
 
:'''TEXT''' variables aren't available.
 
 
 
====CONST (pseudo)====
 
 
 
The '''CONST''' type handles ''32-bit signed integers''. It is used only to assign and compare [[#Constants|constants]] to '''INT''' variables regarding ''model [[#Identifiers|identifiers]]'', ''task statuses'', ''ped or audio events'' and such. It is a pseudo type of '''INT'''.
 
 
 
;Limit
 
:The [[#Arithmetic|assignment]] and [[#Comparison|comparison]] of '''CONST''' values are supported since {{icon|vc}}.
 
 
 
====MULTI (pseudo)====
 
 
 
The '''MULTI''' type handles a group of few data types acceptable per argument. It is used only for commands featuring optional arguments, those whose type is unpredictable before the compilation. It can be a pseudo type of '''INT''', '''FLOAT''' and '''TEXT_LABEL'''.
 
 
 
;Notes
 
:'''INT''' and '''FLOAT''' can be used interchangeably in {{icon|3}}, {{icon|vc}}, {{icon|sa}}, {{icon|lcs}} and {{icon|vcs}};
 
:{{icon|vcs}} also admits '''TEXT_LABEL''' arguments.
 
 
 
===Declaration===
 
----
 
''Defining a variable'' means ''assigning a token string to a memory cell'' at the compiling time. Variables must be declared in the following manner:
 
 
 
VAR_* {varname0}[,] [... {varnameN}]
 
LVAR_* {varname0}[,] [... {varnameN}]
 
 
 
As mentioned in the sections above, local variables have to be put within curly brackets:
 
 
 
{
 
    VAR_* {varname0}[,] [... {varnameN}]
 
    LVAR_* {varname0}[,] [... {varnameN}]
 
 
    [...]
 
}
 
 
 
''Inline variable declaration'' is allowed, you just have to separate them by ''spaces'' or ''tabulations''. Adding a preceding ''comma'' before these characters is optional.
 
 
 
;Limits
 
:Whereas the ''variable buffer'' is limited, you can declare a certain amount of globals and locals. [[#INT|INT]] and [[#FLOAT|FLOAT]] types take 1 variable, while [[#TEXT_LABEL|TEXT_LABEL]] and [[#TEXT_LABEL16|TEXT_LABEL16]] types occupy respectively 2 and 4 variables to store their data (have a look [[#Variables range|here]] for further details);
 
:{{icon|vcs}} isn't affected by what said above;
 
:Global and local variable names must not collide.
 
  
====Arrays====
+
==Delimiters==
 +
Conventionally, lines can be splitted into various regions in order to enhance the code legibility through bracket-delimited and/or comma-separated elements. As being pure white-spaces, the opening parenthesis delimiter doesn't necessarily need to match the closing counterpart and viceversa. The only tangible use of separators carried out in public sources is related to inline declaration of multiple variables, text keys of print-commands and '''SETUP_ZONE_PED_INFO''' but codes can be organized to one's liking. Here are some demonstrations:
  
A ''array'' is a ''collection of variables'' having the same type which can be accessed by an ''index'', an '''INT''' lesser than or equal to the size specified, enclosed by ''square brackets'':
+
VAR_INT joeys_buggy, swank_taxi
 +
PRINT_NOW (ASUKA) 2000 1
 +
SETUP_ZONE_PED_INFO CHINA DAY (30) 350 600 0 (0 0 0 0) 0
  
{
+
==Integers and Floating-points==
    VAR_* {varname0}{[arrsize0]}[,] [... {varnameN}{[arrsizeN]}]
 
    LVAR_* {varname0}{[arrsize0]}[,] [... {varnameN}{[arrsizeN]}]
 
 
    [...]
 
}
 
  
;Limits
+
==Labels, Text labels and Strings==
:The usage of arrays is allowed since {{icon|vc}};
+
Thanks to the beneficial code fragmentation, the source is subject to external file inclusions and variegated in-file unconditional branches involving embedded code blocks diversification. Both kinds of partitioning are accomplished respectively through the specification of:
:Variable indices are quite buggy in {{icon|vc}} and therefore unrecommended, but they are fully supported since {{icon|sa}};
 
:The aforesaid indices are one-based, possibly zero-based since {{icon|sa}};
 
:Multidimensional arrays are not supported.
 
  
====Handles====
+
* ''Filenames'', that is special labels which somehow resemble legit pathnames, starting with any valid pathname character but not containing whitespaces. They are relative to the root path deriving from the .sc extension removal of the main script full path where files are searched in by default: <code>X:\folder\main</code>. Subfolders are scanned as well:
 +
** Till the first tree level if inside one of the subdirectories: <code>X:\parent\main\child</code>;
 +
** Till the second tree level if inside one of the parent directories: <code>X:\parent</code> or <code>X:\parent\main</code>;
 +
** Indefinitely (unlimited recursion till the maximum path length allowed).
 +
:The .sc extension at the end of filenames is mandatory else an argument mismatch is warned, by contrast the main script can have any extension to which ''m'' (multifile) or ''c'' (combinedfile) is appended in the target pathname. Due to a [[Cd image]] system limitation, all sorts of filename must be shorter than 20 characters and conventionally they must be free of extra dots for streamed scripts.
 +
* ''Label references'', that is unique string identifiers suffixed by a colon which identify a precise location within the common (main script, main extensions and subscripts) or the actual (mission scripts and streamed scripts) script space. Basically, they represent the target position of either goto-like, script starter or function caller commands: <code>my_label_ref:</code> (on a new line). Weirdly enough, label references may begin with any character alike filenames despite they are susceptible to the same restrictions of string identifiers whenever passed as arguments but must not exceed 38 characters, colon excluded, either way. Whereas these are not commands, anything else can follow next to and being inlined so long as a splitting character is inserted.
  
A ''handle'' is an univocal identifier assigned to a game entity. It is given by the following statement:
+
That said, labels are essentially user-supplied string identifiers whose existence is verified. Text label identifiers are not fully bound to this rule (except script names) since they are massively employed as main/mission text keys or whatever referring to an internal resource, which the game handles according to a well-defined associative scheme. Notoriously, identifiers length is anything but expensive for readability reasons, in addition they do not even offer the ability to insert white-spaces or other inadmissible characters owing to the by-design absence of delimiting tokens. <incorrect>At this matter, variable-length strings and debugging texts sent as 128-byte string literals are enclosed by " " (double quotes):
  
<source lang=cpp>short nHandle = (iEntityIndexInPool << 8) | ucEntityFlag;</source>
+
CUSTOM_PLATE_FOR_NEXT_CAR CAR_TAMPA "_FELTCH_"</incorrect>
 +
SAVE_STRING_TO_DEBUG_FILE "CURRENT_WANTED_LIST = "
  
;Note
+
Empty text labels are impracticable, though '''NIL''' compiles a <code>NUL</code>-string in the last Stories chapter<sup>[no source]</sup><s> &ndash; as reported by some indiscreet sources, the rearrangement of crucial commands signals a syntax enhancement the language has undergone which sees delimited strings superseding text labels, lowly probable because string constants are still disallowed for multi-type parameters; as previously assumed, instead, '''DUMMY''' could have been the placeholder keyword but a text key exists actually, while a single _ (underscore) is more Python-oriented (used as a throwaway variable)</s>. It's worth noting string literals and text labels are not interchangeable because of their syntactic differences even if they present semantic similarities, moreover text labels do not ever interfere with command names and string constants. A final quirk to note concerning labels as a whole is they are automatically converted to upper case: this obvious evidence proves identifiers and whatnot are all case insensitive with the exception that 128-byte strings are left as-is for remastered game builds.
:R* compiler won't let you assign different entity types to the same variable or using a variable which hasn't been passed to any [[#Commands|command]] designated to the creation of an entity.
 
  
==Operators==
+
==Data types==
 +
Forasmuch as the language obeys the [[Wikipedia:Strong and weak typing|strong typing]] paradigm, the syntactic elements that denote a value during execution do have fixed data types, most of which are appended as a suffix at variable declaration. Their conspicuous assortment is listed below:
  
In general, an ''operator'' is a token string that represents a math calculation or an operation of any other kind, in order to make the code understanding clearer at a glance.
+
{|class=wikitable style="text-align: center"
 
 
===Arithmetic===
 
 
 
''Arithmetic operators'' compute some of the most common algebric calculations between either a [[#Variables|variable]] and a [[#Value|value]] or two variables. As well as in some programming language happens, [[#CONST (pseudo)|CONST]], [[#TEXT_LABEL|TEXT_LABEL]] and [[#TEXT_LABEL16|TEXT_LABEL16]] types are free from these operators, except for the ''basic assignment''  (see also [[#Operators composition|Operators composition]]):
 
 
 
{|class=wikitable
 
!width=70px|Operator
 
!width=225px colspan=2|Name
 
!width=225px|Syntax
 
!width=550px|Description
 
 
|-
 
|-
!=
+
!style="text-align: left"|Name
|align=center colspan=2|Assignment
+
!Format
|align=center|<code>expr0 '''=''' expr1</code>
+
!Size
|Store ''expr1'' to ''expr0''
+
!Range
 +
!width=64px|Game<br/>support
 +
!width=64px|Variable<br/>support
 +
!Is<br/>basic
 
|-
 
|-
!+
+
!colspan=7|Single-typed
|align=center colspan=2|Addition
 
|align=center|<code>expr0 '''+''' expr1</code>
 
|Add ''expr1'' to ''expr0''
 
 
|-
 
|-
!-
+
|align=left|'''LABEL'''||String identifier<br/><span style="font-size: 0.75em">(translated to offset/index)</span>||rowspan=2|4||rowspan=2|-2<sup>31</sup> to 2<sup>31</sup>-1||rowspan=2|Since {{icon|3}}||None||
|align=center colspan=2|Subtraction
 
|align=center|<code>expr0 '''-''' expr1</code>
 
|Subtract ''expr1'' from ''expr0''
 
 
|-
 
|-
!*
+
|align=left|'''INT'''||Signed integer||rowspan=3|Since {{icon|3}}||&#x2713;
|align=center colspan=2|Multiplication
 
|align=center|<code>expr0 '''*''' expr1</code>
 
|Multiply ''expr0'' by ''expr1''
 
 
|-
 
|-
!/
+
|rowspan=2 align=left|'''FLOAT'''||[[Wikipedia:Q (number format)|Q11.4 fixed-point]]||2||-2<sup>11</sup> to 2<sup>11</sup>-2<sup>-4</sup>||{{icon|3}} only||rowspan=2|&#x2713;
|align=center colspan=2|Division
 
|align=center|<code>expr0 '''/''' expr1</code>
 
|Divide ''expr0'' by ''expr1''
 
 
|-
 
|-
!+@
+
|[[Wikipedia:Floating point|IEEE-754 floating-point]]||4||&plusmn;3.4&times;10<sup>&plusmn;38</sup>||Since {{icon|vc}}
|align=center colspan=2|Timed addition
 
|align=center|<code>expr0 '''+@''' expr1</code>
 
|Multiply ''expr2'' by delta time and add the result to ''expr1''
 
 
|-
 
|-
!-@
+
|align=left|'''TEXT_LABEL'''||rowspan=2|UTF-8 null-terminated<br/>[[Wikipedia:String (computer science)|string]] identifier||8||1 to 7||Since {{icon|3}}||{{icon|sa}} and {{icon|vcs}}||&#x2713;
|align=center colspan=2|Timed subtraction
 
|align=center|<code>expr0 '''-@''' expr1</code>
 
|Multiply ''expr2'' by delta time and subtract the result from ''expr1''
 
 
|-
 
|-
!rowspan=2|++
+
|align=left|'''TEXT_LABEL16'''||16||1 to 15||rowspan=2|{{icon|sa}} only||{{icon|sa}} only||&#x2713;
|align=center rowspan=2|Increment
 
|align=center|Pre{{ref|preinc|[*]}}
 
|align=center|<code>'''++''' expr0</code>
 
|rowspan=2|Increment ''expr0'' by 1 and store the result to ''expr0''
 
 
|-
 
|-
|align=center|Post
+
|align=left|'''TEXT_LABEL32'''||UTF-8 null-terminated<br/>string identifier<br/><span style="font-size: 0.75em">(4 contiguous blocks)</span>||32&times;4||1 to 127||None||
|align=center|<code>expr0 '''++'''</code>
 
 
|-
 
|-
!rowspan=2|--
+
!colspan=7|Multi-typed
|align=center rowspan=2|Decrement
 
|align=center|Pre{{ref|preinc|[*]}}
 
|align=center|<code>'''--''' expr0</code>
 
|rowspan=2|Decrement ''expr0'' by 1 and store the result to ''expr0''
 
 
|-
 
|-
|align=center|Post
+
|rowspan=2 align=left|'''PARAM'''||colspan=3|Same as '''INT''' and '''FLOAT'''||colspan=2|Since {{icon|3}}||rowspan=4|
|align=center|<code>expr0 '''--'''</code>
 
|}
 
 
 
;Note
 
:{{note|preinc}} Pre and post increments have no difference unlike what you would expect.
 
 
 
Yet, you can put the ''assignment'' and ''algebric'' operators together inline as follows:
 
 
 
{|class=wikitable
 
!width=70px|Operators
 
!width=225px|Name
 
!width=225px|Syntax
 
!width=550px|Description
 
|-
 
!= +
 
|align=center|Addition and assignment
 
|align=center|<code>expr0 '''=''' expr1{{ref|expr01|[*]}} '''+''' expr2</code>
 
|Add ''expr2'' to ''expr1'' and store the result to ''expr0''
 
|-
 
!= -
 
|align=center|Subtraction and assignment
 
|align=center|<code>expr0 '''=''' expr1{{ref|expr01|[*]}} '''-''' expr2</code>
 
|Subtract ''expr2'' from ''expr1'' and store the result to ''expr0''
 
 
|-
 
|-
!= *
+
|colspan=3|Same as '''TEXT_LABEL'''||colspan=2|Since {{icon|vcs}}
|align=center|Multiplication and assignment
 
|align=center|<code>expr0 '''=''' expr1{{ref|expr01|[*]}} '''*''' expr2</code>
 
|Multiply ''expr1'' by ''expr2'' and store the result to ''expr0''
 
 
|-
 
|-
!= /
+
|rowspan=2 align=left|'''STRING'''||UTF-8 string<br/><span style="font-size: 0.75em">(non null-terminated)</span>||1..127||1 to N-1||rowspan=2|{{icon|sa}} only||None
|align=center|Division and assignment
 
|align=center|<code>expr0 '''=''' expr1{{ref|expr01|[*]}} '''/''' expr2</code>
 
|Divide ''expr1'' by ''expr2'' and store the result to ''expr0''
 
 
|-
 
|-
!= +@
+
|colspan=3|Same as '''TEXT_LABEL/16'''<br/><span style="font-size: 0.75em">(variable-only)</span>||{{icon|sa}} only
|align=center|Timed addition and assignment
 
|align=center|<code>expr0 '''=''' expr1{{ref|expr01|[*]}} '''+@''' expr2</code>
 
|Multiply ''expr2'' by delta time, add the result to ''expr1'' and store everything to ''expr0''
 
|-
 
!= -@
 
|align=center|Timed subtraction and assignment
 
|align=center|<code>expr0 '''=''' expr1{{ref|expr01|[*]}} '''-@''' expr2</code>
 
|Multiply ''expr2'' by delta time, subtract the result from ''expr1'' and store everything to ''expr0''
 
 
|}
 
|}
  
;Note
+
Some tiny caveats about immediate numeric fields:
:{{note|expr01}} ''expr1'' can represent ''expr0'' too.
 
  
;Limit
+
* String constants are compatible with integer parameters;
:Multiple algebric operators per line are not allowed.
+
* Literals must begin with a number or - (minus sign) or rather . (decimal point, for float values);
 +
* Integers allow only the decimal notation;
 +
* Floats disallow scientific notation and such;
 +
* Integral and fractional parts are singularly omissible;
 +
* F or f suffix can be appended next to (quite unused/useless).
  
===Compound assignment===
+
==Immediates and Variables==
 +
Data can take the appearance of a few expressions varying from numeric, text label and string literals each of which occupies a certain area of storage with unfixed size. Immediates can also be preserved for later use and therefore reserve space over the private script memory corresponding to a variable. The strongly-typed language property imposes to explicitly declare variables anywhere in the current scope, namely the context inside which they are visible for usage. Sensibly, declarations should figure beforehand but likewise it is allowed for accessing backward declarations. Variables accessible from any location are marked as globals (starting from offset 8, occupying lots of space in the script multifile, up to 64 kibibytes) and their declaration is achieved by prepending the '''VAR''' prefix followed by one of the basic data types (multiple declarations of the same type can be inlined), both separated by an in-between underscore:
  
''Compound assignment operators'' store [[#Value|values]] or [[#Variables|variable]] content to other variables having a particular type afterwards the computation of an arithmetic operation, to squeeze the code and clear it up from granted repetitions:
+
VAR_INT player scplayer
 +
VAR_FLOAT x_float, y_float, z_float
 +
VAR_TEXT_LABEL interior_name
 +
VAR_TEXT_LABEL16 shop_item
  
{|class=wikitable
+
Globals are capable of being selectively marked as saveable using the '''SAVE_VAR''' prefix, in order to restore their value on savegame loading and free generic variables. In Trilogy chapters, if enabled properly in a hacky manner, these are solely common variable declarations with no additional purpose, a plan not gone through. On the other hand, globals declared within the mission context are not visible outside in Stories chapters since they overlap the same space, making a discernment among true and al-most globals. However, there's no exact rule for variable naming apart they must begin with a letter and never end with a colon, just like text labels. It's preferable definitions shall not contain operator tokens to prevent any parsing ambiguity plus, most importantly, they must not conflict with string constants and local timers. Nevertheless, text labels and variable names semantics may collide: in this case, the formers have priority over the latters unless a preceding dollar sign) is added:
!width=70px|Operator
 
!width=225px|Name
 
!width=225px|Syntax
 
!width=550px|Description
 
|-
 
!+=
 
|align=center|Addition assignment
 
|align=center|<code>expr0 '''+=''' expr1</code>
 
|Add ''expr1'' to ''expr0'' and store the result to ''expr0''
 
|-
 
!-=
 
|align=center|Subtraction assignment
 
|align=center|<code>expr0 '''-=''' expr1</code>
 
|Subtract ''expr1'' from ''expr0'' and store the result to ''expr0''
 
|-
 
!*=
 
|align=center|Multiplication assignment
 
|align=center|<code>expr0 '''*=''' expr1</code>
 
|Multiply ''expr0'' by ''expr1'' and store the result to ''expr0''
 
|-
 
!/=
 
|align=center|Division assignment
 
|align=center|<code>expr0 '''/=''' expr1</code>
 
|Divide ''expr0'' by ''expr1'' and store the result to ''expr0''
 
|-
 
!+=@
 
|align=center|Timed addition assignment
 
|align=center|<code>expr0 '''+=@''' expr1</code>
 
|Multiply ''expr1'' by delta time, add the result to ''expr0'' and store everything to ''expr0''
 
|-
 
!-=@
 
|align=center|Timed subtraction assignment
 
|align=center|<code>expr0 '''-=@''' expr1</code>
 
|Multiply ''expr1'' by delta time, subtract the result from ''expr0'' and store everything to ''expr0''
 
|}
 
 
 
===Uncompounded assignment===
 
 
 
''Uncompounded assignment operators'' are those on their own, or rather they are neither derivable nor decomposable similarly as those [[#Compound assignment|compounds]]:
 
 
 
{|class=wikitable
 
!width=70px|Operator
 
!width=225px|Name
 
!width=225px|Syntax
 
!width=550px|Description
 
|-
 
!=#
 
|align=center|Cast assignment
 
|align=center|<code>expr0 '''=#''' expr1</code>
 
|Cast ''expr1'' to any other type and store the result to ''expr0''
 
|}
 
 
 
;Limit
 
:Supported conversions are [[#FLOAT|FLOAT]] to [[#INT|INT]] and '''INT''' to '''FLOAT'''.
 
 
 
===Logical===
 
 
 
''Logical operators'' influence the way conditions are evalueted and enable to test more of them at a time. More than anything, they are built-in statements:
 
 
 
{|class=wikitable
 
!width=70px|Operator
 
!width=225px|Name
 
!width=225px|Syntax
 
!width=550px|Description
 
|-
 
!NOT
 
|align=center|Logical negation
 
|align=center|<code>IF '''NOT''' condition0</code>
 
|Test if ''condition0'' is false
 
|-
 
!AND
 
|align=center|Logical conjunction
 
|align=center|<code>IF condition0<br/>'''AND''' condition8</code>
 
|Test if both ''condition0'' and ''conditionN'' are true
 
|-
 
!OR
 
|align=center|Logical disjunction
 
|align=center|<code>IF condition0<br/>'''OR''' condition8</code>
 
|Test if either ''condition0'' or ''conditionN'' is true
 
|}
 
  
===Comparison===
+
PRINT_BIG TEXTKEY 5000 2  // Compiles a text label literal.
 +
PRINT_BIG $textkey 5000 2 // Compiles a text label variable.
  
''Comparison operators'' test the truth or falsity of the relation between either a [[#Variables|variable]] and a [[#Value|value]], a value and a variable or two variables:
+
Despite variables are freed and zero-initialized at runtime on new/load game or script allocation in broad terms, statistical information are still gathered whenever they are read before being written, besides if they are never read or never written (passing a variable as reference has no effect onto the content). Furthermore, if a variable is set to hold an entity handle (alias unique index) returned by a specific create-command it cannot be assigned to any other entity-command of different kind or none, including the forseeable assignment operations. This restriction propagates on script and function callings as well: starting/streaming the same script or calling the same function multiple times with variables of dissimilar entity types is forbidden if triggers are encountered prior the script or function local scope is fetched, in which case entities are explicitly initialized in the form of unreachable code:
  
{|class=wikitable
 
!width=70px|Operator
 
!width=225px|Name
 
!width=225px|Syntax
 
!width=550px|Description
 
|-
 
!=
 
|align=center|Equal to
 
|align=center|<code>IF expr0 '''=''' expr1</code>
 
|Test if ''expr0'' and ''expr1'' are equal
 
|-
 
!>
 
|align=center|Greater than
 
|align=center|<code>IF expr0 '''>''' expr1</code>
 
|Test if ''expr0'' is greater than ''expr1''
 
|-
 
!<{{ref|inverr|[*]}}
 
|align=center|Lesser than
 
|align=center|<code>IF expr0 '''<''' expr1</code>
 
|Test if ''expr0'' is lesser than ''expr1''
 
|-
 
!>=
 
|align=center|Greater than or equal to
 
|align=center|<code>IF expr0 '''>=''' expr1</code>
 
|Test if ''expr0'' is greater than or equal to ''expr1''
 
|-
 
!<={{ref|inverr|[*]}}
 
|align=center|Lesser than or equal to
 
|align=center|<code>IF expr0 '''<=''' expr1</code>
 
|Test if ''expr0'' is lesser than or equal to ''expr1''
 
|}
 
 
;Note
 
:{{note|inverr}} As a result of a critical bug, R* compiler mistakenly applies the operator inversion.
 
 
==Commands==
 
 
A ''command'' is a ''symbolic name'' associated to an [[#Command ID|identifier]] which executes a ''portion of code'' that specifies the operation to be performed by passing ''zero or more arguments''. An ''argument'' is in turn some data given as input to a command. Normally, commands have a defined amount of arguments and those not, such as '''START_NEW_SCRIPT''', can pass as many arguments as the available [[#Local|local]] [[#Variables|variables]] are, except [[#Timers|timers]]. Being a procedure, a command does not return [[#Value|values]] that can be assigned to a variable, even though the boolean flag is kept whenever it is used as a ''condition''. It follows the common programming syntax adopted for ''function calls'':
 
 
{commandname} [{anyvalue0|varname0} ... {anyvalueN|varnameN}]
 
 
===Alternators===
 
 
An ''alternator'' is a set of alternative and akin commands chosen specifically during the compilation on the basis of the multiple implementations of the commands binded to the reference set, according to the different argument data types but NOT the [http://en.wikipedia.org/wiki/Arity arity]. The aforementioned sets are listed below:
 
 
* {{icon|t}} {{icon|lcs}} {{icon|vcs}}:
 
** '''SET (=)'''
 
** '''CSET (=#)'''
 
** '''ADD_THING_TO_THING (+=)'''
 
** '''SUB_THING_FROM_THING (-=)'''
 
** '''MULT_THING_BY_THING (*=)'''
 
** '''DIV_THING_BY_THING (/=)'''
 
** '''IS_THING_EQUAL_TO_THING (=)'''
 
** '''IS_THING_NOT_EQUAL_TO_THING (NOT =)'''
 
** '''IS_THING_GREATER_THAN_THING (>, <=)'''
 
** '''IS_THING_GREATER_OR_EQUAL_TO_THING (>=, <)'''
 
** '''ADD_THING_TO_THING_TIMED (+=@)'''
 
** '''SUB_THING_FROM_THING_TIMED (-=@)'''
 
** '''ABS'''
 
* {{icon|sa}}:
 
** '''IS_EMPTY'''
 
** '''IS_BIT_SET'''
 
** '''SET_BIT'''
 
** '''CLEAR_BIT'''
 
** '''STRING_CAT'''
 
 
{{incomplete}}
 
 
===Hardcoded===
 
 
''Hardcoded commands'' are those which have unique characteristics and are handled internally:
 
 
* {{icon|t}} {{icon|lcs}} {{icon|vcs}}:
 
** '''GOTO'''
 
** '''GOTO_IF_FALSE'''
 
** '''TERMINATE_THIS_SCRIPT'''
 
** '''START_NEW_SCRIPT'''
 
** '''VAR_INT'''
 
** '''VAR_FLOAT'''
 
** '''LVAR_INT'''
 
** '''LVAR_FLOAT'''
 
** '''{'''
 
** '''}'''
 
** '''REPEAT'''
 
** '''ENDREPEAT'''
 
** '''IF'''
 
** '''IFNOT'''
 
** '''ELSE'''
 
** '''ENDIF'''
 
** '''WHILE'''
 
** '''WHILENOT'''
 
** '''ENDWHILE'''
 
** '''ANDOR'''
 
** '''LAUNCH_MISSION'''
 
** '''SAVE_VAR_INT'''
 
** '''SAVE_VAR_FLOAT'''
 
** '''START_CUTSCENE'''{{ref|depcnt|[*]}}
 
** '''PLAYER_MADE_PROGRESS'''
 
** '''SET_PROGRESS_TOTAL'''{{ref|thgtot|[*]}}
 
** '''REGISTER_MISSION_GIVEN'''{{ref|depcnt|[*]}}
 
** '''REGISTER_MISSION_PASSED'''
 
** '''SCRIPT_NAME'''
 
** '''LOAD_AND_LAUNCH_MISSION'''
 
** '''LOAD_AND_LAUNCH_MISSION_INTERNAL'''
 
** '''SET_TOTAL_NUMBER_OF_MISSIONS'''{{ref|thgtot|[*]}}
 
** '''VAR_TEXT_LABEL'''
 
** '''LVAR_TEXT_LABEL'''
 
* {{icon|vc}} {{icon|sa}} {{icon|lcs}} {{icon|vcs}}:
 
** '''REGISTER_ODDJOB_MISSION_PASSED'''
 
* {{icon|3}} {{icon|lcs}} {{icon|vcs}}:
 
** '''GOTO_IF_TRUE'''
 
** '''GOSUB_FILE'''
 
* {{icon|3}} {{icon|vc}}:
 
** '''CREATE_COLLECTABLE1'''
 
** '''SET_COLLECTABLE1_TOTAL'''{{ref|thgtot|[*]}}
 
* {{icon|vc}} {{icon|sa}}:
 
** '''LOAD_AND_LAUNCH_MISSION_EXCLUSIVE'''
 
* {{icon|lcs}} {{icon|vcs}}:
 
** '''CALL'''
 
** '''CALLNOT'''
 
* {{icon|sa}}:
 
** '''VAR_TEXT_LABEL16'''
 
** '''LVAR_TEXT_LABEL16'''
 
** '''SWITCH'''
 
** '''ENDSWITCH'''
 
** '''CASE'''
 
** '''DEFAULT'''
 
** '''BREAK'''
 
** '''SWITCH_START'''
 
** '''SWITCH_CONTINUED'''
 
* {{icon|vcs}}:
 
** '''SAVE_VAR_TEXT_LABEL'''{{ref|thgtot|[*]}}
 
** '''SET_COLLECTABLE2_TOTAL'''
 
 
;Notes
 
:{{note|thgtot}} The argument of these commands must be set respectively according to:
 
:* The sum of '''PLAYER_MADE_PROGRESS''' values;
 
:* The amount of '''REGISTER_MISSION_PASSED''' (those that don't have an immediate value are excluded) and '''REGISTER_ODDJOB_MISSION_PASSED''';
 
:* The amount of '''CREATE_COLLECTABLE1'''.
 
:If the argument of the listed commands differs from what expected, a 0-value must be passed;
 
:{{note|depcnt}} This command was intended to be counted originally but its counter got deprecated.
 
 
{{incomplete}}
 
 
===WAIT===
 
 
'''WAIT''' stops the execution of a [[#Structure|script]] according to some milliseconds after which it will resume again. Indeed, it is absolutely necessary into ''infinite loops'' or those that may or may not break after more than one frame, such as the [[#WHILE|WHILE]] control flow. In this case, a [[#INT|INT]] equal to 0 is passed.
 
 
===GOTO===
 
 
'''GOTO''' jumps to the [[#Labels|label]] of any location of the source code but conceptually it should never point off the current context. It is also used internally to build the [[#Control flows|control flows]] offered by the scripting language:
 
 
// File: any.sc
 
 
goto_ref0:
 
GOTO goto_refN
 
 
// File: any.sc
 
 
goto_refN:
 
GOTO goto_ref0
 
 
===ANDOR===
 
 
'''ANDOR''' sets out the way the comparison among more conditions have to occur (see also [[#Compare flag|Compare flag]]).
 
 
===GOTO_IF_TRUE===
 
 
'''GOTO_IF_TRUE''' operates in conjunction with [[#ANDOR|ANDOR]] and jumps to a [[#Labels|label]] if the returned boolean flag is true.
 
 
===GOTO_IF_FALSE===
 
 
Unlike [[#GOTO_IF_TRUE|GOTO_IF_TRUE]], '''GOTO_IF_FALSE''' jumps to the desired [[#Labels|label]] only if the comparison returns false.
 
 
===SCRIPT_NAME===
 
 
'''SCRIPT_NAME''' simply associates an unique name to the current working [[#Structure|script]].
 
 
;Note
 
:R* compiler doesn't enable you to associate a name previously used for another script.
 
 
===SAVE_STRING_TO_DEBUG_FILE===
 
 
'''SAVE_STRING_TO_DEBUG_FILE''' accepts an argument which can admit up to ''127 characters plus the null-terminator''. In the compiling process, the argument is skipped but its string is copied to a predefined ''128-bytes buffer'', compiled afterwards. Since {{icon|vc}}, these are the seemingly predetermined bytes of a random empty string block which are actually the result of uninitialized data:
 
 
00 00 41 00 09 2E 00 00 00 00 00 00 '''00''' 00 00 00
 
09 2E 00 00 00 00 00 00 1C FB 12 00 D8 A8 41 00
 
00 00 41 00 09 2E 00 00 00 00 00 00 '''01''' 00 00 00
 
09 2E 00 00 00 00 00 00 1C FB 12 00 D8 A8 41 00
 
00 00 41 00 09 2E 00 00 00 00 00 00 '''02''' 00 00 00
 
09 2E 00 00 00 00 00 00 1C FB 12 00 D8 A8 41 00
 
00 00 41 00 09 2E 00 00 00 00 00 00 '''03''' 00 00 00
 
09 2E 00 00 00 00 00 00 1C FB 12 00 D8 A8 41 00
 
 
The split of such bytes into 4 blocks of 32-bytes each is quite noticeable.
 
 
==Constants==
 
 
A ''constant'' is a ''symbolic name'' associated to a specific [[#Value|value]]. When compiling, their caption is converted to the assigned value. Since {{icon|vc}}, names and identifiers of objects within [[OBJS]] and [[TOBJ]] blocks are loaded from every ''IDE'' file defined into [[gta.dat|gta_vc.dat]], then those of vehicles and pedestrians within [[PEDS]] and [[CARS]] blocks are retrieved from [[default.ide]]. In {{icon|sa}}, they are listed into ''TXT'' files, whose name follows the [[Wikipedia:CamelCase|Pascal Case]] (eg. ''AudioEvents.txt''). These files respect the syntax below:
 
 
{constname0} {constvalue0}
 
 
{constnameN} {constvalueN}
 
 
''Constant names and values'' are divided by as many ''spaces'' or ''tabulations'' as you want. ''Constant lines'' are distinguished by two '''\n''' (new line) characters. The ''model names'' which aren't assigned to a constant are still valid (see also [[#Identifiers|Identifiers]]). Keep in mind arguments of some [[#Commands|commands]] having the [[#CONST (pseudo)|CONST]] type accept only ''constant values'' of a single ''namespace''.
 
 
;Notes
 
:Constants don't collide even though they belong to different namespaces;
 
:In {{icon|3}} and {{icon|vc}}, they are hardcoded as everything inside R* compiler;
 
:In {{icon|sa}}, the subdivision of constant namespaces in files might be just a listing of hardcoded constants useful for developers. The same would apply to {{icon|lcs}} and {{icon|vcs}}.
 
 
==Formatting==
 
 
Everything is ''case-insensitive'', that means the uppercase and lowercase letters have no dissimilarities when taken. Usually, the source code is conform to the same formatting according to:
 
 
* [[#Labels|Labels]] and [[#Variables|variables]] are entirely in lowercase;
 
* [[#Declaration|Declarations]], [[#Commands|commands]] and [[#Control flows|control flows]] are in uppercase;
 
* [[#Constants|Constants]] are mostly in uppercase but the lowercase variant can be seen as well.<br/><br/>
 
=Compiling=
 
 
==Structure==
 
 
The source code is split up into several ''SC'' files which comprehend ''main file'', ''foreign gosubs'', ''subscripts'', ''mission scripts'', and ''streamed scripts''. These files can be included more times because they are actually processed once.
 
 
===Main file===
 
----
 
The ''main file'' is the most significant part of the whole source. It can include many script files and/or embedded ''gosubs'', ''scripts'' or ''functions''. Originally, it is characterized by the absence of the [[#Local|local]] [[#Scope|scope]]. It must be put outside the directory, having the same name as the main script file, where all other foreign scripts must be:
 
 
<directory>
 
| main
 
|  | gosub
 
|  |  |- gosub1.sc
 
|  |  \- gosubN.sc
 
|  | subscript
 
|  |  |- subscript1.sc
 
|  |  \- subscriptN.sc
 
|  | mission_guy
 
|  |  |- mission_guy1.sc
 
|  |  \- mission_guyN.sc
 
|  |- gosub.sc
 
|  |- subscript.sc
 
|  \- mission.sc
 
\- main.sc
 
 
;Note
 
:R* compiler will scan subfolders too.
 
 
===Foreign gosubs===
 
----
 
''Foreign gosubs'' (also called ''subroutines'') are ''main extension files''. They are called using the '''GOSUB_FILE''' [[#Commands|command]] which jumps to a specific [[#Labels|label]] and executes some code that returns back to the place where it has been called with '''RETURN'''. You are able to specify the gosub label to start jumping at as well:
 
 
// File: main.sc
 
 
GOSUB_FILE gosub_ref foreign_gosub.sc
 
 
// File: foreign_gosub.sc
 
 
gosub_ref:
 
 
  {
 
  {
     [...]
+
     LVAR_INT test_char sanity
}
 
RETURN
 
 
 
;Limit
 
:Foreign gosubs were introduced since {{icon|3}}. They were unused in {{icon|vc}} and got removed in {{icon|sa}}, but then they were reimplemented in {{icon|lcs}} and {{icon|vcs}}.
 
 
 
====Gosubs====
 
 
 
As mentioned, ''gosubs'' are also embedded in any script file. They follow almost the same rules, except they are called by '''GOSUB''' and can actually inehrit the [[#Local|local]] [[#Scope|scope]] of the parent script:
 
 
 
// File: any.sc
 
 
GOSUB gosub_ref
 
 
 
// File: any.sc
 
 
   
 
   
gosub_ref:
+
    sanity = 0
{
+
    IF sanity = -1
    [...]
+
        CREATE_CHAR PEDTYPE_CIVMALE male01 0.0 0.0 0.0 test_char
 +
    ENDIF
 
  }
 
  }
RETURN
 
  
;Note
+
==Local scope==
:R* compiler doesn't take care if the code within a scope jumps to a gosub inside which another scope is declared. It is strongly recommended to pay attention at this issue or you will fall down into an irreparable local [[#Variables|variable]] mismatch.
+
Once a script is started/streamed or a subscript/mission is launched, a local variable space of 72 (16+2 &times; 4, III/Vice City), 136 (32+2 &times; 4, San Andreas) or 424 (96+8+2 &times; 4, Stories) bytes is also reserved. As opposed to global variables, locals have visibility only inside a particular region of the source code and are preceded by the '''LVAR''' prefix at declaration within an unnestable block embraced by curly brackets:
  
===Subscripts===
 
----
 
''Subscripts'' are code blocks which take part of a ''queue of other scripts'' and are allocated over the memory by '''LAUNCH_MISSION'''. They are denoted by the presence of '''MISSION_START''' at the very top of the mission file. As long as they aren't ended with '''MISSION_END''', their execution never expires till the end of the game process. Each one works independently, even though they are able to share [[#Global|global]] [[#Variables|variables]]:
 
 
// File: main.sc
 
 
LAUNCH_MISSION subscript.sc
 
 
// File: subscript.sc
 
 
MISSION_START
 
 
[VAR_* {varname0}[,] [... {varnameN}]]
 
 
SCRIPT_NAME main
 
 
subscript_loop:
 
 
  {
 
  {
     [LVAR_* {varname0}[,] [... {varnameN}]]
+
     LVAR_INT pickup message_num
 
    [...]
 
 
  }
 
  }
//GOTO subscript_loop
 
MISSION_END
 
 
;Notes
 
:'''MISSION_START''' is a special and fake directive that isn't assigned to any [[#Commands|command]]. R* compiler will notify an error if it isn't placed at the first line of a subscript or a [[#Mission scripts|mission script]];
 
:'''MISSION_END''' is an alias of '''TERMINATE_THIS_SCRIPT'''.
 
  
====Scripts====
+
Local names do not override global definitions, they must not collide together otherwise a warn is issued. In the last Trilogy chapter, locals are mainly static variables whose space (having a size of 4096 bytes, 1024&times;4) is shared among each mission thus they are reasonably more abundant in this context. Beyond user-defined locals, predefined '''TIMERA''' and '''TIMERB''' variables are provided: these timers measures the playing time milliseconds passed since the script beginning but they can be reset just fine. As deducible, any script file inclusion within a local scope does inherit no local variable even for the unassuming foreign gosub.
  
As for [[#Gosubs|gosubs]], ''scripts'' can be embedded everywhere in a script file. They are started by '''START_NEW_SCRIPT''' which has an undefined amount of arguments, whose type must match with those of each [[#Local|local]] variable of the starting script in order to be passed, else the compilation will interrupt. Unlike subscripts, they get terminated by '''TERMINATE_THIS_SCRIPT''' or '''TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME''' (elsewhere in another script):
+
==Arrays==
 +
Since the last Trilogy chapter, instead of declaring multiple scalar variables of same type, an unidimensional, numeric (unassociative) array can be defined. Each element is accessed through either a positive, zero-based<sup>[no source]</sup>, 8-bit unsigned number or a variable index embraced by a pair of square brackets on assignment or argument passing. On declaration, the said brackets enclose the array size which mustn't be bigger than 255 units:
  
  // File: any.sc
+
  VAR_INT prop_assets[32]
+
  CREATE_FORSALE_PROPERTY_PICKUP -1969.27 282.47 34.6 50000 PROP_3 prop_assets[0]
  START_NEW_SCRIPT script [{anyvalue0|varname0} ... {anyvalueN|varnameN}]
 
  
// File: any.sc
+
In sooth, one-based arrays were already supported in the second Trilogy chapter but they missed the intrinsic data type, giving no reference point on how to interpret the compiled operands, producing corrupted intermediate code because of fall-through reading. There is no precedent to safely assert that arrays became zero-based later on the language evolution but what is certain is this sort of indexing lines up immediate with variable indices. Oddly, as a result of the unidimensionality constraint implementation, a complementary yet nonfactual identifier can follow the closing bracket immediately afterwards with no redundancy notice (i.e. <code>prop_assets[0]anything</code>). Moreover, scalar variables have an implicit array size of one element which is needlessly accessible and plus the index part of the first element of an array is in turn omissible, everything notwithstanding the misleading declaration. Granted that brackets do not encompass any separator character, array indices reject string constants but admit local timers.
 
script:
 
{
 
    SCRIPT_NAME script
 
 
script_loop:
 
 
    [LVAR_* {varname0}[,] [... {varnameN}]]
 
 
    [...]
 
 
    //GOTO script_loop
 
    TERMINATE_THIS_SCRIPT
 
}
 
  
;Notes
+
==String constants==
:Scripts must have a local [[#Scope|scope]];
+
Very often, numeric literals express arbitrary values which are far from being self-documenting without descriptive labels belonging to a list of predefined names. These strings or enumerations are guaranteed to store an immutable constant and must forcibly pertain to the required namespace if passed as arguments unless, if and only if no namespace is set, the default constants '''TRUE'''/'''FALSE''', '''ON'''/'''OFF''', '''DAY'''/'''NIGHT''' or '''KILLFRENZY''' statuses are supplied:
:Script commands must be inserted within or after the local scope;
 
:Since {{icon|vc}}, the ''opening curly bracket'' must be put before the script [[#Labels|label]] when more arguments are passed.
 
  
====Functions====
+
CHANGE_BLIP_DISPLAY blip1_jm1 BLIP_ONLY
 +
flag_car_blip_displayed_jm1 = TRUE
  
{{incomplete}}
+
Assignments and comparisons do not suffer such a restriction and, what's more, in case of too long lines (wider than 255 characters) immediates can safely replace string constants to shorten the exceeding length and fall within the limits. During the development stage, the game's map experiences lots of continuous changes that make the management of objects, as a result of having a fixed indexing, pretty awkward without taking into account their bulk amount. In this respect, parameters expecting level objects are able to define the used objects (no more longer than 23 characters) under the hood, bringing them together in a sorted array whose criteria depends on the order of their appearance, something other than the default models which are hardcoded (for peds, cars, weapons, wheels, cutscene objects and the like). A blank, unavailable object is always reserved, shifting ahead each next negated position becoming one-based. Negative indices assure models fit in the used objects array, according to which the runtime matches the right index through a lookup table:
  
===Mission scripts===
+
REQUEST_MODEL bridgefuka // First use ever. It compiles -1 from now on.
----
+
REQUEST_MODEL bridgefukb // First use again. This time it compiles -2.
''Mission scripts'' are those [[#Subscripts|subscripts]] which are responsible for the presence of a storyline in the game. When they are launched with '''LOAD_AND_LAUNCH_MISSION''', the mission is loaded in the mission block, allocated over the memory and the script pointer is moved to the corresponding mission [[#Offsets|offset]]. Do not forget to begin a mission script with '''MISSION_START''' and end it with '''MISSION_END''':
+
LOAD_ALL_MODELS_NOW
 +
CREATE_OBJECT_NO_OFFSET bridgefuka 715.746 -937.908 40.194 damagea
 +
CREATE_OBJECT_NO_OFFSET bridgefukb 787.835 -939.24 38.971 damageb
  
// File: main.sc
+
The lack of error-checking requires a meticulous handwriting to avoid script deadlocks at runtime, the reason why both default models and level objects are loaded straight from [[Item Definition|IDE]] files for Vice City's remastered build. Nonetheless, iterating among several objects can be very expensive for a poorly optimised, rough compiler even on fast machines, not to mention namespaced constants are likely to collide without specializing prefixes (i.e. '''SNIPER''' camera mode and weapon name, formerly '''WEAPON_SNIPER'''), enough to revert back thereafter. Assignments and comparisons have no clue about used objects and are therefore not designed to accommodate or implicitly define one on their own, because they are supposed to be strict with the identifier existence as being more prone to work out with variables. This concept somehow extends to those parameters not featuring used objects as a general rule. If an unusual application needs to take place, making use of non-inlined '''CONSTANT_INT''' declarations would hint the compiler to treat unequivocally the specified string constants as used objects, truly defining a new one on the first practical usage wherever it occurs and not yielding an undefined variable error:
 
LOAD_AND_LAUNCH_MISSION mission.sc
 
  
  // File: mission.sc
+
  CONSTANT_INT cj_pizza_1
   
+
  CONSTANT_INT cj_pizza_2
  MISSION_START
+
  VAR_INT test_model1 test_model2
 
GOSUB mission_start
 
 
IF HAS_DEATHARREST_BEEN_EXECUTED
 
    GOSUB mission_failed
 
ENDIF
 
 
GOSUB mission_cleanup
 
 
MISSION_END
 
 
[VAR_* {varname0}[,] [... {varnameN}]]
 
 
mission_start:
 
 
REGISTER_MISSION_GIVEN
 
SCRIPT_NAME mission
 
 
// Variables initialization
 
 
{
 
    [LVAR_* {varname0}[,] [... {varnameN}]]
 
 
    [...]
 
}
 
GOTO mission_passed
 
 
mission_failed:
 
[...]
 
RETURN
 
 
mission_passed:
 
REGISTER_MISSION_PASSED mission
 
//PLAYER_MADE_PROGRESS 1
 
[...]
 
RETURN
 
 
// Mark everything as no longer needed
 
 
   
 
   
  mission_cleanup:
+
  REQUEST_MODEL pizzahigh  // -1
  //MISSION_HAS_FINISHED
+
test_model1 = cj_pizza_1 // -2
  [...]
+
  test_model2 = cj_pizza_2 // -3
  RETURN
+
  REQUEST_MODEL test_model1
 +
  REQUEST_MODEL test_model2
  
Some missions doesn't need to be executed multiple times because they may just initialize some [[#Global|global]] [[#Variables|variables]] defined in the [[#Main file|main]] script or launch the intro mission. For this matter, here comes the usage of '''LOAD_AND_LAUNCH_MISSION_EXCLUSIVE''':
+
Any string constant passed in place of an object model compiles a used object indiscriminately assuming no '''CONSTANT_INT''' declaration, preventing redefinitions (whether default or namespaced), does exist. Messing around with frequent compiler tool recompilations can be tedious solely to establish broad, same-indexed or math-related string constants but fortunately, in the last Trilogy chapter, the language offers the opportunity to settle user-supplied default constants for numeric literals using '''CONST'''-prefixed declarations which, alike for variables and '''CONSTANT_INT'''s, are backward accessible:
  
  // File: main.sc
+
  CONST_INT gf_date_active 1
 +
CONST_FLOAT math_pi 3.1415927
 
   
 
   
  LOAD_AND_LAUNCH_MISSION_EXCLUSIVE initial.sc
+
  SET_BIT gf_date_flags gf_date_active
  LOAD_AND_LAUNCH_MISSION_EXCLUSIVE intro.sc
+
rad_angle = deg_angle * math_pi
 +
  rad_angle /= 180.0
  
;Note
+
Given that default models are also default constants in Stories chapters<sup>[no source]</sup>, default constants and used objects count as pseudoconstants: contrary to what namespaced constants entail, generic alternatives are favoured on assignment or comparison command pairing. It should be pointed out that, due to a critical compiler bug, the high 16 bits of the value held by a namespaced constant are unexpectedly discarded on assignment or comparison and that, if set, the 16th bit yields a nonexistent variable error (i.e. '''THREAT_GANG9''' flag) prior Stories chapters, where a default constant is compiled only if the low 16 bits represent a value lesser than -1<sup>[no source]</sup>:
:Exclusive missions are never launched in the source code. It's likely, it was an idea not came to the end successfully or rather they were useful for debugging purposes.
 
  
;Limits
+
{|style="table-layout: fixed; margin-bottom: -8px" width=100% cellspacing=0 cellpadding=0
:'''LOAD_AND_LAUNCH_MISSION_EXCLUSIVE''' is available only in {{icon|vc}} and {{icon|sa}};
+
|width=50%|'''Mission script'''
:Only 2 exclusive missions in {{icon|vc}} and 3 in {{icon|sa}} are handled, plus they must be launched before any of the counterpart.
+
|width=16px rowspan=2|
 +
|width=50%|'''Script multifile'''
 +
|-
 +
|<pre style="white-space: pre; overflow-x: scroll">
 +
SET_CHAR_THREAT_SEARCH test_char THREAT_GANG_GOLFER
 +
SET_CHAR_THREAT_SEARCH test_char THREAT_GANG9
 +
SET_CHAR_THREAT_SEARCH test_char THREAT_EMERGENCY
 +
threat_flag = THREAT_GANG_GOLFER
 +
threat_flag = THREAT_GANG9 // Ill-formed in Trilogy.
 +
threat_flag = THREAT_EMERGENCY
 +
</pre>
 +
|<pre style="white-space: pre; overflow-x: scroll">
 +
SET_CHAR_THREAT_SEARCH test_char 16384
 +
SET_CHAR_THREAT_SEARCH test_char 32768
 +
SET_CHAR_THREAT_SEARCH test_char 65536
 +
SET_VAR_INT_TO_CONSTANT threat_flag 16384
 +
SET_VAR_INT threat_flag 32768
 +
SET_VAR_INT_TO_CONSTANT threat_flag 0
 +
</pre>
 +
|}
  
===Streamed scripts===
+
This inconvenient unwittingly affects real code in Liberty City Stories in one circumstance. On a final note, string constants are incompatible with optional arguments and thus taking advantage of a temporary variable would overcome this syntactic limitation.
----
 
{{incomplete}}
 
  
==Control flows==
+
==Operators==
 +
As soon as a numeric or text label variable is declared, it can be subjected to algebric operations and/or logical comparisons by virtue of several operators. Their support is sadly very primitive, in fact the ability to establish complex expressions with parentheses and such is not featured albeit one and only binary operation is enabled to follow the basic assignment. In this regard, the variable being assigned to the lvalue cannot be the same as the outer rvalue for non-commutative operations: <code>VAR1 = THING - VAR1</code>, <code>VAR1 = THING / VAR1</code>, <code>VAR1 = THING +@ VAR1</code> and <code>VAR1 = THING -@ VAR1</code> are all ill-formed. This issue arises because the explicit usage of a temporary variable is needed which would be harmful for the compiler to waste by itself under the hood, thus here expressions are necessarily made up of distinct two-operand instructions, that is the lvalue content is initialized prior encoding any supplementary rvalue arithmetic:
  
As usual, the evolution of something implies its development over the years. Alongside, the ''control flows'' implementation has been distributed equally into every chapter. Their definitions are similar to those used in ''pseudocodes'' resulting in a ''raw source code''. However, you are still able to build your own control flows:
+
//VAR1 = 1 - VAR1 // Invalid, cause VAR1 = 1; VAR1 -= VAR1 doesn't make sense. It would perform 1 - 1 = 0.
 +
VAR1 = 1 - VAR2  // Valid, cause VAR1 = 1; VAR1 -= VAR2 doesn't null itself like above.
 +
VAR1 = 1 + VAR1  // Valid, addition (as well as multiplication) is commutative so this is compiled to VAR1 += 1.
  
ANDOR {value}
+
The subtraction of positive or negative rvalues necessitates a splitting character in order to discern the infix operator unambiguously, which would be treated as part of the literal or a variable decrement otherwise (i.e. <code>VAR1 = VAR1 -1</code> or <code>VAR1 = VAR1 --1</code>). Typically, string constants are not suitable for math calculations because of the lack of pairable command alternatives but even so they are semantically contemplated as long as a namespaced constant is provided as the inner rvalue of a compound assignment or a default constant is passed to any rvalue. Another clear limitation is prefix and postfix operators do not apply onto arguments, hence there's no concrete differentiation. However, the language introduces the timed addition/subtraction to looply update a variable in a frame-rate independent way, the cast assignment to do a mutual conversion between integers and floats but it doesn't give support for the modulo operation as its predecessor. The inequality comparison was planned but quickly gone obsolete<sup>[no source]</sup> &ndash; availing of the negated form of the equality operator would have sounded more intuitive but one should be aware the not-flag is not bundled with the command index when pairing command alternatives. Due to a programmers' negligence, the local-global in/equality comparison between integer or float variables is not feasible except in the last chapter of Trilogy and Stories series.
    [NOT] {condition0}
 
    [[NOT] {condition8}]
 
GOTO_IF_FALSE ELSE
 
    {consequence}
 
    [GOTO ENDIF]
 
ELSE:
 
    [{alternative}
 
ENDIF:]
 
  
;Note
+
<span style="display: block; margin: 1em 0; font-size: 1.17em; color: black">'''Arithmetic operators'''</span>
:It's likely, user-made control flows weren't intended to be usable because R* compiler cannot recognize an [[#Comparison|equal to]] rather than an [[#Arithmetic|assignment]] operator.
 
  
===IF===
+
{|class=wikitable
 
 
'''IF''' is one of the most widespread ''conditional statements'' which executes some codes by evaluating a boolean flag, the returning value of one or more conditions. According to the returning value, either the ''consequence'' or the ''alternative'' will be performed. The condition result can be inverted by appending the '''NOT''' [[#Logical|logical operator]] before. More conditions require the use of the remaining logical operators, they are '''AND''', when verifying if all conditions evaluate true, and '''OR''', while testing if just one is satisfied. The syntax below summarize the whole explanation:
 
 
 
IF [NOT] {condition0}
 
[AND|OR [NOT] {condition8}]
 
    {consequence}
 
[ELSE
 
    {alternative}]
 
ENDIF
 
 
 
;Limit
 
:More than ''8 conditions'' per statement aren't allowed.
 
 
 
===IFNOT===
 
 
 
'''IFNOT''' is a variation of the '''IF''' statement as already stated. As opposed to its closest relative, the conditions evaluetion is reversed, that is the ''consequence'' is perfomed when the boolean flag is false, else the ''alternative'' is executed:
 
 
 
IFNOT [NOT] {condition0}
 
[AND|OR [NOT] {condition8}]
 
    {consequence}
 
[ELSE
 
    {alternative}]
 
ENDIF
 
 
 
;Limit
 
:It is supported in {{icon|3}}, {{icon|lcs}} and {{icon|vcs}}.
 
 
 
===WHILE===
 
 
 
Alike '''IF''', '''WHILE''' is a conditional statement. The only difference consists in how it performs the ''consequence'', that is it ''loops'' every line of code built into if the boolean flag is true:
 
 
 
WHILE [NOT] {condition0}
 
[AND|OR [NOT] {condition8}]
 
    {consequence}
 
ENDWHILE
 
 
 
===WHILENOT===
 
 
 
'''WHILENOT''' acts seemingly like the '''WHILE''' statement, as all condition truths are inverted and therefore the ''consequence'' is performed over and over again until the boolean flag becomes true:
 
 
 
WHILENOT [NOT] {condition0}
 
[AND|OR [NOT] {condition8}]
 
    {consequence}
 
ENDWHILE
 
 
 
;Limit
 
:It is supported in {{icon|3}}, {{icon|lcs}} and {{icon|vcs}}.
 
 
 
===REPEAT===
 
 
 
Similar to the '''WHILE''' statement, '''REPEAT''' ''iterates'' the ''consequence'' repeatedly depending on a 0-value incremental [[#Variables|variable]] which rises till the times specified:
 
 
 
REPEAT {times} {varname}
 
    {consequence}
 
ENDREPEAT
 
 
 
;Limits
 
:It is supported since {{icon|vc}};
 
:The times must be positive;
 
:The code will be read at least once in any case.
 
 
 
===SWITCH===
 
 
 
Basically, '''SWITCH''' is a ''group of concatenated '''IF''' statements''. When a condition is false the next '''CASE''' statement gets performed, otherwise the ''consequence'' is executed till a '''BREAK''' occurs and so the code jumps to the end of the construct. If none of the cases is true, a '''DEFAULT''' clause may be carried out:
 
 
 
SWITCH {varname}
 
    CASE {value0}
 
        {consequence}
 
        BREAK
 
    [CASE {valueN}
 
        {consequence}
 
        BREAK]
 
    [DEFAULT
 
        {alternative}
 
        BREAK]
 
ENDSWITCH
 
 
 
;Limits
 
:It is supported since {{icon|sa}};
 
:'''CASE''' allows the use of [[#INT|INT]] and [[#CONST (pseudo)|CONST]] values only;
 
:In {{icon|sa}}, values must be sorted (R* compiler should do it implicitely);
 
:Every '''CASE''' including '''DEFAULT''' must end with a '''BREAK'''.<br/><br/>
 
=Decompiling=
 
 
 
==Structure==
 
 
 
 
 
 
==Identifiers==
 
 
 
''Undefined [[#Constants|constants]]'' of model identifiers, whose name refers to a [[DFF]] which is presumably archived into any of the [[IMG]]<nowiki>s</nowiki>, loaded by the game, are overwritten by a decrementing value in the order they get compiled. These ''model names'' are then put into the second segment of the ''SCM header''. Those of [[#Mission scripts|mission scripts]] and [[#Streamed scripts|streamed scripts]] respect the same rule except the fact they are turned into a zero-based growing identifier, while exclusive mission scripts are launched by a negative identifier resulting from the bits inversion (bitwise complement).
 
 
 
==Offsets==
 
 
 
An ''offset'' is a ''32-bit signed integer'' which points to a location of the script file. Those within the [[#Main file|main file]], [[#Foreign gosubs|foreign gosubs]] and [[#Subscripts|subscripts]] are ''absolute offsets'' that start from the beginning of the main script, while the ones inside [[#Mission scripts|mission scripts]] and [[#Streamed scripts|streamed scripts]] are ''relative and negative offsets'' starting from their beginning. The offset is related to [[#Global|global]] [[#Variables|variables]] as well, whose interval goes from ''8'' and ends to ''65532'' (''0xFFFC''), each one is aligned to the nearest 4 bytes.
 
 
 
==Variables range==
 
 
 
The following table shows the [[#Variables|variables]] range of the [[#Local|local]] [[#Scope|scope]] for each game version:
 
 
 
{|class=wikitable style=text-align:center
 
!Context
 
!width=50px|{{icon|3}}
 
!width=50px|{{icon|vc}}
 
!width=50px|{{icon|sa}}
 
!width=50px|{{icon|lcs}}
 
!width=50px|{{icon|vcs}}
 
|-
 
|align=left|[[#Foreign gosubs|Foreign gosub]]/[[#Gosubs|Gosub]]||0-15||0-15||n/a||0-95||0-95
 
|-
 
|align=left|[[#Subscripts|Subscript]]/[[#Scripts|Script]]||0-15||0-15||0-31||0-95||0-95
 
|-
 
|align=left|[[#Mission scripts|Mission script]]||0-15||0-15||0-1023||0-95||0-95
 
 
|-
 
|-
|align=left|[[#Streamed scripts|Streamed script]]||n/a||n/a||0-31||n/a||n/a
+
!colspan=2 width=192px style="text-align: left"|Name
 +
!width=148px|Syntax
 +
!width=112px|INT
 +
!width=112px|FLOAT
 +
!width=112px|TEXT_LABEL/16
 
|-
 
|-
|align=left|[[#Functions|Function]]||n/a||n/a||n/a||0-95||0-95
+
|colspan=2|Basic assignment||align=center|<pre style="margin: 0">VAR = THING</pre>||align=center|&#x2713;||align=center|&#x2713;||align=center|&#x2713;
 
|-
 
|-
!colspan=6|
+
|colspan=2|Addition||align=center|<pre style="margin: 0">THING + THING</pre>||align=center|&#x2713;||align=center|&#x2713;||
 
|-
 
|-
|align=left|[[#Timers|Timer]]||16-17||16-17||32-33||t0-t1||t0-t1
+
|colspan=2|Subtraction||align=center|<pre style="margin: 0">THING - THING</pre>||align=center|&#x2713;||align=center|&#x2713;||
|}
 
 
 
==Operators composition==
 
 
 
As far as you wouldn't know, SCM's [[#Operators|operators]] always take two operands to compute an operation. Their composition is listed below:
 
 
 
{|class=wikitable
 
!width=70px|Operator/s
 
!width=200px colspan=2|Name
 
!width=200px|Syntax
 
!width=180px|Composition
 
 
|-
 
|-
!rowspan=2|++
+
|colspan=2|Multiplication||align=center|<pre style="margin: 0">THING * THING</pre>||align=center|&#x2713;||align=center|&#x2713;||
|align=center rowspan=2|Increment
 
|align=center|Pre
 
|align=center|<code>'''++''' expr0</code>
 
|align=center rowspan=2|<code>expr0 '''+=''' 1</code>
 
 
|-
 
|-
|align=center|Post
+
|colspan=2|Division||align=center|<pre style="margin: 0">THING / THING</pre>||align=center|&#x2713;||align=center|&#x2713;||
|align=center|<code>expr0 '''++'''</code>
 
 
|-
 
|-
!rowspan=2|--
+
|colspan=2|Timed addition||align=center|<pre style="margin: 0">THING +@ THING</pre>||||align=center|&#x2713;||
|align=center rowspan=2|Decrement
 
|align=center|Pre
 
|align=center|<code>'''--''' expr0</code>
 
|align=center rowspan=2|<code>expr0 '''-=''' 1</code>
 
 
|-
 
|-
|align=center|Post
+
|colspan=2|Timed subtraction||align=center|<pre style="margin: 0">THING -@ THING</pre>||||align=center|&#x2713;||
|align=center|<code>expr0 '''--'''</code>
 
 
|-
 
|-
!= +
+
|rowspan=2|Increment||Prefix||align=center|<pre style="margin: 0">++ VAR</pre>||rowspan=2 align=center|&#x2713;||rowspan=2|
|align=center colspan=2|Addition and assignment
+
|rowspan=2|
|align=center|<code>expr0 '''=''' expr1 '''+''' expr2</code>
 
|align=center|<code>expr0 '''=''' expr1<br/>expr0 '''+=''' expr2</code>
 
 
|-
 
|-
!= -
+
|Postfix||align=center|<pre style="margin: 0">VAR ++</pre>
|align=center colspan=2|Subtraction and assignment
 
|align=center|<code>expr0 '''=''' expr1 '''-''' expr2</code>
 
|align=center|<code>expr0 '''=''' expr1<br/>expr0 '''-=''' expr2</code>
 
 
|-
 
|-
!= *
+
|rowspan=2|Decrement||Prefix||align=center|<pre style="margin: 0">-- VAR</pre>||rowspan=2 align=center|&#x2713;||rowspan=2|
|align=center colspan=2|Multiplication and assignment
+
|rowspan=2|
|align=center|<code>expr0 '''=''' expr1 '''*''' expr2</code>
 
|align=center|<code>expr0 '''=''' expr1<br/>expr0 '''*=''' expr2</code>
 
 
|-
 
|-
!= /
+
|Postfix||align=center|<pre style="margin: 0">VAR --</pre>
|align=center colspan=2|Division and assignment
 
|align=center|<code>expr0 '''=''' expr1 '''/''' expr2</code>
 
|align=center|<code>expr0 '''=''' expr1<br/>expr0 '''/=''' expr2</code>
 
|-
 
!= +@
 
|align=center colspan=2|Timed addition and assignment
 
|align=center|<code>expr0 '''=''' expr1 '''+@''' expr2</code>
 
|align=center|<code>expr0 '''=''' expr1<br/>expr0 '''+=@''' expr2</code>
 
|-
 
!= -@
 
|align=center colspan=2|Timed subtraction and assignment
 
|align=center|<code>expr0 '''=''' expr1 '''-@''' expr2</code>
 
|align=center|<code>expr0 '''=''' expr1<br/>expr0 '''-=@''' expr2</code>
 
 
|}
 
|}
  
==Command ID==
+
<span style="display: block; margin: 1em 0; font-size: 1.17em; color: black">'''Compound assignment operators'''</span>
  
A ''command ID'' is a ''16-bit signed integer'' internal and progressive identifier, somehow referred to as part of the hexadecimal representation of an [http://en.wikipedia.org/wiki/Opcode opcode], which identifies the command to execute at runtime, forming the game's script [http://en.wikipedia.org/wiki/Bytecode bytecode]. The maximum number of available commands is ''32767'' (''0x7FFF''), since the least significant bit (''0x8000'') is set whenever they are used as ''negative conditions'' (those with the '''NOT''' [[#Logical|logical operator]], just to clear things up).
+
{|class=wikitable
 
 
==Command arguments==
 
 
 
The limitation of the amount of arguments a [http://en.wikipedia.org/wiki/Variadic_function variadic] command can pass is game specific:
 
 
 
* 16 for {{icon|3}} and {{icon|vc}};
 
* 32 for {{icon|sa}};
 
* 96 for {{icon|lcs}} and {{icon|vcs}}.
 
 
 
==Managed commands==
 
 
 
Here is the list of all managed [[#Commands|commands]] and their relative specifications:
 
 
 
'''Legend:'''
 
 
 
* '''Prefix:'''
 
** V, [[#Global|VAR]];
 
** L, [[#Local|LVAR]];
 
** A, ANY ([[#Value|VALUE]], VAR, LVAR).
 
 
 
* '''Specifier:'''
 
** R, [[#LABEL|LABEL]];
 
** I, [[#INT|INT]];
 
** F, [[#FLOAT|FLOAT]];
 
** T, [[#TEXT_LABEL|TEXT_LABEL]];
 
** T16, [[#TEXT_LABEL16|TEXT_LABEL16]];
 
** T32, [[#TEXT_LABEL32|TEXT_LABEL32]];
 
** T[N], [[#TEXT|TEXT]];
 
** C, [[#CONST (pseudo)|CONST]];
 
** M, [[#MULTI (pseudo)|MULTI]].
 
 
 
* '''Suffix:'''
 
** O, OPTIONAL.
 
 
 
'''List:'''
 
 
 
Be aware, the argument data types of the commands below are just informative:
 
 
 
<div width=100% style="overflow: auto; margin: -8px auto 8px">
 
{|class="wikitable collapsible collapsed" style=text-align:center
 
 
|-
 
|-
!rowspan=3 colspan=2|Command
+
!width=192px style="text-align: left"|Name
!rowspan=3|ID
+
!width=148px|Syntax
!colspan=9|Arguments
+
!Meaning
 +
!width=112px|INT
 +
!width=112px|FLOAT
 
|-
 
|-
!width=45px rowspan=2|#
+
|Addition assignment||align=center|<pre style="margin: 0">VAR += THING</pre>||align=center|<pre style="margin: 0">VAR1 = VAR1 + THING</pre>||align=center|&#x2713;||align=center|&#x2713;
!width=45px rowspan=2|1
 
!width=45px rowspan=2|2
 
!width=45px rowspan=2|3
 
!width=45px rowspan=2|4
 
!width=45px rowspan=2|...
 
!width=45px rowspan=2|18
 
!width=45px rowspan=2|...
 
!width=45px|n+l
 
 
|-
 
|-
!n+i+o
+
|Subtraction assignment||align=center|<pre style="margin: 0">VAR -= THING</pre>||align=center|<pre style="margin: 0">VAR1 = VAR1 - THING</pre>||align=center|&#x2713;||align=center|&#x2713;
 
|-
 
|-
|colspan=12|{{icon|t}} {{icon|lcs}} {{icon|vcs}}
+
|Multiplication assignment||align=center|<pre style="margin: 0">VAR *= THING</pre>||align=center|<pre style="margin: 0">VAR1 = VAR1 * THING</pre>||align=center|&#x2713;||align=center|&#x2713;
 
|-
 
|-
!colspan=2|MISSION_START{{ref|misdef|[*]}}
+
|Division assignment||align=center|<pre style="margin: 0">VAR /= THING</pre>||align=center|<pre style="margin: 0">VAR1 = VAR1 / THING</pre>||align=center|&#x2713;||align=center|&#x2713;
|
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|GOTO{{ref|statem|[*]}}
+
|Timed addition assignment||align=center|<pre style="margin: 0">VAR +=@ THING</pre>||align=center|<pre style="margin: 0">VAR1 = VAR1 +@ THING</pre>||align=center|&nbsp;||align=center|&#x2713;
|[[0002|2]]
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
|colspan=12|{{icon|t}} {{icon|lcs}}
+
|Timed subtraction assignment||align=center|<pre style="margin: 0">VAR -=@ THING</pre>||align=center|<pre style="margin: 0">VAR1 = VAR1 -@ THING</pre>||||align=center|&#x2713;
 
|-
 
|-
!rowspan=12|=<br/>SET!!SET_VAR_INT
+
|Cast assignment||align=center|<pre style="margin: 0">VAR =# THING</pre>||align=center|AS IS||align=center|&#x2713;||align=center|&#x2713;
|[[0004|4]]
+
|}
!rowspan=12|2
+
 
|VI||I||colspan=6|
+
<span style="display: block; margin: 1em 0; font-size: 1.17em; color: black">'''Comparison operators/relational operators'''</span>
 +
 
 +
{|class=wikitable
 
|-
 
|-
!SET_VAR_FLOAT
+
!width=192px style="text-align: left"|Name
|[[0005|5]]||VF||F||colspan=6|
+
!width=148px|Syntax
 +
!width=112px|INT
 +
!width=112px|FLOAT
 +
!width=112px|TEXT_LABEL/16
 
|-
 
|-
!SET_LVAR_INT
+
|Equal to||align=center|<pre style="margin: 0">VAR = THING</pre>||align=center|&#x2713;||align=center|&#x2713;||align=center|&#x2713;
|[[0006|6]]||LI||I||colspan=6|
 
 
|-
 
|-
!SET_LVAR_FLOAT
+
|Not equal to||align=center|<pre style="margin: 0">VAR <> THING</pre>||align=center|&#x2713;||align=center|&#x2713;||
|[[0007|7]]||LF||F||colspan=6|
 
 
|-
 
|-
!SET_VAR_INT_TO_VAR_INT
+
|Greater than||align=center|<pre style="margin: 0">THING > THING</pre>||align=center|&#x2713;||align=center|&#x2713;||
|[[0084|132]]||VI||VI||colspan=6|
 
 
|-
 
|-
!SET_LVAR_INT_TO_LVAR_INT
+
|Less than||align=center|<pre style="margin: 0">THING < THING</pre>||align=center|&#x2713;||align=center|&#x2713;||
|[[0085|133]]||LI||LI||colspan=6|
 
 
|-
 
|-
!SET_VAR_FLOAT_TO_VAR_FLOAT
+
|Greater than or equal to||align=center|<pre style="margin: 0">THING >= THING</pre>||align=center|&#x2713;||align=center|&#x2713;||
|[[0086|134]]||VF||VF||colspan=6|
 
 
|-
 
|-
!SET_LVAR_FLOAT_TO_LVAR_FLOAT
+
|Less than or equal to||align=center|<pre style="margin: 0">THING <= THING</pre>||align=center|&#x2713;||align=center|&#x2713;||
|[[0087|135]]||LF||LF||colspan=6|
+
|}
 +
 
 +
<span style="display: block; margin: 1em 0; font-size: 1.17em; color: black">'''Logical operators'''</span>
 +
 
 +
{|class=wikitable
 
|-
 
|-
!SET_VAR_FLOAT_TO_LVAR_FLOAT
+
!width=192px style="text-align: left"|Name
|[[0088|136]]||VF||LF||colspan=6|
+
!width=148px|Syntax
 
|-
 
|-
!SET_LVAR_FLOAT_TO_VAR_FLOAT
+
|Logical negation||align=center|<pre style="margin: 0">NOT</pre>
|[[0089|137]]||LF||VF||colspan=6|
 
 
|-
 
|-
!SET_VAR_INT_TO_LVAR_INT
+
|Logical conjunction||align=center|<pre style="margin: 0">AND</pre>
|[[008A|138]]||VI||LI||colspan=6|
 
 
|-
 
|-
!SET_LVAR_INT_TO_VAR_INT
+
|Logical disjunction||align=center|<pre style="margin: 0">OR</pre>
|[[008B|139]]||LI||VI||colspan=6|
+
|}
 +
 
 +
==Commands==
 +
The [[Wikipedia:Imperative programming|imperative programming]] paradigm provides for a conglomerate of commands the script is filled up of and structured in, which are seen as orders to instruct the execution of the relative built-in portion of game code at runtime. Their invocation is faithful to [[Wikipedia:Functional programming|procedure]] calls: they may feature zero or more parameters of any type or indefinite, depending on whether or not qualified as optional, and receive as much as arguments either by-value or by-reference affecting the read/written access accordingly (do note a pure reference does not initialize anything). Alike procedures, no assignable result is returned but a boolean state is catched anyway on conditional evaluation. One major peculiarity is command names are usually identified by a verb in its imperative form:
 +
 
 +
GIVE_WEAPON_TO_CHAR mafia_1X WEAPONTYPE_UZI 999
 +
 
 +
Historically, complex commands stand out over the simple counterpart in the way they are implemented compiler-wise:
 +
 
 +
* Variable and local scope declarators are true, non-compilable commands;
 +
* File includers assemble multiple files in a single source and require the rightmost argument to be a filename if inside the main script or main extension, otherwise '''START_NEW_SCRIPT''' is expected (this behaviour is originally buggy);
 +
* Script starters/streamers and function callers involve a type-checking of the optional parameters passed basing on the variables declared in the local scope, whose opening brace must precede the script label reference even few lines earlier since the second Trilogy chapter (the first one needs it right after instead but it's likely it is merely due to good style programming);
 +
* '''SCRIPT_NAME''' defines an univocal script name immune to redefinitions but not among mission scripts because they can only run one at a time;
 +
* '''SKIP_CUTSCENE_START''' and '''SKIP_CUTSCENE_END''' mark a specific region of code (mostly inside mission scripts). Several blocks cannot be nested together;
 +
* Dynamic counters expect one argument to be a zero-value which gets updated automatically/internally on compilation, keeping track of the times few commands are used (unless, if applicable, the only acceptable argument is a variable, then the command is not taken into account) or the total sum of the first argument values (of course, non-immediates are discarded):
 +
 
 +
:{|class=wikitable style="text-align: left"
 
|-
 
|-
!rowspan=12|+=<br/>+<br/>ADD_THING_TO_THING!!ADD_VAL_TO_INT_VAR
+
!Initializer
|[[0008|8]]
+
!Dependency/ies
!rowspan=12|2
+
!width=50px|Check<br/>arg.
|VI||I||colspan=6|
+
!width=50px|Is<br/>addend
 
|-
 
|-
!ADD_VAL_TO_FLOAT_VAR
+
|'''SET_COLLECTABLE1_TOTAL'''||'''CREATE_COLLECTABLE1'''||||
|[[0009|9]]||VF||F||colspan=6|
 
 
|-
 
|-
!ADD_VAL_TO_INT_LVAR
+
|'''SET_PROGRESS_TOTAL'''||'''PLAYER_MADE_PROGRESS'''||align=center|&#x2713;||align=center|&#x2713;
|[[000A|10]]||LI||I||colspan=6|
 
 
|-
 
|-
!ADD_VAL_TO_FLOAT_LVAR
+
|rowspan=2|'''SET_TOTAL_NUMBER_OF_MISSIONS'''||'''REGISTER_MISSION_PASSED'''||align=center|&#x2713;||
|[[000B|11]]||LF||F||colspan=6|
 
 
|-
 
|-
!ADD_INT_VAR_TO_INT_VAR
+
|'''REGISTER_ODDJOB_MISSION_PASSED'''||||
|[[0058|88]]||VI||VI||colspan=6|
 
 
|-
 
|-
!ADD_FLOAT_VAR_TO_FLOAT_VAR
+
|'''SET_MISSION_RESPECT_TOTAL'''||'''AWARD_PLAYER_MISSION_RESPECT'''||align=center|&#x2713;||align=center|&#x2713;
|[[0059|89]]||VF||VF||colspan=6|
+
|}
|-
+
 
!ADD_INT_LVAR_TO_INT_LVAR
+
A third category consisting of special commands or command pairs, is able to look for the matching signature into a list of akin commands on the basis of the data type of the passed arguments and choose, accordingly, the equivalent alternative in a direct and effortless way. Although the alternative commands are also accessible by and can share the same definition, the selection process is not entirely conform to [[Wikipedia:Function overloading|function overloading]] because these still maintain their own unique name, they are just smartly resolved through common aliases. The complete lists are reported below:
|[[005A|90]]||LI||LI||colspan=6|
 
|-
 
!ADD_FLOAT_LVAR_TO_FLOAT_LVAR
 
|[[005B|91]]||LF||LF||colspan=6|
 
|-
 
!ADD_INT_VAR_TO_INT_LVAR
 
|[[005C|92]]||LI||VI||colspan=6|
 
|-
 
!ADD_FLOAT_VAR_TO_FLOAT_LVAR
 
|[[005D|93]]||LF||VF||colspan=6|
 
|-
 
!ADD_INT_LVAR_TO_INT_VAR
 
|[[005E|94]]||VI||LI||colspan=6|
 
|-
 
!ADD_FLOAT_LVAR_TO_FLOAT_VAR
 
|[[005F|95]]||VF||LF||colspan=6|
 
|-
 
!rowspan=12|-=<br/>-<br/>SUB_THING_FROM_THING!!SUB_VAL_FROM_INT_VAR
 
|[[000C|12]]
 
!rowspan=12|2
 
|VI||I||colspan=6|
 
|-
 
!SUB_VAL_FROM_FLOAT_VAR
 
|[[000D|13]]||VF||F||colspan=6|
 
|-
 
!SUB_VAL_FROM_INT_LVAR
 
|[[000E|14]]||LI||I||colspan=6|
 
|-
 
!SUB_VAL_FROM_FLOAT_LVAR
 
|[[000F|15]]||LF||F||colspan=6|
 
|-
 
!SUB_INT_VAR_FROM_INT_VAR
 
|[[0060|96]]||VI||VI||colspan=6|
 
|-
 
!SUB_FLOAT_VAR_FROM_FLOAT_VAR
 
|[[0061|97]]||VF||VF||colspan=6|
 
|-
 
!SUB_INT_LVAR_FROM_INT_LVAR
 
|[[0062|98]]||LI||LI||colspan=6|
 
|-
 
!SUB_FLOAT_LVAR_FROM_FLOAT_LVAR
 
|[[0063|99]]||LF||LF||colspan=6|
 
|-
 
!SUB_INT_VAR_FROM_INT_LVAR
 
|[[0064|100]]||LI||VI||colspan=6|
 
|-
 
!SUB_FLOAT_VAR_FROM_FLOAT_LVAR
 
|[[0065|101]]||LF||VF||colspan=6|
 
|-
 
!SUB_INT_LVAR_FROM_INT_VAR
 
|[[0066|102]]||VI||LI||colspan=6|
 
|-
 
!SUB_FLOAT_LVAR_FROM_FLOAT_VAR
 
|[[0067|103]]||VF||LF||colspan=6|
 
|-
 
!rowspan=12|*=<br/>*<br/>MULT_THING_BY_THING!!MULT_INT_VAR_BY_VAL
 
|[[0010|16]]
 
!rowspan=12|2
 
|VI||I||colspan=6|
 
|-
 
!MULT_FLOAT_VAR_BY_VAL
 
|[[0011|17]]||VF||F||colspan=6|
 
|-
 
!MULT_INT_LVAR_BY_VAL
 
|[[0012|18]]||LI||I||colspan=6|
 
|-
 
!MULT_FLOAT_LVAR_BY_VAL
 
|[[0013|19]]||LF||F||colspan=6|
 
|-
 
!MULT_INT_VAR_BY_INT_VAR
 
|[[0068|104]]||VI||VI||colspan=6|
 
|-
 
!MULT_FLOAT_VAR_BY_FLOAT_VAR
 
|[[0069|105]]||VF||VF||colspan=6|
 
|-
 
!MULT_INT_LVAR_BY_INT_LVAR
 
|[[006A|106]]||LI||LI||colspan=6|
 
|-
 
!MULT_FLOAT_LVAR_BY_FLOAT_LVAR
 
|[[006B|107]]||LF||LF||colspan=6|
 
|-
 
!MULT_INT_VAR_BY_INT_LVAR
 
|[[006C|108]]||VI||LI||colspan=6|
 
|-
 
!MULT_FLOAT_VAR_BY_FLOAT_LVAR
 
|[[006D|109]]||VF||LF||colspan=6|
 
|-
 
!MULT_INT_LVAR_BY_INT_VAR
 
|[[006E|110]]||LI||VI||colspan=6|
 
|-
 
!MULT_FLOAT_LVAR_BY_FLOAT_VAR
 
|[[006F|111]]||LF||VF||colspan=6|
 
|-
 
!rowspan=12|/=<br/>/<br/>DIV_THING_BY_THING!!DIV_INT_BY_VAL
 
|[[0014|20]]
 
!rowspan=12|2
 
|VI||I||colspan=6|
 
|-
 
!DIV_FLOAT_VAR_BY_VAL
 
|[[0015|21]]||VF||F||colspan=6|
 
|-
 
!DIV_INT_LVAR_BY_VAL
 
|[[0016|22]]||LI||I||colspan=6|
 
|-
 
!DIV_FLOAT_LVAR_BY_VAL
 
|[[0017|23]]||LF||F||colspan=6|
 
|-
 
!DIV_INT_VAR_BY_INT_VAR
 
|[[0070|112]]||VI||VI||colspan=6|
 
|-
 
!DIV_FLOAT_VAR_BY_FLOAT_VAR
 
|[[0071|113]]||VF||VF||colspan=6|
 
|-
 
!DIV_INT_LVAR_BY_INT_LVAR
 
|[[0072|114]]||LI||LI||colspan=6|
 
|-
 
!DIV_FLOAT_LVAR_BY_FLOAT_LVAR
 
|[[0073|115]]||LF||LF||colspan=6|
 
|-
 
!DIV_INT_VAR_BY_INT_LVAR
 
|[[0074|116]]||VI||LI||colspan=6|
 
|-
 
!DIV_FLOAT_VAR_BY_FLOAT_LVAR
 
|[[0075|117]]||VF||LF||colspan=6|
 
|-
 
!DIV_INT_LVAR_BY_INT_VAR
 
|[[0076|118]]||LI||VI||colspan=6|
 
|-
 
!DIV_FLOAT_LVAR_BY_FLOAT_VAR
 
|[[0077|119]]||LF||VF||colspan=6|
 
|-
 
!rowspan=16|><br/><=<br/>IS_THING_GREATER_THAN_THING!!IS_INT_VAR_GREATER_THAN_NUMBER
 
|[[0018|24]]
 
!rowspan=16|2
 
|VI||I||colspan=6|
 
|-
 
!IS_INT_LVAR_GREATER_THAN_NUMBER
 
|[[0019|25]]||LI||I||colspan=6|
 
|-
 
!IS_NUMBER_GREATER_THAN_INT_VAR
 
|[[001A|26]]||I||VI||colspan=6|
 
|-
 
!IS_NUMBER_GREATER_THAN_INT_LVAR
 
|[[001B|27]]||I||LI||colspan=6|
 
|-
 
!IS_INT_VAR_GREATER_THAN_INT_VAR
 
|[[001C|28]]||VI||VI||colspan=6|
 
|-
 
!IS_INT_LVAR_GREATER_THAN_INT_LVAR
 
|[[001D|29]]||LI||LI||colspan=6|
 
|-
 
!IS_INT_VAR_GREATER_THAN_INT_LVAR
 
|[[001E|30]]||VI||LI||colspan=6|
 
|-
 
!IS_INT_LVAR_GREATER_THAN_INT_VAR
 
|[[001F|31]]||LI||VI||colspan=6|
 
|-
 
!IS_FLOAT_VAR_GREATER_THAN_NUMBER
 
|[[0020|32]]||VF||F||colspan=6|
 
|-
 
!IS_FLOAT_LVAR_GREATER_THAN_NUMBER
 
|[[0021|33]]||LF||F||colspan=6|
 
|-
 
!IS_NUMBER_GREATER_THAN_FLOAT_VAR
 
|[[0022|34]]||F||VF||colspan=6|
 
|-
 
!IS_NUMBER_GREATER_THAN_FLOAT_LVAR
 
|[[0023|35]]||F||LF||colspan=6|
 
|-
 
!IS_FLOAT_VAR_GREATER_THAN_FLOAT_VAR
 
|[[0024|36]]||VF||VF||colspan=6|
 
|-
 
!IS_FLOAT_LVAR_GREATER_THAN_FLOAT_LVAR
 
|[[0025|37]]||LF||LF||colspan=6|
 
|-
 
!IS_FLOAT_VAR_GREATER_THAN_FLOAT_LVAR
 
|[[0026|38]]||VF||LF||colspan=6|
 
|-
 
!IS_FLOAT_LVAR_GREATER_THAN_FLOAT_VAR
 
|[[0027|39]]||LF||VF||colspan=6|
 
|-
 
!rowspan=16|>=<br/><<br/>IS_THING_GREATER_OR_EQUAL_TO_THING!!IS_INT_VAR_GREATER_OR_EQUAL_TO_NUMBER
 
|[[0028|40]]
 
!rowspan=16|2
 
|VI||I||colspan=6|
 
|-
 
!IS_INT_LVAR_GREATER_OR_EQUAL_TO_NUMBER
 
|[[0029|41]]||LI||I||colspan=6|
 
|-
 
!IS_NUMBER_GREATER_OR_EQUAL_TO_INT_VAR
 
|[[002A|42]]||I||VI||colspan=6|
 
|-
 
!IS_NUMBER_GREATER_OR_EQUAL_TO_INT_LVAR
 
|[[002B|43]]||I||LI||colspan=6|
 
|-
 
!IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_VAR
 
|[[002C|44]]||VI||VI||colspan=6|
 
|-
 
!IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_LVAR
 
|[[002D|45]]||LI||LI||colspan=6|
 
|-
 
!IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_LVAR
 
|[[002E|46]]||VI||LI||colspan=6|
 
|-
 
!IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_VAR
 
|[[002F|47]]||LI||VI||colspan=6|
 
|-
 
!IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_NUMBER
 
|[[0030|48]]||VF||F||colspan=6|
 
|-
 
!IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_NUMBER
 
|[[0031|49]]||LF||F||colspan=6|
 
|-
 
!IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_VAR
 
|[[0032|50]]||F||VF||colspan=6|
 
|-
 
!IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_LVAR
 
|[[0033|51]]||F||LF||colspan=6|
 
|-
 
!IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_VAR
 
|[[0034|52]]||VF||VF||colspan=6|
 
|-
 
!IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR
 
|[[0035|53]]||LF||LF||colspan=6|
 
|-
 
!IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR
 
|[[0036|54]]||VF||LF||colspan=6|
 
|-
 
!IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_VAR
 
|[[0037|55]]||LF||VF||colspan=6|
 
|-
 
!rowspan=10|=<br/>IS_THING_EQUAL_TO_THING!!IS_INT_VAR_EQUAL_TO_NUMBER
 
|[[0038|56]]
 
!rowspan=10|2
 
|VI||I||colspan=6|
 
|-
 
!IS_INT_LVAR_EQUAL_TO_NUMBER
 
|[[0039|57]]||LI||I||colspan=6|
 
|-
 
!IS_INT_VAR_EQUAL_TO_INT_VAR
 
|[[003A|58]]||VI||VI||colspan=6|
 
|-
 
!IS_INT_LVAR_EQUAL_TO_INT_LVAR
 
|[[003B|59]]||LI||LI||colspan=6|
 
|-
 
!IS_INT_VAR_EQUAL_TO_INT_LVAR
 
|[[003C|60]]||VI||LI||colspan=6|
 
|-
 
!IS_FLOAT_VAR_EQUAL_TO_NUMBER
 
|[[0042|66]]||VF||F||colspan=6|
 
|-
 
!IS_FLOAT_LVAR_EQUAL_TO_NUMBER
 
|[[0043|67]]||LF||F||colspan=6|
 
|-
 
!IS_FLOAT_VAR_EQUAL_TO_FLOAT_VAR
 
|[[0044|68]]||VF||VF||colspan=6|
 
|-
 
!IS_FLOAT_LVAR_EQUAL_TO_FLOAT_LVAR
 
|[[0045|69]]||LF||LF||colspan=6|
 
|-
 
!IS_FLOAT_VAR_EQUAL_TO_FLOAT_LVAR
 
|[[0046|70]]||VF||LF||colspan=6|
 
|-
 
!rowspan=10|NOT =<br/>IS_THING_NOT_EQUAL_TO_THING!!IS_INT_VAR_NOT_EQUAL_TO_NUMBER
 
|[[003D|61]]
 
!rowspan=10|2
 
|VI||I||colspan=6|
 
|-
 
!IS_INT_LVAR_NOT_EQUAL_TO_NUMBER
 
|[[003E|62]]||LI||I||colspan=6|
 
|-
 
!IS_INT_VAR_NOT_EQUAL_TO_INT_VAR
 
|[[003F|63]]||VI||VI||colspan=6|
 
  
 +
{|width=100% cellspacing=0 cellpadding=0
 
|-
 
|-
!IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR
+
|width=50%|<span style="display: block; margin: 0; font-size: 1.17em; color: black">'''Trilogy and first Stories chapters'''</span>||width=50%|<span style="display: block; margin: 0; font-size: 1.17em; color: black">'''Second Stories chapter'''</span>
|[[0040|64]]||LI||LI||colspan=6|
 
 
|-
 
|-
!IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR
+
|valign=top|<div style="overflow: auto; float: left" width=auto>
|[[0041|65]]||VI||LI||colspan=6|
+
{|class="wikitable" style="margin-bottom: 0" width=100%
 
|-
 
|-
!IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER
+
!colspan=2 style="text-align: left"|Command
|[[0047|71]]||VF||F||colspan=6|
+
!rowspan=2 width=64px|Game<br/>support
 
|-
 
|-
!IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER
+
|width=20px|
|[[0048|72]]||LF||F||colspan=6|
+
!style="text-align: left"|Alternative
 +
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR
+
!colspan=2 style="background-color: inherit; text-align: left"|SET (<code>=</code>)
|[[0049|73]]||VF||VF||colspan=6|
+
|width=64px align=center|Since {{icon|3}}
 
|-
 
|-
!IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR
+
|rowspan=18 width=20px|
|[[004A|74]]||LF||LF||colspan=6|
+
|'''SET_VAR_INT'''||rowspan=12|
 
|-
 
|-
!IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR
+
|'''SET_VAR_FLOAT'''
|[[004B|75]]||VF||LF||colspan=6|
 
 
|-
 
|-
!colspan=2|GOTO_IF_FALSE{{ref|statem|[*]}}
+
|'''SET_LVAR_INT'''
|[[004D|77]]
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
!colspan=2|TERMINATE_THIS_SCRIPT
+
|'''SET_LVAR_FLOAT'''
|rowspan=2|[[004E|78]]
 
!rowspan=2|0
 
|rowspan=2 colspan=8|
 
 
|-
 
|-
!colspan=2|MISSION_END
+
|'''SET_VAR_INT_TO_VAR_INT'''
 
|-
 
|-
!colspan=2|START_NEW_SCRIPT{{ref|undarg|[*]}}
+
|'''SET_LVAR_INT_TO_LVAR_INT'''
|[[004F|79]]
 
!1+l
 
|R||colspan=7|AM
 
 
|-
 
|-
|colspan=2|GOSUB
+
|'''SET_VAR_FLOAT_TO_VAR_FLOAT'''
|[[0050|80]]
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
|colspan=2|RETURN
+
|'''SET_LVAR_FLOAT_TO_LVAR_FLOAT'''
|[[0051|81]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
!rowspan=6|+=@<br/>+@<br/>ADD_THING_TO_THING_TIMED!!ADD_TIMED_VAL_TO_FLOAT_VAR
+
|'''SET_VAR_FLOAT_TO_LVAR_FLOAT'''
|[[0078|120]]
 
!rowspan=6|2
 
|VF||F||colspan=6|
 
 
|-
 
|-
!ADD_TIMED_VAL_TO_FLOAT_LVAR
+
|'''SET_LVAR_FLOAT_TO_VAR_FLOAT'''
|[[0079|121]]||LF||F||colspan=6|
 
 
|-
 
|-
!ADD_TIMED_FLOAT_VAR_TO_FLOAT_VAR
+
|'''SET_VAR_INT_TO_LVAR_INT'''
|[[007A|122]]||VF||VF||colspan=6|
 
 
|-
 
|-
!ADD_TIMED_FLOAT_LVAR_TO_FLOAT_LVAR
+
|'''SET_LVAR_INT_TO_VAR_INT'''
|[[007B|123]]||LF||LF||colspan=6|
 
 
|-
 
|-
!ADD_TIMED_FLOAT_LVAR_TO_FLOAT_VAR
+
|'''SET_VAR_INT_TO_CONSTANT'''||rowspan=2 align=center|Since {{icon|vc}}
|[[007C|124]]||LF||VF||colspan=6|
 
 
|-
 
|-
!ADD_TIMED_FLOAT_VAR_TO_FLOAT_LVAR
+
|'''SET_LVAR_INT_TO_CONSTANT'''
|[[007D|125]]||VF||LF||colspan=6|
 
 
|-
 
|-
!rowspan=6|-=@<br/>-@<br/>SUB_THING_FROM_THING_TIMED!!SUB_TIMED_VAL_FROM_FLOAT_VAR
+
|'''SET_VAR_TEXT_LABEL'''||rowspan=4 align=center|{{icon|sa}} only
|[[007E|126]]
 
!rowspan=6|2
 
|VF||F||colspan=6|
 
 
|-
 
|-
!SUB_TIMED_VAL_FROM_FLOAT_LVAR
+
|'''SET_LVAR_TEXT_LABEL'''
|[[007F|127]]||LF||F||colspan=6|
 
 
|-
 
|-
!SUB_TIMED_FLOAT_VAR_FROM_FLOAT_VAR
+
|'''SET_VAR_TEXT_LABEL16'''
|[[0080|128]]||VF||VF||colspan=6|
 
 
|-
 
|-
!SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_LVAR
+
|'''SET_LVAR_TEXT_LABEL16'''
|[[0081|129]]||LF||LF||colspan=6|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_VAR
+
!colspan=2 style="background-color: inherit; text-align: left"|CSET (<code>=#</code>)
|[[0082|130]]||LF||VF||colspan=6|
+
|width=64px align=center|Since {{icon|3}}
 
|-
 
|-
!SUB_TIMED_FLOAT_VAR_FROM_FLOAT_LVAR
+
|rowspan=8 width=20px|
|[[0083|131]]||VF||LF||colspan=6|
+
|'''CSET_VAR_INT_TO_VAR_FLOAT||rowspan=8|
 
|-
 
|-
!rowspan=8|=#<br/>CSET<br/>!!CSET_VAR_INT_TO_VAR_FLOAT
+
|'''CSET_VAR_FLOAT_TO_VAR_INT
|[[008C|140]]
 
!rowspan=8|2
 
|VI||VF||colspan=6|
 
 
|-
 
|-
!CSET_VAR_FLOAT_TO_VAR_INT
+
|'''CSET_LVAR_INT_TO_VAR_FLOAT
|[[008D|141]]||VF||VI||colspan=6|
 
 
|-
 
|-
!CSET_LVAR_INT_TO_VAR_FLOAT
+
|'''CSET_LVAR_FLOAT_TO_VAR_INT
|[[008E|142]]||LI||VF||colspan=6|
 
 
|-
 
|-
!CSET_LVAR_FLOAT_TO_VAR_INT
+
|'''CSET_VAR_INT_TO_LVAR_FLOAT
|[[008F|143]]||LF||VI||colspan=6|
 
 
|-
 
|-
!CSET_VAR_INT_TO_LVAR_FLOAT
+
|'''CSET_VAR_FLOAT_TO_LVAR_INT
|[[0090|144]]||VI||LF||colspan=6|
 
 
|-
 
|-
!CSET_VAR_FLOAT_TO_LVAR_INT
+
|'''CSET_LVAR_INT_TO_LVAR_FLOAT
|[[0091|145]]||VF||LI||colspan=6|
 
 
|-
 
|-
!CSET_LVAR_INT_TO_LVAR_FLOAT
+
|'''CSET_LVAR_FLOAT_TO_LVAR_INT
|[[0092|146]]||LI||LF||colspan=6|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!CSET_LVAR_FLOAT_TO_LVAR_INT
+
!colspan=2 style="background-color: inherit; text-align: left"|ADD_THING_TO_THING (<code>+=</code>)
|[[0093|147]]||LF||LI||colspan=6|
+
|width=64px align=center|Since {{icon|3}}
 
|-
 
|-
!rowspan=4|ABS!!ABS_VAR_INT
+
|rowspan=12 width=20px|
|[[0094|148]]
+
|'''ADD_VAL_TO_INT_VAR'''||rowspan=12|
!rowspan=4|1
 
|VI||colspan=7|
 
 
|-
 
|-
!ABS_LVAR_INT
+
|'''ADD_VAL_TO_FLOAT_VAR'''
|[[0095|149]]||LI||colspan=7|
 
 
|-
 
|-
!ABS_VAR_FLOAT
+
|'''ADD_VAL_TO_INT_LVAR'''
|[[0096|150]]||VF||colspan=7|
 
 
|-
 
|-
!ABS_LVAR_FLOAT
+
|'''ADD_VAL_TO_FLOAT_LVAR'''
|[[0097|151]]||LF||colspan=7|
 
 
|-
 
|-
!colspan=2|VAR_INT{{ref|defvar|[*]}}
+
|'''ADD_INT_VAR_TO_INT_VAR'''
|[[00C7|199]]
 
!n
 
|VI||colspan=7|VIO
 
 
|-
 
|-
!colspan=2|VAR_FLOAT{{ref|defvar|[*]}}
+
|'''ADD_FLOAT_VAR_TO_FLOAT_VAR'''
|[[00C8|200]]
 
!n
 
|VF||colspan=7|VFO
 
 
|-
 
|-
!colspan=2|LVAR_INT{{ref|defvar|[*]}}
+
|'''ADD_INT_LVAR_TO_INT_LVAR'''
|[[00C9|201]]
 
!n
 
|LI||colspan=7|LIO
 
 
|-
 
|-
!colspan=2|LVAR_FLOAT{{ref|defvar|[*]}}
+
|'''ADD_FLOAT_LVAR_TO_FLOAT_LVAR'''
|[[00CA|202]]
 
!n
 
|LF||colspan=7|LFO
 
 
|-
 
|-
!colspan=2|{{{ref|embdsc|[*]}}
+
|'''ADD_INT_VAR_TO_INT_LVAR'''
|[[00CB|203]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|}{{ref|embdsc|[*]}}
+
|'''ADD_FLOAT_VAR_TO_FLOAT_LVAR'''
|[[00CC|204]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|IF{{ref|statem|[*]}}
+
|'''ADD_INT_LVAR_TO_INT_VAR'''
|[[00CF|207]]
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|ELSE{{ref|statem|[*]}}
+
|'''ADD_FLOAT_LVAR_TO_FLOAT_VAR'''
|[[00D1|209]]
+
|}
!0
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|colspan=8|
 
 
|-
 
|-
!colspan=2|ENDIF{{ref|statem|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|SUB_THING_FROM_THING (<code>-=</code>)
|[[00D2|210]]
+
|width=64px align=center|Since {{icon|3}}
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|WHILE{{ref|statem|[*]}}
+
|rowspan=12 width=20px|
|[[00D3|211]]
+
|'''SUB_VAL_FROM_INT_VAR'''||rowspan=12|
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|ENDWHILE{{ref|statem|[*]}}
+
|'''SUB_VAL_FROM_FLOAT_VAR'''
|[[00D5|213]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
|colspan=12|{{icon|t}}
+
|'''SUB_VAL_FROM_INT_LVAR'''
 
|-
 
|-
!colspan=2|ANDOR{{ref|statem|[*]}}
+
|'''SUB_VAL_FROM_FLOAT_LVAR'''
|[[00D6|214]]
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|LAUNCH_MISSION
+
|'''SUB_INT_VAR_FROM_INT_VAR'''
|[[00D7|215]]
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
|colspan=2|START_CUTSCENE
+
|'''SUB_FLOAT_VAR_FROM_FLOAT_VAR'''
|[[02E7|743]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|PLAYER_MADE_PROGRESS
+
|'''SUB_INT_LVAR_FROM_INT_LVAR'''
|[[030C|780]]
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|SET_PROGRESS_TOTAL
+
|'''SUB_FLOAT_LVAR_FROM_FLOAT_LVAR'''
|[[030D|781]]
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
|colspan=2|REGISTER_MISSION_GIVEN
+
|'''SUB_INT_VAR_FROM_INT_LVAR'''
|[[0317|791]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|REGISTER_MISSION_PASSED
+
|'''SUB_FLOAT_VAR_FROM_FLOAT_LVAR'''
|[[0318|792]]
 
!1
 
|T||colspan=7|
 
 
|-
 
|-
!colspan=2|SCRIPT_NAME
+
|'''SUB_INT_LVAR_FROM_INT_VAR'''
|[[03A4|932]]
 
!1
 
|T||colspan=7|
 
 
|-
 
|-
!colspan=2|LOAD_AND_LAUNCH_MISSION
+
|'''SUB_FLOAT_LVAR_FROM_FLOAT_VAR'''
|[[0416|1046]]
+
|}
!1
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|R||colspan=7|
 
 
|-
 
|-
!colspan=2|LOAD_AND_LAUNCH_MISSION_INTERNAL
+
!colspan=2 style="background-color: inherit; text-align: left"|MULT_THING_BY_THING (<code>*=</code>)
|[[0417|1047]]
+
|width=64px align=center|Since {{icon|3}}
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|SET_TOTAL_NUMBER_OF_MISSIONS
+
|rowspan=12 width=20px|
|[[042C|1068]]
+
|'''MULT_INT_VAR_BY_VAL'''||rowspan=12|
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|REGISTER_ODDJOB_MISSION_PASSED
+
|'''MULT_FLOAT_VAR_BY_VAL'''
|[[0595|1429]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
|colspan=12|{{icon|vc}} {{icon|sa}} {{icon|lcs}}
+
|'''MULT_INT_LVAR_BY_VAL'''
 
|-
 
|-
!colspan=2|REPEAT{{ref|statem|[*]}}
+
|'''MULT_FLOAT_LVAR_BY_VAL'''
|[[00CD|205]]
 
!2
 
|I||VLI||colspan=6|
 
 
|-
 
|-
!colspan=2|ENDREPEAT{{ref|statem|[*]}}
+
|'''MULT_INT_VAR_BY_INT_VAR'''
|[[00CE|206]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
|colspan=12|{{icon|3}} {{icon|vc}}
+
|'''MULT_FLOAT_VAR_BY_FLOAT_VAR'''
 
|-
 
|-
!colspan=2|CREATE_COLLECTABLE1
+
|'''MULT_INT_LVAR_BY_INT_LVAR'''
|[[02EC|748]]
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|SET_COLLECTABLE1_TOTAL
+
|'''MULT_FLOAT_LVAR_BY_FLOAT_LVAR'''
|[[02ED|749]]
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
|colspan=12|{{icon|3}} {{icon|lcs}}
+
|'''MULT_INT_VAR_BY_INT_LVAR'''
 
|-
 
|-
!colspan=2|GOTO_IF_TRUE{{ref|statem|[*]}}
+
|'''MULT_FLOAT_VAR_BY_FLOAT_LVAR'''
|[[004C|76]]
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
|colspan=12|{{icon|vc}} {{icon|sa}}
+
|'''MULT_INT_LVAR_BY_INT_VAR'''
 
|-
 
|-
!rowspan=2|=<br/>IS_THING_EQUAL_TO_THING!!IS_INT_VAR_EQUAL_TO_CONSTANT
+
|'''MULT_FLOAT_LVAR_BY_FLOAT_VAR'''
|[[04A3|1187]]
+
|}
!rowspan=2|2
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|VI||C||colspan=6|
 
 
|-
 
|-
!IS_INT_LVAR_EQUAL_TO_CONSTANT
+
!colspan=2 style="background-color: inherit; text-align: left"|DIV_THING_BY_THING (<code>/=</code>)
|[[04A4|1188]]||LI||C||colspan=6|
+
|width=64px align=center|Since {{icon|3}}
 
|-
 
|-
!rowspan=2|=<br/>SET!!SET_VAR_INT_TO_CONSTANT
+
|rowspan=12 width=20px|
|[[04AE|1198]]
+
|'''DIV_INT_VAR_BY_VAL'''||rowspan=12|
!rowspan=2|2
 
|VI||C||colspan=6|
 
 
|-
 
|-
!SET_LVAR_INT_TO_CONSTANT
+
|'''DIV_FLOAT_VAR_BY_VAL'''
|[[04AF|1199]]||LI||C||colspan=6|
 
 
|-
 
|-
!rowspan=4|><br/><=<br/>IS_THING_GREATER_THAN_THING!!IS_INT_VAR_GREATER_THAN_CONSTANT
+
|'''DIV_INT_LVAR_BY_VAL'''
|[[04B0|1200]]
 
!rowspan=4|2
 
|VI||C||colspan=6|
 
 
|-
 
|-
!IS_INT_LVAR_GREATER_THAN_CONSTANT
+
|'''DIV_FLOAT_LVAR_BY_VAL'''
|[[04B1|1201]]||LI||C||colspan=6|
 
 
|-
 
|-
!IS_CONSTANT_GREATER_THAN_INT_VAR
+
|'''DIV_INT_VAR_BY_INT_VAR'''
|[[04B2|1202]]||C||VI||colspan=6|
 
 
|-
 
|-
!IS_CONSTANT_GREATER_THAN_INT_LVAR
+
|'''DIV_FLOAT_VAR_BY_FLOAT_VAR'''
|[[04B3|1203]]||C||LI||colspan=6|
 
 
|-
 
|-
!rowspan=4|>=<br/><<br/>IS_THING_GREATER_OR_EQUAL_TO_THING!!IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT
+
|'''DIV_INT_LVAR_BY_INT_LVAR'''
|[[04B4|1204]]
 
!rowspan=4|2
 
|VI||C||colspan=6|
 
 
|-
 
|-
!IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT
+
|'''DIV_FLOAT_LVAR_BY_FLOAT_LVAR'''
|[[04B5|1205]]||LI||C||colspan=6|
 
 
|-
 
|-
!IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR
+
|'''DIV_INT_VAR_BY_INT_LVAR'''
|[[04B6|1206]]||C||VI||colspan=6|
 
 
|-
 
|-
!IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR
+
|'''DIV_FLOAT_VAR_BY_FLOAT_LVAR'''
|[[04B7|1207]]||C||LI||colspan=6|
 
 
|-
 
|-
!colspan=2|LOAD_AND_LAUNCH_MISSION_EXCLUSIVE
+
|'''DIV_INT_LVAR_BY_INT_VAR'''
|[[0515|1301]]
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
|colspan=12|{{icon|3}}
+
|'''DIV_FLOAT_LVAR_BY_FLOAT_VAR'''
 +
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!colspan=2|IFNOT{{ref|statem|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|IS_THING_EQUAL_TO_THING (<code>=</code>)
|[[00D0|208]]
+
|width=64px align=center|Since {{icon|3}}
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|WHILENOT{{ref|statem|[*]}}
+
|rowspan=18 width=20px|
|[[00D4|212]]
+
|'''IS_INT_VAR_EQUAL_TO_NUMBER'''||rowspan=5|
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|GOSUB_FILE
+
|'''IS_INT_LVAR_EQUAL_TO_NUMBER'''
|[[02CD|717]]
 
!2
 
|R||R||colspan=6|
 
 
|-
 
|-
|colspan=12|{{icon|sa}}
+
|'''IS_INT_VAR_EQUAL_TO_INT_VAR'''
 
|-
 
|-
!rowspan=2|=<br/>SET!!SET_VAR_TEXT_LABEL
+
|'''IS_INT_LVAR_EQUAL_TO_INT_LVAR'''
|[[05A9|1449]]
 
!rowspan=2|2
 
|VT||AT||colspan=6|
 
 
|-
 
|-
!SET_LVAR_TEXT_LABEL
+
|'''IS_INT_VAR_EQUAL_TO_INT_LVAR'''
|[[05AA|1450]]||LT||AT||colspan=6|
 
 
|-
 
|-
!colspan=2|VAR_TEXT_LABEL{{ref|defvar|[*]}}
+
|'''IS_INT_LVAR_EQUAL_TO_INT_VAR'''||align=center|{{icon|sa}} only
|[[05AB|1451]]
 
!n
 
|VT||colspan=7|VTO
 
 
|-
 
|-
!colspan=2|LVAR_TEXT_LABEL{{ref|defvar|[*]}}
+
|'''IS_FLOAT_VAR_EQUAL_TO_NUMBER'''||rowspan=5|
|[[05AC|1452]]
 
!n
 
|LT||colspan=7|LTO
 
 
|-
 
|-
!rowspan=2|=<br/>IS_THING_EQUAL_TO_THING!!IS_VAR_TEXT_LABEL_EQUAL_TO_TEXT_LABEL
+
|'''IS_FLOAT_LVAR_EQUAL_TO_NUMBER'''
|[[05AD|1453]]
 
!rowspan=2|2
 
|VT||AT||colspan=6|
 
 
|-
 
|-
!IS_LVAR_TEXT_LABEL_EQUAL_TO_TEXT_LABEL
+
|'''IS_FLOAT_VAR_EQUAL_TO_FLOAT_VAR'''
|[[05AE|1454]]||LT||AT||colspan=6|
 
 
|-
 
|-
!rowspan=2|=<br/>SET!!SET_VAR_TEXT_LABEL16
+
|'''IS_FLOAT_LVAR_EQUAL_TO_FLOAT_LVAR'''
|[[06D1|1745]]
 
!rowspan=2|2
 
|VT16||AT16||colspan=6|
 
 
|-
 
|-
!SET_LVAR_TEXT_LABEL16
+
|'''IS_FLOAT_VAR_EQUAL_TO_FLOAT_LVAR'''
|[[06D2|1476]]||LT16||AT16||colspan=6|
 
 
|-
 
|-
!colspan=2|VAR_TEXT_LABEL16{{ref|defvar|[*]}}
+
|'''IS_FLOAT_LVAR_EQUAL_TO_FLOAT_VAR'''||align=center|{{icon|sa}} only
|[[06D3|1477]]
 
!n
 
|VT16||colspan=7|VT16O
 
 
|-
 
|-
!colspan=2|LVAR_TEXT_LABEL16{{ref|defvar|[*]}}
+
|'''IS_INT_VAR_EQUAL_TO_CONSTANT'''||rowspan=2 align=center|Since {{icon|vc}}
|[[06D4|1478]]
 
!n
 
|LT16||colspan=7|LT16O
 
 
|-
 
|-
!rowspan=2|=<br/>IS_THING_EQUAL_TO_THING!!IS_INT_LVAR_EQUAL_TO_INT_VAR
+
|'''IS_INT_LVAR_EQUAL_TO_CONSTANT'''
|[[07D6|2006]]
 
!rowspan=2|2
 
|LI||VI||colspan=6|
 
 
|-
 
|-
!IS_FLOAT_LVAR_EQUAL_TO_FLOAT_VAR
+
|'''IS_VAR_TEXT_LABEL_EQUAL_TO_TEXT_LABEL'''||rowspan=4 align=center|{{icon|sa}} only
|[[07D7|2007]]||LF||VF||colspan=6|
 
 
|-
 
|-
!rowspan=4|IS_EMPTY{{ref|likely|[*]}}!!IS_VAR_TEXT_LABEL_EMPTY
+
|'''IS_LVAR_TEXT_LABEL_EQUAL_TO_TEXT_LABEL'''
|[[0844|2116]]
 
!rowspan=4|1
 
|VT||colspan=7|
 
 
|-
 
|-
!IS_LVAR_TEXT_LABEL_EMPTY
+
|'''IS_VAR_TEXT_LABEL16_EQUAL_TO_TEXT_LABEL'''
|[[0845|2117]]||LT||colspan=7|
 
 
|-
 
|-
!IS_VAR_TEXT_LABEL16_EMPTY
+
|'''IS_LVAR_TEXT_LABEL16_EQUAL_TO_TEXT_LABEL'''
|[[0846|2118]]||VT16||colspan=7|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!IS_LVAR_TEXT_LABEL16_EMPTY
+
!colspan=2 style="background-color: inherit; text-align: left"|IS_THING_NOT_EQUAL_TO_THING (<code><></code>)
|[[0847|2119]]||LT16||colspan=7|
+
|width=64px align=center|Since {{icon|3}}
 
|-
 
|-
!colspan=2|SWITCH{{ref|statem|[*]}}
+
|rowspan=12 width=20px|
|[[0848|2120]]
+
|'''IS_INT_VAR_NOT_EQUAL_TO_NUMBER'''||rowspan=5|
!1
 
|VLI||colspan=7|
 
 
|-
 
|-
!colspan=2|ENDSWITCH{{ref|statem|[*]}}
+
|'''IS_INT_LVAR_NOT_EQUAL_TO_NUMBER'''
|[[0849|2121]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|CASE{{ref|statem|[*]}}
+
|'''IS_INT_VAR_NOT_EQUAL_TO_INT_VAR'''
|[[084A|2122]]
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|DEFAULT{{ref|statem|[*]}}
+
|'''IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR'''
|[[084B|2123]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|BREAK{{ref|statem|[*]}}
+
|'''IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR'''
|[[084C|2124]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
!rowspan=4 colspan=2|SWITCH_START{{ref|statem|[*]}}
+
|'''IS_INT_LVAR_NOT_EQUAL_TO_INT_VAR'''||align=center|{{icon|sa}} only
|rowspan=4|[[0871|2161]]
 
!rowspan=4|18
 
|rowspan=2|VI
 
|rowspan=2|I
 
|rowspan=2|I
 
|rowspan=2|R
 
|colspan=2|I||colspan=2|
 
 
|-
 
|-
|colspan=2|R||colspan=2|
+
|'''IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER'''||rowspan=5|
 
|-
 
|-
|rowspan=2|LI
+
|'''IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER'''
|rowspan=2|I
 
|rowspan=2|I
 
|rowspan=2|R
 
|colspan=2|I||colspan=2|
 
 
|-
 
|-
|colspan=2|R||colspan=2|
+
|'''IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR'''
 
|-
 
|-
!rowspan=2 colspan=2|SWITCH_CONTINUED{{ref|statem|[*]}}
+
|'''IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR'''
|rowspan=2|[[0872|2162]]
 
!rowspan=2|18
 
|colspan=6|I
 
|colspan=2|
 
 
|-
 
|-
|colspan=6|R
+
|'''IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR'''
|colspan=2|
 
 
|-
 
|-
!rowspan=6|IS_BIT_SET{{ref|likely|[*]}}!!IS_GLOBAL_VAR_BIT_SET_CONST
+
|'''IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_VAR'''||align=center|{{icon|sa}} only
|[[08B4|2228]]
+
|}
!rowspan=6|2
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|VI||C||colspan=6|
 
 
|-
 
|-
!IS_GLOBAL_VAR_BIT_SET_VAR
+
!colspan=2 style="background-color: inherit; text-align: left"|IS_THING_GREATER_THAN_THING (<code>></code>, <code><=</code>)
|[[08B5|2229]]||VI||VI||colspan=6|
+
|width=64px align=center|Since {{icon|3}}
 
|-
 
|-
!IS_GLOBAL_VAR_BIT_SET_LVAR
+
|rowspan=20 width=20px|
|[[08B6|2230]]||VI||LI||colspan=6|
+
|'''IS_INT_VAR_GREATER_THAN_NUMBER'''||rowspan=16|
 
|-
 
|-
!IS_LOCAL_VAR_BIT_SET_CONST
+
|'''IS_INT_LVAR_GREATER_THAN_NUMBER'''
|[[08B7|2231]]||LI||C||colspan=6|
 
 
|-
 
|-
!IS_LOCAL_VAR_BIT_SET_VAR
+
|'''IS_NUMBER_GREATER_THAN_INT_VAR'''
|[[08B8|2232]]||LI||VI||colspan=6|
 
 
|-
 
|-
!IS_LOCAL_VAR_BIT_SET_LVAR
+
|'''IS_NUMBER_GREATER_THAN_INT_LVAR'''
|[[08B9|2233]]||LI||LI||colspan=6|
 
 
|-
 
|-
!rowspan=6|SET_BIT{{ref|likely|[*]}}!!SET_GLOBAL_VAR_BIT_CONST
+
|'''IS_INT_VAR_GREATER_THAN_INT_VAR'''
|[[08BA|2234]]
 
!rowspan=6|2
 
|VI||C||colspan=6|
 
 
|-
 
|-
!SET_GLOBAL_VAR_BIT_VAR
+
|'''IS_INT_LVAR_GREATER_THAN_INT_LVAR'''
|[[08BB|2235]]||VI||VI||colspan=6|
 
 
|-
 
|-
!SET_GLOBAL_VAR_BIT_LVAR
+
|'''IS_INT_VAR_GREATER_THAN_INT_LVAR'''
|[[08BC|2236]]||VI||LI||colspan=6|
 
 
|-
 
|-
!SET_LOCAL_VAR_BIT_CONST
+
|'''IS_INT_LVAR_GREATER_THAN_INT_VAR'''
|[[08BD|2237]]||LI||C||colspan=6|
 
 
|-
 
|-
!SET_LOCAL_VAR_BIT_VAR
+
|'''IS_FLOAT_VAR_GREATER_THAN_NUMBER'''
|[[08BE|2238]]||LI||VI||colspan=6|
 
 
|-
 
|-
!SET_LOCAL_VAR_BIT_LVAR
+
|'''IS_FLOAT_LVAR_GREATER_THAN_NUMBER'''
|[[08BF|2239]]||LI||LI||colspan=6|
 
 
|-
 
|-
!rowspan=6|CLEAR_BIT{{ref|likely|[*]}}!!CLEAR_GLOBAL_VAR_BIT_CONST
+
|'''IS_NUMBER_GREATER_THAN_FLOAT_VAR'''
|[[08C0|2240]]
 
!rowspan=6|2
 
|VI||C||colspan=6|
 
 
|-
 
|-
!CLEAR_GLOBAL_VAR_BIT_VAR
+
|'''IS_NUMBER_GREATER_THAN_FLOAT_LVAR'''
|[[08C1|2241]]||VI||VI||colspan=6|
 
 
|-
 
|-
!CLEAR_GLOBAL_VAR_BIT_LVAR
+
|'''IS_FLOAT_VAR_GREATER_THAN_FLOAT_VAR'''
|[[08C2|2242]]||VI||LI||colspan=6|
 
 
|-
 
|-
!CLEAR_LOCAL_VAR_BIT_CONST
+
|'''IS_FLOAT_LVAR_GREATER_THAN_FLOAT_LVAR'''
|[[08C3|2243]]||LI||C||colspan=6|
 
 
|-
 
|-
!CLEAR_LOCAL_VAR_BIT_VAR
+
|'''IS_FLOAT_VAR_GREATER_THAN_FLOAT_LVAR'''
|[[08C4|2244]]||LI||VI||colspan=6|
 
 
|-
 
|-
!CLEAR_LOCAL_VAR_BIT_LVAR
+
|'''IS_FLOAT_LVAR_GREATER_THAN_FLOAT_VAR'''
|[[08C5|2245]]||LI||LI||colspan=6|
 
 
|-
 
|-
!rowspan=2|=<br/>IS_THING_EQUAL_TO_THING!!IS_VAR_TEXT_LABEL16_EQUAL_TO_TEXT_LABEL
+
|'''IS_INT_VAR_GREATER_THAN_CONSTANT'''||rowspan=4 align=center|Since {{icon|vc}}
|[[08F9|2297]]
 
!rowspan=2|2
 
|VT16||AT16||colspan=6|
 
 
|-
 
|-
!IS_LVAR_TEXT_LABEL16_EQUAL_TO_TEXT_LABEL
+
|'''IS_INT_LVAR_GREATER_THAN_CONSTANT'''
|[[08FA|2298]]||LT16||AT16||colspan=6|
 
 
|-
 
|-
!rowspan=2|STRING_CAT{{ref|likely|[*]}}!!STRING_CAT16
+
|'''IS_CONSTANT_GREATER_THAN_INT_VAR'''
|[[098B|2443]]
 
!rowspan=2|3
 
|VT16||VT16||VT16||colspan=5|
 
 
|-
 
|-
!STRING_CAT8
+
|'''IS_CONSTANT_GREATER_THAN_INT_LVAR'''
|[[098C|2444]]||VT||VT||VT||colspan=5|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
|colspan=12|{{icon|lcs}}
+
!colspan=2 style="background-color: inherit; text-align: left"|IS_THING_GREATER_OR_EQUAL_TO_THING (<code>>=</code>, <code><</code>)
 +
|width=64px align=center|Since {{icon|3}}
 
|-
 
|-
|colspan=2|RETURN_TRUE
+
|rowspan=20 width=20px|
|[[00C5|197]]
+
|'''IS_INT_VAR_GREATER_OR_EQUAL_TO_NUMBER'''||rowspan=16|
!0
 
|colspan=8|
 
 
|-
 
|-
|colspan=2|RETURN_FALSE
+
|'''IS_INT_LVAR_GREATER_OR_EQUAL_TO_NUMBER'''
|[[00C6|198]]
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|SWITCH{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_NUMBER_GREATER_OR_EQUAL_TO_INT_VAR'''
|214
 
!1
 
|VLI||colspan=7|
 
 
|-
 
|-
!colspan=2|ENDSWITCH{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_NUMBER_GREATER_OR_EQUAL_TO_INT_LVAR'''
|215
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|CASE{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_VAR'''
|216
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|DEFAULT{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_LVAR'''
|217
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|BREAK{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_LVAR'''
|218
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|ANDOR{{ref|statem|[*]}}
+
|'''IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_VAR'''
|219
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|LAUNCH_MISSION
+
|'''IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_NUMBER'''
|220
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
!colspan=2|SAVE_VAR_INT{{ref|defvar|[*]}}
+
|'''IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_NUMBER'''
|502
 
!l
 
|VI||colspan=7|VIO
 
 
|-
 
|-
!colspan=2|SAVE_VAR_FLOAT{{ref|defvar|[*]}}
+
|'''IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_VAR'''
|503
 
!l
 
|VF||colspan=7|VFO
 
 
|-
 
|-
!colspan=2|GOSUB_FILE
+
|'''IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_LVAR'''
|722
 
!2
 
|R||R||colspan=6|
 
 
|-
 
|-
|colspan=2|START_CUTSCENE
+
|'''IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_VAR'''
|748
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|PLAYER_MADE_PROGRESS
+
|'''IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR'''
|785
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|SET_PROGRESS_TOTAL
+
|'''IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR'''
|786
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
|colspan=2|REGISTER_MISSION_GIVEN
+
|'''IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_VAR'''
|796
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|REGISTER_MISSION_PASSED
+
|'''IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT'''||rowspan=4 align=center|Since {{icon|vc}}
|797
 
!1
 
|T||colspan=7|
 
 
|-
 
|-
!colspan=2|SCRIPT_NAME
+
|'''IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT'''
|937
 
!1
 
|T||colspan=7|
 
 
|-
 
|-
!colspan=2|LOAD_AND_LAUNCH_MISSION
+
|'''IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR'''
|1051
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
!colspan=2|LOAD_AND_LAUNCH_MISSION_INTERNAL
+
|'''IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR'''
|1052
+
|}
!1
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|SET_TOTAL_NUMBER_OF_MISSIONS
+
!colspan=2 style="background-color: inherit; text-align: left"|ADD_THING_TO_THING_TIMED (<code>+=@</code>)
|1073
+
|width=64px align=center|Since {{icon|3}}
!1
 
|I||colspan=7|
 
 
|-
 
|-
!rowspan=2|=<br/>IS_THING_EQUAL_TO_THING!!IS_INT_VAR_EQUAL_TO_CONSTANT
+
|rowspan=6 width=20px|
|1192
+
|'''ADD_TIMED_VAL_TO_FLOAT_VAR'''||rowspan=6|
!rowspan=2|2
 
|VI||C||colspan=6|
 
 
|-
 
|-
!IS_INT_LVAR_EQUAL_TO_CONSTANT
+
|'''ADD_TIMED_VAL_TO_FLOAT_LVAR'''
|1193||LI||C||colspan=6|
 
 
|-
 
|-
!rowspan=2|=<br/>SET!!SET_VAR_INT_TO_CONSTANT
+
|'''ADD_TIMED_FLOAT_VAR_TO_FLOAT_VAR'''
|1203
 
!rowspan=2|2
 
|VI||C||colspan=6|
 
 
|-
 
|-
!SET_LVAR_INT_TO_CONSTANT
+
|'''ADD_TIMED_FLOAT_LVAR_TO_FLOAT_LVAR'''
|1204||LI||C||colspan=6|
 
 
|-
 
|-
!rowspan=4|><br/><=<br/>IS_THING_GREATER_THAN_THING!!IS_INT_VAR_GREATER_THAN_CONSTANT
+
|'''ADD_TIMED_FLOAT_LVAR_TO_FLOAT_VAR'''
|1205
 
!rowspan=4|2
 
|VI||C||colspan=6|
 
 
|-
 
|-
!IS_INT_LVAR_GREATER_THAN_CONSTANT
+
|'''ADD_TIMED_FLOAT_VAR_TO_FLOAT_LVAR'''
|1206||LI||C||colspan=6|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!IS_CONSTANT_GREATER_THAN_INT_VAR
+
!colspan=2 style="background-color: inherit; text-align: left"|SUB_THING_FROM_THING_TIMED (<code>-=@</code>)
|1207||C||VI||colspan=6|
+
|width=64px align=center|Since {{icon|3}}
 
|-
 
|-
!IS_CONSTANT_GREATER_THAN_INT_LVAR
+
|rowspan=6 width=20px|
|1208||C||LI||colspan=6|
+
|'''SUB_TIMED_VAL_FROM_FLOAT_VAR'''||rowspan=6|
 
|-
 
|-
!rowspan=4|>=<br/><<br/>IS_THING_GREATER_OR_EQUAL_TO_THING!!IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT
+
|'''SUB_TIMED_VAL_FROM_FLOAT_LVAR'''
|1209
 
!rowspan=4|2
 
|VI||C||colspan=6|
 
 
|-
 
|-
!IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT
+
|'''SUB_TIMED_FLOAT_VAR_FROM_FLOAT_VAR'''
|1210||LI||C||colspan=6|
 
 
|-
 
|-
!IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR
+
|'''SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_LVAR'''
|1211||C||VI||colspan=6|
 
 
|-
 
|-
!IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR
+
|'''SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_VAR'''
|1212||C||LI||colspan=6|
 
 
|-
 
|-
!colspan=2|REGISTER_ODDJOB_MISSION_PASSED
+
|'''SUB_TIMED_FLOAT_VAR_FROM_FLOAT_LVAR'''
|1434
+
|}
!0
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|colspan=8|
 
 
|-
 
|-
!rowspan=2 colspan=2|CALL{{ref|undarg|[*]}}{{ref|argvar|[*]}}{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|ABS
|rowspan=2|1454
+
|width=64px align=center|Since {{icon|3}}
!rowspan=2|1+i+o
 
|rowspan=2|R
 
|colspan=7|AM
 
 
|-
 
|-
|colspan=7|VLM
+
|rowspan=4 width=20px|
 +
|'''ABS_VAR_INT'''||rowspan=4|
 
|-
 
|-
!rowspan=2 colspan=2|CALLNOT{{ref|undarg|[*]}}{{ref|argvar|[*]}}{{ref|likely|[*]}}
+
|'''ABS_LVAR_INT'''
|rowspan=2|1455
 
!rowspan=2|1+i+o
 
|rowspan=2|R
 
|colspan=7|AM
 
 
|-
 
|-
|colspan=7|VLM
+
|'''ABS_VAR_FLOAT'''
 
|-
 
|-
|colspan=12|{{icon|vcs}}
+
|'''ABS_LVAR_FLOAT'''
 +
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!rowspan=7|=<br/>SET!!SET_INT{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|IS_EMPTY
|4
+
|width=64px align=center|{{icon|sa}} only
 
 
!rowspan=7|2
 
|VLI||I||colspan=6|
 
 
|-
 
|-
!SET_FLOAT{{ref|likely|[*]}}
+
|rowspan=4 width=20px|
|5||VLF||F||colspan=6|
+
|'''IS_VAR_TEXT_LABEL_EMPTY'''||rowspan=4|
 
|-
 
|-
!SET_TEXT_LABEL{{ref|likely|[*]}}
+
|'''IS_LVAR_TEXT_LABEL_EMPTY'''
|6||VLT||T||colspan=6|
 
 
|-
 
|-
!SET_INT_TO_INT{{ref|likely|[*]}}
+
|'''IS_VAR_TEXT_LABEL16_EMPTY'''
|53||VLI||VLI||colspan=6|
 
 
|-
 
|-
!SET_FLOAT_TO_FLOAT{{ref|likely|[*]}}
+
|'''IS_LVAR_TEXT_LABEL16_EMPTY'''
|54||VLF||VLF||colspan=6|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!SET_TEXT_LABEL_TO_TEXT_LABEL{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|IS_BIT_SET
|55||VLT||VLT||colspan=6|
+
|width=64px align=center|{{icon|sa}} only
 
|-
 
|-
!SET_INT_TO_CONSTANT{{ref|likely|[*]}}
+
|rowspan=6 width=20px|
|738||VLI||C||colspan=6|
+
|'''IS_GLOBAL_VAR_BIT_SET_CONST'''||rowspan=6|
 
|-
 
|-
!rowspan=4|+=<br/>+<br/>ADD_THING_TO_THING!!ADD_VAL_TO_INT{{ref|likely|[*]}}
+
|'''IS_GLOBAL_VAR_BIT_SET_VAR'''
|7
 
!rowspan=4|2
 
|VLI||I||colspan=6|
 
 
|-
 
|-
!ADD_VAL_TO_FLOAT{{ref|likely|[*]}}
+
|'''IS_GLOBAL_VAR_BIT_SET_LVAR'''
|8||VLF||F||colspan=6|
 
 
|-
 
|-
!ADD_INT_TO_INT{{ref|likely|[*]}}
+
|'''IS_LOCAL_VAR_BIT_SET_CONST'''
|41||VLI||VLI||colspan=6|
 
 
|-
 
|-
!ADD_FLOAT_TO_FLOAT{{ref|likely|[*]}}
+
|'''IS_LOCAL_VAR_BIT_SET_VAR'''
|42||VLF||VLF||colspan=6|
 
 
|-
 
|-
!rowspan=4|-=<br/>-<br/>SUB_THING_FROM_THING!!SUB_VAL_FROM_INT{{ref|likely|[*]}}
+
|'''IS_LOCAL_VAR_BIT_SET_LVAR'''
|9
+
|}
!rowspan=4|2
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|VLI||I||colspan=6|
 
 
|-
 
|-
!SUB_VAL_FROM_FLOAT{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|SET_BIT
|10||VLF||F||colspan=6|
+
|width=64px align=center|{{icon|sa}} only
 
|-
 
|-
!SUB_INT_FROM_INT{{ref|likely|[*]}}
+
|rowspan=6 width=20px|
|43||VLI||VLI||colspan=6|
+
|'''SET_GLOBAL_VAR_BIT_CONST'''||rowspan=6|
 
|-
 
|-
!SUB_FLOAT_FROM_FLOAT{{ref|likely|[*]}}
+
|'''SET_GLOBAL_VAR_BIT_VAR'''
|44||VLF||VLF||colspan=6|
 
 
|-
 
|-
!rowspan=4|*=<br/>*<br/>MULT_THING_BY_THING!!MULT_INT_BY_VAL{{ref|likely|[*]}}
+
|'''SET_GLOBAL_VAR_BIT_LVAR'''
|11
 
!rowspan=4|2
 
|VLI||I||colspan=6|
 
 
|-
 
|-
!MULT_FLOAT_BY_VAL{{ref|likely|[*]}}
+
|'''SET_LOCAL_VAR_BIT_CONST'''
|12||VLF||F||colspan=6|
 
 
|-
 
|-
!MULT_INT_BY_INT{{ref|likely|[*]}}
+
|'''SET_LOCAL_VAR_BIT_VAR'''
|45||VLI||VLI||colspan=6|
 
 
|-
 
|-
!|MULT_FLOAT_BY_FLOAT{{ref|likely|[*]}}
+
|'''SET_LOCAL_VAR_BIT_LVAR'''
|46||VLF||VLF||colspan=6|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!rowspan=4|/=<br/>/<br/>DIV_THING_BY_THING!!DIV_INT_BY_VAL{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|CLEAR_BIT
|13
+
|width=64px align=center|{{icon|sa}} only
!rowspan=4|2
 
|VLI||I||colspan=6|
 
 
|-
 
|-
!DIV_FLOAT_BY_VAL{{ref|likely|[*]}}
+
|rowspan=6 width=20px|
|14||VLF||F||colspan=6|
+
|'''CLEAR_GLOBAL_VAR_BIT_CONST'''||rowspan=6|
 
|-
 
|-
!DIV_INT_BY_INT{{ref|likely|[*]}}
+
|'''CLEAR_GLOBAL_VAR_BIT_VAR'''
|47||VLI||VLI||colspan=6|
 
 
|-
 
|-
!DIV_FLOAT_BY_FLOAT{{ref|likely|[*]}}
+
|'''CLEAR_GLOBAL_VAR_BIT_LVAR'''
|48||VLF||VLF||colspan=6|
 
 
|-
 
|-
!rowspan=8|><br/><=<br/>IS_THING_GREATER_THAN_THING!!IS_INT_GREATER_THAN_NUMBER{{ref|likely|[*]}}
+
|'''CLEAR_LOCAL_VAR_BIT_CONST'''
|15
 
!rowspan=8|2
 
|VLI||I||colspan=6|
 
 
|-
 
|-
!IS_NUMBER_GREATER_THAN_INT{{ref|likely|[*]}}
+
|'''CLEAR_LOCAL_VAR_BIT_VAR'''
|16||I||VLI||colspan=6|
 
 
|-
 
|-
!IS_INT_GREATER_THAN_INT{{ref|likely|[*]}}
+
|'''CLEAR_LOCAL_VAR_BIT_LVAR'''
|17||VLI||VLI||colspan=6|
+
|}
 +
</div>
 +
|valign=top|<div style="overflow: auto; float: left" width=auto>
 +
{|class="wikitable" style="margin-bottom: 0" width=100%
 
|-
 
|-
!IS_FLOAT_GREATER_THAN_NUMBER{{ref|likely|[*]}}
+
!colspan=2 style="text-align: left"|Command
|18||VLF||F||colspan=6|
 
 
|-
 
|-
!IS_NUMBER_GREATER_THAN_FLOAT{{ref|likely|[*]}}
+
|width=20px|
|19||F||VLF||colspan=6|
+
!style="text-align: left"|Alternative
 +
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!IS_FLOAT_GREATER_THAN_FLOAT{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|SET (<code>=</code>)
|20||VLF||VLF||colspan=6|
 
 
|-
 
|-
!IS_INT_GREATER_THAN_CONSTANT{{ref|likely|[*]}}
+
|rowspan=7 width=20px|
|739||VLI||C||colspan=6|
+
|'''SET_VAR_INT'''
 
|-
 
|-
!IS_CONSTANT_GREATER_THAN_INT{{ref|likely|[*]}}
+
|'''SET_VAR_FLOAT'''
|740||C||VLI||colspan=6|
 
 
|-
 
|-
!rowspan=8|>=<br/><<br/>IS_THING_GREATER_OR_EQUAL_TO_THING!!IS_INT_GREATER_OR_EQUAL_TO_NUMBER{{ref|likely|[*]}}
+
|'''SET_VAR_TEXT_LABEL'''
|21
 
!rowspan=8|2
 
|VLI||I||colspan=6|
 
 
|-
 
|-
!IS_NUMBER_GREATER_OR_EQUAL_TO_INT{{ref|likely|[*]}}
+
|'''SET_VAR_INT_TO_VAR_INT'''
|22||I||VLI||colspan=6|
 
 
|-
 
|-
!IS_INT_GREATER_OR_EQUAL_TO_INT{{ref|likely|[*]}}
+
|'''SET_VAR_FLOAT_TO_VAR_FLOAT'''
|23||VLI||VLI||colspan=6|
 
 
|-
 
|-
!IS_FLOAT_GREATER_OR_EQUAL_TO_NUMBER{{ref|likely|[*]}}
+
|'''SET_VAR_TEXT_LABEL_TO_VAR_TEXT_LABEL'''
|24||VLF||F||colspan=6|
 
 
|-
 
|-
!IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT{{ref|likely|[*]}}
+
|'''SET_VAR_INT_TO_CONSTANT'''
|25||F||VLF||colspan=6|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!IS_FLOAT_GREATER_OR_EQUAL_TO_FLOAT{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|CSET (<code>=#</code>)
|26||VLF||VLF||colspan=6|
 
 
|-
 
|-
!IS_INT_GREATER_OR_EQUAL_TO_CONSTANT{{ref|likely|[*]}}
+
|rowspan=2 width=20px|
|741||VLI||C||colspan=6|
+
|'''CSET_VAR_INT_TO_VAR_FLOAT'''
 
|-
 
|-
!IS_CONSTANT_GREATER_OR_EQUAL_TO_INT{{ref|likely|[*]}}
+
|'''CSET_VAR_FLOAT_TO_VAR_INT'''
|742||C||VLI||colspan=6|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!rowspan=7|=<br/>IS_THING_EQUAL_TO_THING!!IS_INT_EQUAL_TO_NUMBER{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|ADD_THING_TO_THING (<code>+=</code>)
|27
 
!rowspan=7|2
 
|VLI||I||colspan=6|
 
 
|-
 
|-
!IS_INT_EQUAL_TO_INT{{ref|likely|[*]}}
+
|rowspan=4 width=20px|
|28||VLI||VLI||colspan=6|
+
|'''ADD_VAL_TO_INT_VAR'''
 
|-
 
|-
!IS_FLOAT_EQUAL_TO_NUMBER{{ref|likely|[*]}}
+
|'''ADD_VAL_TO_FLOAT_VAR'''
|29||VLF||F||colspan=6|
 
 
|-
 
|-
!IS_FLOAT_EQUAL_TO_FLOAT{{ref|likely|[*]}}
+
|'''ADD_INT_VAR_TO_INT_VAR'''
|30||VLF||VLF||colspan=6|
 
 
|-
 
|-
!IS_TEXT_LABEL_EQUAL_TO_STRING{{ref|likely|[*]}}
+
|'''ADD_FLOAT_VAR_TO_FLOAT_VAR'''
|31||VLT||T||colspan=6|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!IS_TEXT_LABEL_EQUAL_TO_TEXT_LABEL{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|SUB_THING_FROM_THING (<code>-=</code>)
|32||VLT||VLT||colspan=6|
 
 
|-
 
|-
!IS_INT_EQUAL_TO_CONSTANT{{ref|likely|[*]}}
+
|rowspan=4 width=20px|
|731||VLI||C||colspan=6|
+
|'''SUB_VAL_FROM_INT_VAR'''
 
|-
 
|-
!colspan=2|GOTO_IF_TRUE{{ref|statem|[*]}}
+
|'''SUB_VAL_FROM_FLOAT_VAR'''
|33
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
!colspan=2|GOTO_IF_FALSE{{ref|statem|[*]}}
+
|'''SUB_INT_VAR_FROM_INT_VAR'''
|34
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
!colspan=2|TERMINATE_THIS_SCRIPT
+
|'''SUB_FLOAT_VAR_FROM_FLOAT_VAR'''
|rowspan=2|35
+
|}
!rowspan=2|0
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|rowspan=2 colspan=8|
 
 
|-
 
|-
!colspan=2|MISSION_END
+
!colspan=2 style="background-color: inherit; text-align: left"|MULT_THING_BY_THING (<code>*=</code>)
 
|-
 
|-
!colspan=2|START_NEW_SCRIPT{{ref|undarg|[*]}}
+
|rowspan=4 width=20px|
|36
+
|'''MULT_INT_VAR_BY_VAL'''
!1+l
 
|R||colspan=7|AM
 
 
|-
 
|-
|colspan=2|GOSUB
+
|'''MULT_FLOAT_VAR_BY_VAL'''
|37
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
|colspan=2|RETURN
+
|'''MULT_INT_VAR_BY_INT_VAR'''
|38
 
!0
 
|colspan=8|
 
 
|-
 
|-
!rowspan=2|+=@<br/>+@<br/>ADD_THING_TO_THING_TIMED!!ADD_TIMED_VAL_TO_FLOAT{{ref|likely|[*]}}
+
|'''MULT_FLOAT_VAR_BY_FLOAT_VAR'''
|49
+
|}
!rowspan=2|2
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|VLF||F||colspan=6|
 
 
|-
 
|-
!ADD_TIMED_FLOAT_TO_FLOAT{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|DIV_THING_BY_THING (<code>/=</code>)
|50||VLF||VLF||colspan=6|
 
 
|-
 
|-
!rowspan=2|-=@<br/>-@<br/>SUB_THING_FROM_THING_TIMED!!SUB_TIMED_VAL_FROM_FLOAT{{ref|likely|[*]}}
+
|rowspan=4 width=20px|
|51
+
|'''DIV_INT_VAR_BY_VAL'''
!rowspan=2|2
 
|VLF||F||colspan=6|
 
 
|-
 
|-
!SUB_TIMED_FLOAT_FROM_FLOAT{{ref|likely|[*]}}
+
|'''DIV_FLOAT_VAR_BY_VAL'''
|52||VLF||VLF||colspan=6|
 
 
|-
 
|-
!rowspan=2|=#<br/>CSET!!CSET_INT_TO_FLOAT{{ref|likely|[*]}}
+
|'''DIV_INT_VAR_BY_INT_VAR'''
|56
 
!rowspan=2|2
 
|VLI||VLF||colspan=6|
 
 
|-
 
|-
!CSET_FLOAT_TO_INT{{ref|likely|[*]}}
+
|'''DIV_FLOAT_VAR_BY_FLOAT_VAR'''
|57||VLF||VLI||colspan=6|
+
|}
 +
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
|-
 
|-
!rowspan=2|ABS!!ABS_INT{{ref|likely|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|IS_THING_EQUAL_TO_THING (<code>=</code>)
|58
 
!rowspan=2|1
 
|VLI||colspan=7|
 
 
|-
 
|-
!ABS_FLOAT{{ref|likely|[*]}}
+
|rowspan=7 width=20px|
|59||VLF||colspan=7|
+
|'''IS_INT_VAR_EQUAL_TO_NUMBER'''
 
|-
 
|-
|colspan=2|RETURN_TRUE
+
|'''IS_INT_VAR_EQUAL_TO_INT_VAR'''
|94
 
!0
 
|colspan=8|
 
 
|-
 
|-
|colspan=2|RETURN_FALSE
+
|'''IS_FLOAT_VAR_EQUAL_TO_NUMBER'''
|95
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|VAR_INT{{ref|defvar|[*]}}{{ref|posngs|[*]}}
+
|'''IS_FLOAT_VAR_EQUAL_TO_FLOAT_VAR'''
|96
 
!n
 
|VI||colspan=7|VIO
 
 
|-
 
|-
!colspan=2|VAR_FLOAT{{ref|defvar|[*]}}{{ref|posngs|[*]}}
+
|'''IS_TEXT_LABEL_VAR_EQUAL_TO_TEXT_LABEL'''
|97
 
!n
 
|VF||colspan=7|VFO
 
 
|-
 
|-
!colspan=2|LVAR_INT{{ref|defvar|[*]}}{{ref|posngs|[*]}}
+
|'''IS_TEXT_LABEL_VAR_EQUAL_TO_TEXT_LABEL_VAR'''
|98
 
!n
 
|LI||colspan=7|LIO
 
 
|-
 
|-
!colspan=2|LVAR_FLOAT{{ref|defvar|[*]}}{{ref|posngs|[*]}}
+
|'''IS_INT_VAR_EQUAL_TO_CONSTANT'''
|99
+
|}
!n
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|LF||colspan=7|LFO
 
 
|-
 
|-
!colspan=2|VAR_TEXT_LABEL{{ref|defvar|[*]}}{{ref|posngs|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|IS_THING_GREATER_THAN_THING (<code>></code>, <code><=</code>)
|100
 
!n
 
|VT||colspan=7|VTO
 
 
|-
 
|-
!colspan=2|LVAR_TEXT_LABEL{{ref|defvar|[*]}}{{ref|posngs|[*]}}
+
|rowspan=8 width=20px|
|101
+
|'''IS_INT_VAR_GREATER_THAN_NUMBER'''
!n
 
|LT||colspan=7|LTO
 
 
|-
 
|-
!colspan=2|{{{ref|embdsc|[*]}}{{ref|posngs|[*]}}
+
|'''IS_NUMBER_GREATER_THAN_INT_VAR'''
|102
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|}{{ref|embdsc|[*]}}{{ref|posngs|[*]}}
+
|'''IS_INT_VAR_GREATER_THAN_INT_VAR'''
|103
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|IF{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_FLOAT_VAR_GREATER_THAN_NUMBER'''
|104
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|IFNOT{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_NUMBER_GREATER_THAN_FLOAT_VAR'''
|105
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|ELSE{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_FLOAT_VAR_GREATER_THAN_FLOAT_VAR'''
|106
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|ENDIF{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_INT_VAR_GREATER_THAN_CONSTANT'''
|107
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|WHILE{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_CONSTANT_GREATER_THAN_INT_VAR'''
|108
+
|}
!1
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|WHILENOT{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|IS_THING_GREATER_OR_EQUAL_TO_THING (<code>>=</code>, <code><</code>)
|109
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|ENDWHILE{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|rowspan=8 width=20px|
|110
+
|'''IS_INT_VAR_GREATER_OR_EQUAL_TO_NUMBER'''
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|REPEAT{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_NUMBER_GREATER_OR_EQUAL_TO_INT_VAR'''
|111
 
!2
 
|I||VLI||colspan=6|
 
 
|-
 
|-
!colspan=2|ENDREPEAT{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_VAR'''
|112
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|SWITCH{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_NUMBER'''
|113
 
!1
 
|VLI||colspan=7|
 
 
|-
 
|-
!colspan=2|ENDSWITCH{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_VAR'''
|114
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|CASE{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_VAR'''
|115
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|DEFAULT{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT'''
|116
 
!0
 
|colspan=8|
 
 
|-
 
|-
!colspan=2|BREAK{{ref|statem|[*]}}{{ref|posngs|[*]}}
+
|'''IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR'''
|117
+
|}
!0
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|colspan=8|
 
 
|-
 
|-
!colspan=2|ANDOR{{ref|statem|[*]}}
+
!colspan=2 style="background-color: inherit; text-align: left"|ADD_THING_TO_THING_TIMED (<code>+=@</code>)
|120
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|LAUNCH_MISSION
+
|rowspan=2 width=20px|
|121
+
|'''ADD_TIMED_VAL_TO_FLOAT_VAR'''
!1
 
|R||colspan=7|
 
 
|-
 
|-
!colspan=2|SAVE_VAR_INT{{ref|defvar|[*]}}
+
|'''ADD_TIMED_FLOAT_VAR_TO_FLOAT_VAR'''
|297
+
|}
!l
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
|VI||colspan=7|VIO
 
|-
 
!colspan=2|SAVE_VAR_FLOAT{{ref|defvar|[*]}}
 
|298
 
!l
 
|VF||colspan=7|VFO
 
|-
 
!colspan=2|SAVE_VAR_TEXT_LABEL{{ref|defvar|[*]}}
 
|299
 
!l
 
|VT||colspan=7|VTO
 
|-
 
!colspan=2|GOSUB_FILE
 
|442
 
!2
 
|R||R||colspan=6|
 
|-
 
!colspan=2|PLAYER_MADE_PROGRESS
 
|479
 
!1
 
|I||colspan=7|
 
|-
 
!colspan=2|SET_PROGRESS_TOTAL
 
|480
 
!1
 
|I||colspan=7|
 
|-
 
|colspan=2|REGISTER_MISSION_GIVEN
 
|490
 
!0
 
|colspan=8|
 
|-
 
!colspan=2|REGISTER_MISSION_PASSED
 
|491
 
!1
 
|T||colspan=7|
 
|-
 
!colspan=2|SCRIPT_NAME
 
|568
 
!1
 
|T||colspan=7|
 
|-
 
!colspan=2|LOAD_AND_LAUNCH_MISSION
 
|648
 
!1
 
|R||colspan=7|
 
 
|-
 
|-
!colspan=2|LOAD_AND_LAUNCH_MISSION_INTERNAL
+
!colspan=2 style="background-color: inherit; text-align: left"|SUB_THING_FROM_THING_TIMED (<code>-=@</code>)
|649
 
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|SET_TOTAL_NUMBER_OF_MISSIONS
+
|rowspan=2 width=20px|
|662
+
|'''SUB_TIMED_VAL_FROM_FLOAT_VAR'''
!1
 
|I||colspan=7|
 
 
|-
 
|-
!colspan=2|REGISTER_ODDJOB_MISSION_PASSED
+
|'''SUB_TIMED_FLOAT_VAR_FROM_FLOAT_VAR'''
|874
 
!0
 
|colspan=8|
 
|-
 
!rowspan=2 colspan=2|CALL{{ref|undarg|[*]}}{{ref|argvar|[*]}}{{ref|likely|[*]}}
 
|rowspan=2|890
 
!rowspan=2|1+i+o
 
|rowspan=2|R
 
|colspan=7|AM
 
|-
 
|colspan=7|VLM
 
|-
 
!rowspan=2 colspan=2|CALLNOT{{ref|undarg|[*]}}{{ref|argvar|[*]}}{{ref|likely|[*]}}
 
|rowspan=2|891
 
!rowspan=2|1+i+o
 
|rowspan=2|R
 
|colspan=7|AM
 
|-
 
|colspan=7|VLM
 
|-
 
!colspan=2|SET_COLLECTABLE2_TOTAL
 
|1242
 
!1
 
|I||colspan=7|
 
 
|}
 
|}
</div>
+
{|class="wikitable collapsible collapsed" style="margin: -1px auto 0" width=100%
 
 
;Notes
 
:{{note|misdef}} A special [[#Mission scripts|mission]] directive which is never compiled;
 
:{{note|statem}} It is used to build the various [[#Control flows|control flows]] internally;
 
:{{note|defvar}} It is used to declare one or more variables;
 
:{{note|embdsc}} It embeds a variable scope;
 
:{{note|undarg}} It has an undefined amount of arguments;
 
:{{note|likely}} It is a likely definition of the standard command;
 
:{{note|posngs}} It should exist but its position is purely guessed;
 
:{{note|argvar}} Arguments amount varies when compiling.
 
 
 
{{incomplete}}
 
 
 
==Uncommon values==
 
 
 
Arguments of some commands keep uncommon [[#Value|values]] which look familiar after encoding:
 
 
 
<div width=100% style="overflow: auto; margin: -8px auto 8px">
 
{|class=wikitable style=text-align:center
 
|-
 
!rowspan=2|Command
 
!rowspan=2|Arg.<br/>ID
 
!rowspan=2|Value
 
!colspan=4|Encoded
 
|-
 
!Command!!Arg.<br/>ID!!Value!!Type
 
|-
 
|colspan=7|{{icon|t}} {{icon|lcs}} {{icon|vcs}}
 
|-
 
!GOTO
 
|1||Generic [[#Labels|label]]
 
!GOTO
 
|1||Positive/Negative [[#Offsets|offset]]||INT
 
|-
 
!GOTO_IF_FALSE
 
|1||Generic label
 
!GOTO_IF_FALSE
 
|1||Positive/Negative offset||INT
 
|-
 
!GOSUB
 
|1||[[#Gosubs|Gosub]] label
 
!GOSUB
 
|1||Positive/Negative offset||INT
 
|-
 
!rowspan=4|GOSUB_FILE
 
|1||Gosub label
 
!rowspan=4|GOSUB_FILE
 
|1||rowspan=2|Zero-based offset||rowspan=4|INT
 
|-
 
|2||[[#Foreign gosubs|Foreign gosub]] file||2
 
|-
 
|1||Gosub label||1||rowspan=2|Positive/Negative offset
 
|-
 
|2||Foreign gosub label||2
 
|-
 
!rowspan=2|START_NEW_SCRIPT
 
|1||[[#Scripts|Script]] label
 
!rowspan=2|START_NEW_SCRIPT
 
|1||Positive/Negative offset||INT
 
|-
 
|l||Passed [[#Local|locals]]||l||Passed locals||ANY_MULTI
 
|-
 
!rowspan=2|LAUNCH_MISSION
 
|rowspan=2|1||[[#Subscripts|Subscript]] file
 
!rowspan=2|LAUNCH_MISSION
 
|rowspan=2|1||Zero-based offset||rowspan=2|INT
 
|-
 
|Subscript label||Positive/Negative offset
 
|-
 
!rowspan=2|LOAD_AND_LAUNCH_MISSION
 
|rowspan=2|1||[[#Mission scripts|Mission script]] file
 
!LOAD_AND_LAUNCH_MISSION_INTERNAL
 
|rowspan=2|1||Mission [[#Identifiers|identifier]]||rowspan=2|INT
 
|-
 
|Mission script label
 
!LOAD_AND_LAUNCH_MISSION
 
|Positive/Negative offset
 
|-
 
|colspan=7|{{icon|3}} {{icon|lcs}} {{icon|vcs}}
 
|-
 
!GOTO_IF_TRUE
 
|1||Generic label
 
!GOTO_IF_TRUE
 
|1||Positive/Negative offset||INT
 
|-
 
|colspan=7|{{icon|vc}} {{icon|sa}}
 
 
|-
 
|-
!rowspan=2|LOAD_AND_LAUNCH_MISSION_EXCLUSIVE
+
!colspan=2 style="background-color: inherit; text-align: left"|ABS
|rowspan=2|1||Mission script file
 
!LOAD_AND_LAUNCH_MISSION_INTERNAL
 
|rowspan=2|1||Negative mission identifier||rowspan=2|INT
 
 
|-
 
|-
|Mission script label
+
|rowspan=2 width=20px|
!LOAD_AND_LAUNCH_MISSION_EXCLUSIVE
+
|'''ABS_VAR_INT'''
|Positive/Negative offset
 
 
|-
 
|-
|colspan=7|{{icon|lcs}} {{icon|vcs}}
+
|'''ABS_VAR_FLOAT'''
|-
 
!rowspan=6|CALL<br/>CALLNOT
 
|rowspan=4|1||rowspan=4|[[#Functions|Function]] label
 
!rowspan=6|CALL<br/>CALLNOT
 
|1||# of input arguments||rowspan=4|INT
 
|-
 
|2||# of output arguments
 
|-
 
|3||# of script locals
 
|-
 
|4||Positive/Negative offset
 
|-
 
|i||Input arguments||i||Input arguments||ANY_MULTI
 
|-
 
|o||Output arguments||o||Output arguments||HOLD_MULTI
 
 
|}
 
|}
 
</div>
 
</div>
 
{{incomplete}}
 
 
==Compare flag==
 
 
The ''compare flag'' is an internal script-dependent flag which makes conditional '''GOTO'''s such as [[#GOTO_IF_TRUE|GOTO_IF_TRUE]] (unavailable in {{icon|t}}) and [[#GOTO_IF_FALSE|GOTO_IF_FALSE]] deciding whether to jump otherwise. It can handle up to ''8 checks'' per conditional statement and indicates you are verifying a single condition (0, see also [[#Optimization|Optimization]]) or multiple conditions with either '''AND''' (1 to 8) or '''OR''' (21 to 28) [[#Logical|logical operators]] (see also [[#ANDOR|ANDOR]]).
 
 
==Control flows analysis==
 
 
As an overview of the compiled source, [[#Control flows|control flows]] are literally nested meaning that the code is unoptimized. Furthermore, the jump of an embedded construct doesn't get merged with that of the construct itself, which consists of a benefit for the code parsing.
 
 
===IF===
 
 
As regards the [[#IF|IF]] control flow, if the whole check is true the ''consequence'' is performed and the code jumps to the end of the construct, otherwise it skips to the ''alternative'' (see also [[#Compare flag|Compare flag]]):
 
 
{|width=100%
 
!width=50%|Decompiled
 
!width=1px|{{icon|t}}
 
!width=1px|{{icon|lcs}}
 
!width=1px|{{icon|vcs}}
 
!Compiled
 
|-
 
|
 
IF [NOT] {condition0}
 
[AND|OR [NOT] {condition8}]
 
    {consequence}
 
[ELSE
 
    {alternative}]
 
ENDIF
 
|
 
{..214}
 
{.....}
 
{.....}
 
{...77}
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
  -----
 
|
 
{..219}
 
{.....}
 
{.....}
 
{...77}
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
  -----
 
|
 
{..120}
 
{.....}
 
{.....}
 
{...34}
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
  -----
 
|
 
ANDOR {value}
 
    [NOT] {condition0}
 
    [[NOT] {condition8}]
 
GOTO_IF_FALSE ELSE
 
    {consequence}
 
    [GOTO ENDIF]
 
ELSE:
 
    [{alternative}
 
ENDIF:]
 
 
|}
 
|}
  
===IFNOT===
+
==Control flows==
 
+
Insofar as subprograms, scripts are organized in a systematic arrangement through which goto branches, subroutine branches, function calls and returns are executed to form control flow statements and structures. These alter the [[Wikipedia:Program Counter|program counter]] most of the time affecting the top-down order all commands are fetched by. Facing off code duplication is quite recurring especially when the tasks to perform vary only in the input data, the case where a piece of code or subroutine, built once in the source, is invoked many times from various different places and returns back, as if the '''GOSUB''' statement is substituted in-place by the subroutine's body without '''RETURN''' during the control transferring, shrinking long codes and reducing the script overall size. The flow of execution can also be broken up conditionally by means of:
Not that much to say more than the preceding construct, the [[#IFNOT|IFNOT]] control flow is built nearly in the same way. In fact, the '''ELSE''' clause points to the ''alternative'', whereas the [[#GOTO|GOTO]] jumps to its end. The substantial difference consists in the substitution of [[#GOTO_IF_FALSE|GOTO_IF_FALSE]] with [[#GOTO_IF_TRUE|GOTO_IF_TRUE]]:
 
 
 
{|width=100%
 
!width=50%|Decompiled
 
!width=1px|{{icon|3}}
 
!width=1px|{{icon|lcs}}
 
!width=1px|{{icon|vcs}}
 
!Compiled
 
|-
 
|
 
IFNOT [NOT] {condition0}
 
[AND|OR [NOT] {condition8}]
 
    {consequence}
 
[ELSE
 
    {alternative}]
 
ENDIF
 
|
 
{..214}
 
{.....}
 
{.....}
 
{...76}
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
  -----
 
|
 
{..219}
 
{.....}
 
{.....}
 
{...76}
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
  -----
 
|
 
{..120}
 
{.....}
 
{.....}
 
{...33}
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
  -----
 
|
 
ANDOR {value}
 
    [NOT] {condition0}
 
    [[NOT] {condition8}]
 
GOTO_IF_TRUE ELSE
 
    {consequence}
 
    [GOTO ENDIF]
 
ELSE:
 
    [{alternative}
 
ENDIF:]
 
|}
 
 
 
===WHILE===
 
 
 
The [[#WHILE|WHILE]] control flow is built pretty much similarly to the previous, even though when the ''consequence'' is read the code is moved to the beginning of the construct:
 
 
 
{|width=100%
 
!width=50%|Decompiled
 
!width=1px|{{icon|t}}
 
!width=1px|{{icon|lcs}}
 
!width=1px|{{icon|vcs}}
 
!Compiled
 
|-
 
|
 
WHILE [NOT] {condition0}
 
[AND|OR [NOT] {condition8}]
 
    {consequence}
 
ENDWHILE
 
|
 
  -----
 
{..214}
 
{.....}
 
{.....}
 
{...77}
 
{.....}
 
{....2}
 
  -----
 
|
 
  -----
 
{..219}
 
{.....}
 
{.....}
 
{...77}
 
{.....}
 
{....2}
 
  -----
 
|
 
  -----
 
{..120}
 
{.....}
 
{.....}
 
{...34}
 
{.....}
 
{....2}
 
  -----
 
|
 
WHILE:
 
ANDOR {value}
 
    [NOT] {condition0}
 
    [[NOT] {condition8}]
 
GOTO_IF_FALSE ENDWHILE
 
    {consequence}
 
    GOTO WHILE
 
ENDWHILE:
 
|}
 
  
===WHILENOT===
+
* Decision-making structures ('''IF''', '''IFNOT''', '''SWITCH'''), which evaluate the result of one or more conditions and choose what path to follow based off the trueness or falseness of the check being tested. Been deemed the most basic tool of [[Wikipedia:Structured programming|structured programming]], '''IF''' is a bidirectional statement that proceeds with the execution of the underneath code only if the test carried out evaluates to true otherwise it transfers the control next to '''ENDIF''', unless a preceding and optional '''ELSE''' clause, establishing an alternative path, is specified. In the first Trilogy and both Stories chapters where '''GOTO_IF_TRUE''' is handled by game code, the barely used '''IFNOT''' can be deployed as a placeholder to easily invert the compare-flag, a boolean state which is set or cleared as a result of the bitwise [[Wikipedia:Bitwise operation#AND|conjunction]] or [[Wikipedia:Bitwise operation#OR|disjunction]] with the true/false state caught by a condition, applying the inversion according to the presence of the not-flag before updating. Logical operators make possible the connection among multiple conditions via the '''AND''' [[Wikipedia:Logical conjunction|conjunction]] and '''OR''' [[Wikipedia:Logical disjunction|disjunction]] giving the chance to verify if conditions are all true or if just one of them is satisfied bearing in mind that the '''NOT''' [[Wikipedia:Logical negation|negation]], inverting the boolean state of a single condition, may be supplied. Connectivity information are held by '''ANDOR''', whose argument depicts a value in the range <code>[1,8)</code> or <code>[21,28)</code> for logical conjunction and disjunction respectively, limiting the amount of total conditions to provide to a maximum of 8 per check (the prominent intervals discrepancy also suggests '''NAND''' and '''NOR''' operators might have been a plan). A value of 0 does nothing relevant functional-wise at runtime, what led programmers to not compile said command in such a situation for Stories chapters. The inability to create subexpressions enforces to not combine '''AND''' with '''OR''' in a check, plus evaluations are eager and therefore not short-circuited meaning all conditions are executed prior potentially branching through '''GOTO_IF_FALSE''' in the common case after the compare-flag gets processed. Nesting lots of '''IF-ELSE-ENDIF''' structures of one-condition checks testing the equality of the same variable against a few integer literals or string constants can add a ridiculous code redundancy and performance overhead, sorted out in the last Trilogy chapter thanks to the introduction of the '''SWITCH''' statement, a multiway statement either branching to the switch section labelled by fall-through '''CASE''' statements of which one passses a value that shall match the variable content to compare or optionally branching to '''DEFAULT''' in the worst-case scenario, each ending with a nonmandatory '''BREAK''' statement goto-ing past '''ENDSWITCH'''. On compilation, the implementation somehow mimics the pattern of a [[Wikipedia:Jump table|jump table]] sorting case label references by value to fulfil the runtime's [[Wikipedia:Binary search|binary search]] among at least 1 of 75 entries (default case aside);
 +
* Looping structures ('''REPEAT''', '''WHILE''', '''WHILENOT'''), which repeatedly execute a block of code certain number of times (count-controlled) or by constantly and successfully evaluating a check (condition-controlled).
  
To say the least, [[#WHILENOT|WHILENOT]] control flow follows the same constitution of both [[#WHILE|WHILE]] and [[#IFNOT|IFNOT]] constructs, by exchanging [[#GOTO_IF_FALSE|GOTO_IF_FALSE]] with [[#GOTO_IF_TRUE|GOTO_IF_TRUE]]:
+
IF/IFNOT-ELSE-ENDIF
 +
SWITCH-CASE/DEFAULT-BREAK-ENDSWITCH
  
{|width=100%
+
WHILE/WHILENOT-ENDWHILE
!width=50%|Decompiled
+
REPEAT-ENDREPEAT
!width=1px|{{icon|3}}
 
!width=1px|{{icon|lcs}}
 
!width=1px|{{icon|vcs}}
 
!Compiled
 
|-
 
|
 
WHILENOT [NOT] {condition0}
 
[AND|OR [NOT] {condition8}]
 
    {consequence}
 
ENDWHILE
 
|
 
  -----
 
{..214}
 
{.....}
 
{.....}
 
{...76}
 
{.....}
 
{....2}
 
  -----
 
|
 
  -----
 
{..219}
 
{.....}
 
{.....}
 
{...76}
 
{.....}
 
{....2}
 
  -----
 
|
 
  -----
 
{..120}
 
{.....}
 
{.....}
 
{...33}
 
{.....}
 
{....2}
 
  -----
 
|
 
WHILENOT:
 
ANDOR {value}
 
    [NOT] {condition0}
 
    [[NOT] {condition8}]
 
GOTO_IF_TRUE ENDWHILE
 
    {consequence}
 
    GOTO WHILENOT
 
ENDWHILE:
 
|}
 
  
===REPEAT===
+
=Code layout=
  
Seemingly, the [[#REPEAT|REPEAT]] control flow is the first construct ever optimized as a result of a possible R* compiler fault. Moreover, it sounds ambiguous as it loops at least once. This was probably the intention of R* programmers, that is iterating at least once else the construct is useless. However, there are few chance they decide to use such structure to avoid some conflict with some other constructs:
+
==Main script and Main extensions==
  
{|width=100%
+
==Scripts and Streamed scripts==
!width=50%|Decompiled
 
!colspan=2|G/L {{icon|vc}} {{icon|sa}} {{icon|lcs}}
 
!width=1px|G/L {{icon|vcs}}
 
!Compiled
 
|-
 
|
 
REPEAT {times} {varname}
 
    {consequence}
 
ENDREPEAT
 
|width=1px|
 
{....4}
 
  -----
 
{.....}
 
{....8}
 
{...40}
 
{...77}
 
|width=1px|
 
{....5}
 
  -----
 
{.....}
 
{....9}
 
{...41}
 
{...77}
 
|
 
{....4}
 
  -----
 
{.....}
 
{....7}
 
{...21}
 
{...34}
 
|
 
{varname} = {value0}
 
LOOP:
 
{consequence}
 
++ {varname}
 
    {varname} >= {valueN}
 
GOTO_IF_FALSE LOOP
 
|}
 
  
===SWITCH===
+
==Subscripts and Mission scripts==
  
In {{icon|sa}}, the [[#SWITCH|SWITCH]] control flow is more complex and efficient because the game uses internally a [[Wikipedia:Binary_search_algorithm|binary search algorithm]] to jump at the [[#Labels|label]] that matches with the value of a particular case. This method requires a known amount of cases which is up to 75. When a case is true, a ''consequence'' is executed and the code jumps to the end of the construct, otherwise the ''alternative'' may be performed. As the code is unoptimized, the [[#GOTO|GOTO]] of the last case is still compiled even though its label points right after the command mentioned earlier:
+
[...] The so-called official compiler is custom by ''War Drum Studios''.
  
{|width=100%
+
<del>[...] '''LOAD_SPRITE''' expects a variable-length text label of 14 characters but then the game code enforces an useless uppercase conversion of a fixed-length 15 character identifier, incorrectly including the null-terminator at 15th position during the process.</del>
!width=20%|Decompiled
+
[...] Variable and text label identifiers are limited to 40 characters, the reason why 4 '''TEXT_LABEL32''' parameters are needed to store 128-byte strings. They can be passed individually as 32-byte aligned blocks but the first character is trimmed out.
!width=1px|{{icon|sa}}
+
[...] In the last Trilogy and Stories chapter, text labels must begin with an alphanumeric character or an underscore, provided that they aren't valid integer or floating-point literals.
!Compiled
+
[...] It is prohibited to fetch or handle a long text label using a variable of shorter length but this one is rather passable to those text label parameters also permitting long-lengthed literals.
|-
+
[...] Variable-length text labels are kind of Pascal strings. Reference: https://en.wikipedia.org/wiki/String_(computer_science)#Length-prefixed.
|
 
SWITCH {varname}
 
    CASE {value0}
 
        {consequence}
 
        BREAK
 
    [CASE {valueN}
 
        {consequence}
 
        BREAK]
 
    [DEFAULT
 
        {alternative}
 
        BREAK]
 
ENDSWITCH
 
|
 
{.2161}
 
{.2162}
 
  -----  
 
{.....}
 
{....2}
 
  -----  
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
{....2}
 
  -----  
 
|
 
SWITCH_START {varname} {numcases} {isdefault} DEFAULT {value0} CASE0 ...
 
[SWITCH_CONTINUED ... {valueN} CASEN [-1 ENDSWITCH]]
 
CASE0:
 
    {consequence}
 
    GOTO ENDSWITCH
 
[CASEN:
 
    {consequence}
 
    GOTO ENDSWITCH]
 
[DEFAULT:
 
    {alternative}
 
    GOTO ENDSWITCH]
 
ENDSWITCH:
 
|}
 
  
In {{icon|lcs}} and {{icon|vcs}}, such control flow is a set of nested [[#IF|IF]] constructs which causes a very slight loss of performance by considering that [[#ANDOR|ANDOR]] isn't compiled:
+
[...] In the last Trilogy chapter, local variables start at index 34 in mission scripts so local timers are also ignored.
  
{|width=100%
+
[...] Some commands have non-typified arguments which are referred to as parameters.
!width=50%|Decompiled
 
!colspan=2|G/L {{icon|lcs}}
 
!width=1px|G/L {{icon|vcs}}
 
!Compiled
 
|-
 
|
 
SWITCH {varname}
 
    CASE {value0}
 
        {consequence}
 
        BREAK]
 
    [CASE {valueN}
 
        {consequence}
 
        BREAK]
 
    [DEFAULT
 
        {alternative}
 
        BREAK]
 
ENDSWITCH
 
|width=1px|
 
  -----
 
{...56}
 
{...77}
 
{.....}
 
{....2}
 
  -----
 
{...56}
 
{...77}
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
  -----
 
  -----
 
|width=1px|
 
  -----
 
{...57}
 
{...77}
 
{.....}
 
{....2}
 
  -----
 
{...57}
 
{...77}
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
  -----
 
  -----
 
|
 
  -----
 
{...27}
 
{...34}
 
{.....}
 
{....2}
 
  -----
 
{...27}
 
{...34}
 
{.....}
 
{....2}
 
  -----
 
{.....}
 
  -----
 
  -----
 
|
 
CASE0:
 
    {varname} = {value0}
 
GOTO_IF_FALSE CASEN
 
    {consequence}
 
    GOTO ENDSWITCH0
 
CASEN:
 
        [{varname} = {valueN}
 
    GOTO_IF_FALSE DEFAULT
 
        {consequence}
 
        GOTO ENDSWITCHN
 
    DEFAULT:
 
        [{alternative}
 
    ENDSWITCHN:]]
 
ENDSWITCH0:
 
|}
 
  
==Optimization==
+
[*] No more than 8 conditions are allowed per check
 +
[*] Checks are not short-circuited at runtime meaning all conditions are executed before branching
 +
[*] NAND and NOR might have been planned considering ANDOR values (0, 1 to 7, 21 to 27). Hint: mention the compare flag.
 +
[*] ANDOR is not compiled in Stories games for one condition checks
 +
[*] IFNOT and WHILENOT are not supported in VC and SA because GOTO_IF_TRUE is not handled by game code there.
 +
[*] REPEAT is supported since VC
 +
[*] REPEAT cycles at least one-time
 +
[*] REPEAT wrongly accepts a value lesser than 1 for the times argument
 +
[*] SWITCH is supported only in SA
 +
[*] SWITCH allows fall-through CASEs so BREAK is not mandatory
 +
[*] SWITCH handles up to 75 CASEs chosen as a result of a binary search which requires CASEs to be sorted on compilation
 +
[*] In contrast to scope-free subroutines which feature no argument...
 +
[*] Boolean-valued gosub and function
 +
[*] Recursion is allegedly not supported albeit gosubs and functions have 8 global levels of nesting in Trilogy chapters and 16 in Stories'.
 +
[*] Decision-making statement (IF, IFNOT, SWITCH)
 +
[*] Count-controlled loop (REPEAT)
 +
[*] Condition-controlled loop (WHILE, WHILENOT)
 +
[*] An unconditional branch, despite considered harmful in the programming literature, is the only way to go for breaking loops prematurely and enhance the simplistic code logic.
 +
[*] Infinite loops are achieved by means of a backward GOTO
  
In {{icon|lcs}} and {{icon|vcs}}, whenever a ''single condition'' is checked [[#ANDOR|ANDOR]] doesn't get compiled cause no [[#Logical|logical operator]] ('''AND''', '''OR''') is used and so they become really useless. Its lack increases the script efficiency a lot. However, the jump of the '''ELSE''' clause of an [[#IF|IF]] statement which points to the end of the construct is still compiled after a [[#GOTO|GOTO]]. Furthermore, ''Stories Games'' come with an improved data type managing which causes a considerable decrease of the compiled file size.
+
[...] Although it is able to infer nothing regarding the aim exclusive mission scripts were planned for which swings among testing, mission pack and multiplayer purposes, there are bunch of irrefutable evidences implementation-wise. The functionality is analoguous to usual mission scripts but, on the other hand, the opposing kind of them is totally superseded and completely overlooked during the compilation phase. Their coexistence is perfectly legal, though leftover launchers are bad style and dangerous in so far as noncompilable unless an exclusive variation is also provided. Additionally, they are a lot limited in quantity: the first Trilogy chapter expects in theory only an intro mission ('''INTRO''', shame not at runtime), the second chapter an auxiliary initialization mission ('''INITIAL'''), the third one an extra initialization mission ('''INITIL2''') and whereas Stories chapters have game provision for such feature along the lines of Vice City, their compilers have allegedly no support because of deprecation (the trigger command is still there, however the too many initialization missions seen in the script binary might speak from themselves). Hints: one's complement
  
=Tools=
+
[...] Early in development, '''STREAM_SCRIPT''' was compiled to '''STREAM_SCRIPT_INTERNAL'''.
  
* [[SCRambl]] - an open-source tool provided by {{U|Deji}}
+
Despite streamed scripts may receive an entity handle as input parameter, they are not necessarily callable and so an on-top, unreachable, explicit entity's creation is due:
* [[Mission Scripting Tools]]
 
  
=See also=
+
{
* [[SCM language III/VC definitions]]
+
    VAR_INT test_char sanity
 
+
=External links=
+
    sanity = 0
 
+
    IF sanity = -1
*{{icon|2}} [http://gtamp.com/GTA2/gta2script.7z DMA's official GTA2script Compiler V9.6], [http://projectcerbera.com/gta/2/tutorials/scripting DMA's official GTA2script information] - found into the game copy
+
        CREATE_CHAR PEDTYPE_CIVMALE male01 0.0 0.0 0.0 test_char
*{{icon|3}} [https://www.dropbox.com/s/bwxqe33c8ownfc8/gta3ta_source.rar GTA III 10th Anniversary source] - found into the ''iOS'' game copy
+
    ENDIF
*{{icon|3}} [http://pastebin.com/Pfwscpeh GTA III unofficial main.sc] - Reconstruction of main.sc, missing from the iOS source code, by {{U|Link2012}}
+
}
*{{icon|3}} {{icon|vc}} [http://pastebin.com/raw.php?i=T73rCdDd GTA III/VC unavailable script commands (possibly NOP'd)] - some sort of information by {{U|Wesser}} as a result of the reverse-engineering applied to the [http://www.rockstargames.com/ Rockstar Games]' official '''GTA3 Script Compiler V413'''
 
*{{icon|3}} {{icon|vc}} [https://www.dropbox.com/s/7xgvqo8b9u1qw02/gta3sc_v413.rar Official GTA3 Script Compiler V413] - found into the ''GTA VC 10th Anniversary'' copy
 
*{{icon|3}} {{icon|vc}} [http://pastebin.com/raw.php?i=Pjb0Ezkx GTA3 Script Compiler V413 Compilation Strings] - a list by {{U|Wesser}} of all the error messages the compiler can throw and more
 
*{{icon|sa}} [http://pastebin.com/raw.php?i=Ra9JLLeN GTA SA PC/PS2/XBOX script commands], [http://pastebin.com/raw.php?i=kCwS6rdG GTA SA Mobile script commands] - taken directly from the ''Android'' application and rearranged by {{U|Wesser}}
 
*{{GTAF|441362|Reconstructing the III .sc language}} &ndash; a post by {{U|NTAuthority}}
 
  
{{N|SA|VC|3}}
+
This scenario also extends to any embedded script or script file
  
[[Category:Mission Script]]
+
Originally, explicit entity creations are conventionally put on top of any sort of script by mean of unreachable code to confer specific entity types to declared variables for better error-checking:

Revision as of 22:36, 26 April 2017

Test link (please, submit changes with "Show preview"): http://www.gtamodding.com/index.php?title=SCM_language&action=edit (login required)

This section deals with the native script language syntax of GTA 3 series, nothing other than III, VC, SA, LCS and VCS.
It may incorporate nonstandard specifications due to the fact R* hasn't published enough documentation about yet.

On the occasion of the Grand Theft Auto III's 10th Anniversary, after a long period of darkness where we fell about the real scripting language syntax, R* finally treated us (or was it, as it seems, a War Drum Studios sloppy oversight?) by attaching part of its own original source code into the mobile release, available for iOS and Android devices. As far back as 2001, a snip of some debugging scripts has been already provided with main.sc and debug.sc files that were allegedly meaningful for a sort of script version checker uncut on debug builds. Nonetheless, many secrets are still unrevealed, thus some things cannot be fully documented and so they can be merely guessed. The .scm format abbreviation is one of countless proofs of this inconvenience, which may stand for Script Multifile; .scc, in turn, might be the short form of Script Compiled though we would better predilige the Combinedfile wording. No doubt come with source files, whose .sc extension is the contraction of Mission Script. Although we have enough information to suppose the currently unknown mysteries of the used language, we still have no safe clue about what was its original denomination. Furthermore, it is a matter of fact that R* developers have been left untouched the miss2 executable filename of the third generation compiler since the chapter 2. In this connection, we could imagine the newer scripting language is a variant or an evolution of the GTA2script (sometimes referred to as GBHscript), which label expressly popped up in the ancient documentation by DMA Design Ltd (at present Rockstar North). Therefore, we are almost sure to say the language name is most likely GTA3script (as-is casing). However, it is definitely based on BASIC.

Fundamentals

Comments

Codes are usually self-explanatory for the author but large sources can compromise everyone's management capability, that means some annotation can save much time on the long-term particularly when being stuck trying to understand old stuff which should never happen in the first place, not to mention team mates would certainly blame the original writer on each revision and slow down the completion of cooperative projects. Sometimes, it is also required to temporarily/permanently disable code lines for testing purposes. Fortunately, the language supports the following typologies of comments:

  • Single-line comment, prefixed with // (two forward slashes), which extends till the end of the line. Everything is ignored inside: // Some comment.;
  • Multi-line comment, enclosed with a pair of /* (a slash plus an asterisk) and */ (the other way around), which covers a cricumscribed text area. Several blocks can be nested together: /* Some /* comment */ . */.

Delimiters

Conventionally, lines can be splitted into various regions in order to enhance the code legibility through bracket-delimited and/or comma-separated elements. As being pure white-spaces, the opening parenthesis delimiter doesn't necessarily need to match the closing counterpart and viceversa. The only tangible use of separators carried out in public sources is related to inline declaration of multiple variables, text keys of print-commands and SETUP_ZONE_PED_INFO but codes can be organized to one's liking. Here are some demonstrations:

VAR_INT joeys_buggy, swank_taxi
PRINT_NOW (ASUKA) 2000 1
SETUP_ZONE_PED_INFO CHINA DAY (30) 350 600 0 (0 0 0 0) 0

Integers and Floating-points

Labels, Text labels and Strings

Thanks to the beneficial code fragmentation, the source is subject to external file inclusions and variegated in-file unconditional branches involving embedded code blocks diversification. Both kinds of partitioning are accomplished respectively through the specification of:

  • Filenames, that is special labels which somehow resemble legit pathnames, starting with any valid pathname character but not containing whitespaces. They are relative to the root path deriving from the .sc extension removal of the main script full path where files are searched in by default: X:\folder\main. Subfolders are scanned as well:
    • Till the first tree level if inside one of the subdirectories: X:\parent\main\child;
    • Till the second tree level if inside one of the parent directories: X:\parent or X:\parent\main;
    • Indefinitely (unlimited recursion till the maximum path length allowed).
The .sc extension at the end of filenames is mandatory else an argument mismatch is warned, by contrast the main script can have any extension to which m (multifile) or c (combinedfile) is appended in the target pathname. Due to a Cd image system limitation, all sorts of filename must be shorter than 20 characters and conventionally they must be free of extra dots for streamed scripts.
  • Label references, that is unique string identifiers suffixed by a colon which identify a precise location within the common (main script, main extensions and subscripts) or the actual (mission scripts and streamed scripts) script space. Basically, they represent the target position of either goto-like, script starter or function caller commands: my_label_ref: (on a new line). Weirdly enough, label references may begin with any character alike filenames despite they are susceptible to the same restrictions of string identifiers whenever passed as arguments but must not exceed 38 characters, colon excluded, either way. Whereas these are not commands, anything else can follow next to and being inlined so long as a splitting character is inserted.

That said, labels are essentially user-supplied string identifiers whose existence is verified. Text label identifiers are not fully bound to this rule (except script names) since they are massively employed as main/mission text keys or whatever referring to an internal resource, which the game handles according to a well-defined associative scheme. Notoriously, identifiers length is anything but expensive for readability reasons, in addition they do not even offer the ability to insert white-spaces or other inadmissible characters owing to the by-design absence of delimiting tokens. <incorrect>At this matter, variable-length strings and debugging texts sent as 128-byte string literals are enclosed by " " (double quotes):

CUSTOM_PLATE_FOR_NEXT_CAR CAR_TAMPA "_FELTCH_"</incorrect>
SAVE_STRING_TO_DEBUG_FILE "CURRENT_WANTED_LIST = "

Empty text labels are impracticable, though NIL compiles a NUL-string in the last Stories chapter[no source] – as reported by some indiscreet sources, the rearrangement of crucial commands signals a syntax enhancement the language has undergone which sees delimited strings superseding text labels, lowly probable because string constants are still disallowed for multi-type parameters; as previously assumed, instead, DUMMY could have been the placeholder keyword but a text key exists actually, while a single _ (underscore) is more Python-oriented (used as a throwaway variable). It's worth noting string literals and text labels are not interchangeable because of their syntactic differences even if they present semantic similarities, moreover text labels do not ever interfere with command names and string constants. A final quirk to note concerning labels as a whole is they are automatically converted to upper case: this obvious evidence proves identifiers and whatnot are all case insensitive with the exception that 128-byte strings are left as-is for remastered game builds.

Data types

Forasmuch as the language obeys the strong typing paradigm, the syntactic elements that denote a value during execution do have fixed data types, most of which are appended as a suffix at variable declaration. Their conspicuous assortment is listed below:

Name Format Size Range Game
support
Variable
support
Is
basic
Single-typed
LABEL String identifier
(translated to offset/index)
4 -231 to 231-1 Since GTA III None
INT Signed integer Since GTA III
FLOAT Q11.4 fixed-point 2 -211 to 211-2-4 GTA III only
IEEE-754 floating-point 4 ±3.4×10±38 Since Vice City
TEXT_LABEL UTF-8 null-terminated
string identifier
8 1 to 7 Since GTA III San Andreas and Vice City Stories
TEXT_LABEL16 16 1 to 15 San Andreas only San Andreas only
TEXT_LABEL32 UTF-8 null-terminated
string identifier
(4 contiguous blocks)
32×4 1 to 127 None
Multi-typed
PARAM Same as INT and FLOAT Since GTA III
Same as TEXT_LABEL Since Vice City Stories
STRING UTF-8 string
(non null-terminated)
1..127 1 to N-1 San Andreas only None
Same as TEXT_LABEL/16
(variable-only)
San Andreas only

Some tiny caveats about immediate numeric fields:

  • String constants are compatible with integer parameters;
  • Literals must begin with a number or - (minus sign) or rather . (decimal point, for float values);
  • Integers allow only the decimal notation;
  • Floats disallow scientific notation and such;
  • Integral and fractional parts are singularly omissible;
  • F or f suffix can be appended next to (quite unused/useless).

Immediates and Variables

Data can take the appearance of a few expressions varying from numeric, text label and string literals each of which occupies a certain area of storage with unfixed size. Immediates can also be preserved for later use and therefore reserve space over the private script memory corresponding to a variable. The strongly-typed language property imposes to explicitly declare variables anywhere in the current scope, namely the context inside which they are visible for usage. Sensibly, declarations should figure beforehand but likewise it is allowed for accessing backward declarations. Variables accessible from any location are marked as globals (starting from offset 8, occupying lots of space in the script multifile, up to 64 kibibytes) and their declaration is achieved by prepending the VAR prefix followed by one of the basic data types (multiple declarations of the same type can be inlined), both separated by an in-between underscore:

VAR_INT player scplayer
VAR_FLOAT x_float, y_float, z_float
VAR_TEXT_LABEL interior_name
VAR_TEXT_LABEL16 shop_item

Globals are capable of being selectively marked as saveable using the SAVE_VAR prefix, in order to restore their value on savegame loading and free generic variables. In Trilogy chapters, if enabled properly in a hacky manner, these are solely common variable declarations with no additional purpose, a plan not gone through. On the other hand, globals declared within the mission context are not visible outside in Stories chapters since they overlap the same space, making a discernment among true and al-most globals. However, there's no exact rule for variable naming apart they must begin with a letter and never end with a colon, just like text labels. It's preferable definitions shall not contain operator tokens to prevent any parsing ambiguity plus, most importantly, they must not conflict with string constants and local timers. Nevertheless, text labels and variable names semantics may collide: in this case, the formers have priority over the latters unless a preceding dollar sign) is added:

PRINT_BIG TEXTKEY 5000 2  // Compiles a text label literal.
PRINT_BIG $textkey 5000 2 // Compiles a text label variable.

Despite variables are freed and zero-initialized at runtime on new/load game or script allocation in broad terms, statistical information are still gathered whenever they are read before being written, besides if they are never read or never written (passing a variable as reference has no effect onto the content). Furthermore, if a variable is set to hold an entity handle (alias unique index) returned by a specific create-command it cannot be assigned to any other entity-command of different kind or none, including the forseeable assignment operations. This restriction propagates on script and function callings as well: starting/streaming the same script or calling the same function multiple times with variables of dissimilar entity types is forbidden if triggers are encountered prior the script or function local scope is fetched, in which case entities are explicitly initialized in the form of unreachable code:

{
    LVAR_INT test_char sanity

    sanity = 0
    IF sanity = -1
        CREATE_CHAR PEDTYPE_CIVMALE male01 0.0 0.0 0.0 test_char
    ENDIF
}

Local scope

Once a script is started/streamed or a subscript/mission is launched, a local variable space of 72 (16+2 × 4, III/Vice City), 136 (32+2 × 4, San Andreas) or 424 (96+8+2 × 4, Stories) bytes is also reserved. As opposed to global variables, locals have visibility only inside a particular region of the source code and are preceded by the LVAR prefix at declaration within an unnestable block embraced by curly brackets:

{
    LVAR_INT pickup message_num
}

Local names do not override global definitions, they must not collide together otherwise a warn is issued. In the last Trilogy chapter, locals are mainly static variables whose space (having a size of 4096 bytes, 1024×4) is shared among each mission thus they are reasonably more abundant in this context. Beyond user-defined locals, predefined TIMERA and TIMERB variables are provided: these timers measures the playing time milliseconds passed since the script beginning but they can be reset just fine. As deducible, any script file inclusion within a local scope does inherit no local variable even for the unassuming foreign gosub.

Arrays

Since the last Trilogy chapter, instead of declaring multiple scalar variables of same type, an unidimensional, numeric (unassociative) array can be defined. Each element is accessed through either a positive, zero-based[no source], 8-bit unsigned number or a variable index embraced by a pair of square brackets on assignment or argument passing. On declaration, the said brackets enclose the array size which mustn't be bigger than 255 units:

VAR_INT prop_assets[32]
CREATE_FORSALE_PROPERTY_PICKUP -1969.27 282.47 34.6 50000 PROP_3 prop_assets[0]

In sooth, one-based arrays were already supported in the second Trilogy chapter but they missed the intrinsic data type, giving no reference point on how to interpret the compiled operands, producing corrupted intermediate code because of fall-through reading. There is no precedent to safely assert that arrays became zero-based later on the language evolution but what is certain is this sort of indexing lines up immediate with variable indices. Oddly, as a result of the unidimensionality constraint implementation, a complementary yet nonfactual identifier can follow the closing bracket immediately afterwards with no redundancy notice (i.e. prop_assets[0]anything). Moreover, scalar variables have an implicit array size of one element which is needlessly accessible and plus the index part of the first element of an array is in turn omissible, everything notwithstanding the misleading declaration. Granted that brackets do not encompass any separator character, array indices reject string constants but admit local timers.

String constants

Very often, numeric literals express arbitrary values which are far from being self-documenting without descriptive labels belonging to a list of predefined names. These strings or enumerations are guaranteed to store an immutable constant and must forcibly pertain to the required namespace if passed as arguments unless, if and only if no namespace is set, the default constants TRUE/FALSE, ON/OFF, DAY/NIGHT or KILLFRENZY statuses are supplied:

CHANGE_BLIP_DISPLAY blip1_jm1 BLIP_ONLY
flag_car_blip_displayed_jm1 = TRUE

Assignments and comparisons do not suffer such a restriction and, what's more, in case of too long lines (wider than 255 characters) immediates can safely replace string constants to shorten the exceeding length and fall within the limits. During the development stage, the game's map experiences lots of continuous changes that make the management of objects, as a result of having a fixed indexing, pretty awkward without taking into account their bulk amount. In this respect, parameters expecting level objects are able to define the used objects (no more longer than 23 characters) under the hood, bringing them together in a sorted array whose criteria depends on the order of their appearance, something other than the default models which are hardcoded (for peds, cars, weapons, wheels, cutscene objects and the like). A blank, unavailable object is always reserved, shifting ahead each next negated position becoming one-based. Negative indices assure models fit in the used objects array, according to which the runtime matches the right index through a lookup table:

REQUEST_MODEL bridgefuka // First use ever. It compiles -1 from now on.
REQUEST_MODEL bridgefukb // First use again. This time it compiles -2.
LOAD_ALL_MODELS_NOW
CREATE_OBJECT_NO_OFFSET bridgefuka 715.746 -937.908 40.194 damagea
CREATE_OBJECT_NO_OFFSET bridgefukb 787.835 -939.24 38.971 damageb

The lack of error-checking requires a meticulous handwriting to avoid script deadlocks at runtime, the reason why both default models and level objects are loaded straight from IDE files for Vice City's remastered build. Nonetheless, iterating among several objects can be very expensive for a poorly optimised, rough compiler even on fast machines, not to mention namespaced constants are likely to collide without specializing prefixes (i.e. SNIPER camera mode and weapon name, formerly WEAPON_SNIPER), enough to revert back thereafter. Assignments and comparisons have no clue about used objects and are therefore not designed to accommodate or implicitly define one on their own, because they are supposed to be strict with the identifier existence as being more prone to work out with variables. This concept somehow extends to those parameters not featuring used objects as a general rule. If an unusual application needs to take place, making use of non-inlined CONSTANT_INT declarations would hint the compiler to treat unequivocally the specified string constants as used objects, truly defining a new one on the first practical usage wherever it occurs and not yielding an undefined variable error:

CONSTANT_INT cj_pizza_1
CONSTANT_INT cj_pizza_2
VAR_INT test_model1 test_model2

REQUEST_MODEL pizzahigh  // -1
test_model1 = cj_pizza_1 // -2
test_model2 = cj_pizza_2 // -3
REQUEST_MODEL test_model1
REQUEST_MODEL test_model2

Any string constant passed in place of an object model compiles a used object indiscriminately assuming no CONSTANT_INT declaration, preventing redefinitions (whether default or namespaced), does exist. Messing around with frequent compiler tool recompilations can be tedious solely to establish broad, same-indexed or math-related string constants but fortunately, in the last Trilogy chapter, the language offers the opportunity to settle user-supplied default constants for numeric literals using CONST-prefixed declarations which, alike for variables and CONSTANT_INTs, are backward accessible:

CONST_INT gf_date_active 1
CONST_FLOAT math_pi 3.1415927

SET_BIT gf_date_flags gf_date_active
rad_angle = deg_angle * math_pi
rad_angle /= 180.0

Given that default models are also default constants in Stories chapters[no source], default constants and used objects count as pseudoconstants: contrary to what namespaced constants entail, generic alternatives are favoured on assignment or comparison command pairing. It should be pointed out that, due to a critical compiler bug, the high 16 bits of the value held by a namespaced constant are unexpectedly discarded on assignment or comparison and that, if set, the 16th bit yields a nonexistent variable error (i.e. THREAT_GANG9 flag) prior Stories chapters, where a default constant is compiled only if the low 16 bits represent a value lesser than -1[no source]:

Mission script Script multifile
SET_CHAR_THREAT_SEARCH test_char THREAT_GANG_GOLFER
SET_CHAR_THREAT_SEARCH test_char THREAT_GANG9
SET_CHAR_THREAT_SEARCH test_char THREAT_EMERGENCY
threat_flag = THREAT_GANG_GOLFER
threat_flag = THREAT_GANG9 // Ill-formed in Trilogy.
threat_flag = THREAT_EMERGENCY
SET_CHAR_THREAT_SEARCH test_char 16384
SET_CHAR_THREAT_SEARCH test_char 32768
SET_CHAR_THREAT_SEARCH test_char 65536
SET_VAR_INT_TO_CONSTANT threat_flag 16384
SET_VAR_INT threat_flag 32768
SET_VAR_INT_TO_CONSTANT threat_flag 0

This inconvenient unwittingly affects real code in Liberty City Stories in one circumstance. On a final note, string constants are incompatible with optional arguments and thus taking advantage of a temporary variable would overcome this syntactic limitation.

Operators

As soon as a numeric or text label variable is declared, it can be subjected to algebric operations and/or logical comparisons by virtue of several operators. Their support is sadly very primitive, in fact the ability to establish complex expressions with parentheses and such is not featured albeit one and only binary operation is enabled to follow the basic assignment. In this regard, the variable being assigned to the lvalue cannot be the same as the outer rvalue for non-commutative operations: VAR1 = THING - VAR1, VAR1 = THING / VAR1, VAR1 = THING +@ VAR1 and VAR1 = THING -@ VAR1 are all ill-formed. This issue arises because the explicit usage of a temporary variable is needed which would be harmful for the compiler to waste by itself under the hood, thus here expressions are necessarily made up of distinct two-operand instructions, that is the lvalue content is initialized prior encoding any supplementary rvalue arithmetic:

//VAR1 = 1 - VAR1 // Invalid, cause VAR1 = 1; VAR1 -= VAR1 doesn't make sense. It would perform 1 - 1 = 0.
VAR1 = 1 - VAR2   // Valid, cause VAR1 = 1; VAR1 -= VAR2 doesn't null itself like above.
VAR1 = 1 + VAR1   // Valid, addition (as well as multiplication) is commutative so this is compiled to VAR1 += 1.

The subtraction of positive or negative rvalues necessitates a splitting character in order to discern the infix operator unambiguously, which would be treated as part of the literal or a variable decrement otherwise (i.e. VAR1 = VAR1 -1 or VAR1 = VAR1 --1). Typically, string constants are not suitable for math calculations because of the lack of pairable command alternatives but even so they are semantically contemplated as long as a namespaced constant is provided as the inner rvalue of a compound assignment or a default constant is passed to any rvalue. Another clear limitation is prefix and postfix operators do not apply onto arguments, hence there's no concrete differentiation. However, the language introduces the timed addition/subtraction to looply update a variable in a frame-rate independent way, the cast assignment to do a mutual conversion between integers and floats but it doesn't give support for the modulo operation as its predecessor. The inequality comparison was planned but quickly gone obsolete[no source] – availing of the negated form of the equality operator would have sounded more intuitive but one should be aware the not-flag is not bundled with the command index when pairing command alternatives. Due to a programmers' negligence, the local-global in/equality comparison between integer or float variables is not feasible except in the last chapter of Trilogy and Stories series.

Arithmetic operators

Name Syntax INT FLOAT TEXT_LABEL/16
Basic assignment
VAR = THING
Addition
THING + THING
Subtraction
THING - THING
Multiplication
THING * THING
Division
THING / THING
Timed addition
THING +@ THING
Timed subtraction
THING -@ THING
Increment Prefix
++ VAR
Postfix
VAR ++
Decrement Prefix
-- VAR
Postfix
VAR --

Compound assignment operators

Name Syntax Meaning INT FLOAT
Addition assignment
VAR += THING
VAR1 = VAR1 + THING
Subtraction assignment
VAR -= THING
VAR1 = VAR1 - THING
Multiplication assignment
VAR *= THING
VAR1 = VAR1 * THING
Division assignment
VAR /= THING
VAR1 = VAR1 / THING
Timed addition assignment
VAR +=@ THING
VAR1 = VAR1 +@ THING
 
Timed subtraction assignment
VAR -=@ THING
VAR1 = VAR1 -@ THING
Cast assignment
VAR =# THING
AS IS

Comparison operators/relational operators

Name Syntax INT FLOAT TEXT_LABEL/16
Equal to
VAR = THING
Not equal to
VAR <> THING
Greater than
THING > THING
Less than
THING < THING
Greater than or equal to
THING >= THING
Less than or equal to
THING <= THING

Logical operators

Name Syntax
Logical negation
NOT
Logical conjunction
AND
Logical disjunction
OR

Commands

The imperative programming paradigm provides for a conglomerate of commands the script is filled up of and structured in, which are seen as orders to instruct the execution of the relative built-in portion of game code at runtime. Their invocation is faithful to procedure calls: they may feature zero or more parameters of any type or indefinite, depending on whether or not qualified as optional, and receive as much as arguments either by-value or by-reference affecting the read/written access accordingly (do note a pure reference does not initialize anything). Alike procedures, no assignable result is returned but a boolean state is catched anyway on conditional evaluation. One major peculiarity is command names are usually identified by a verb in its imperative form:

GIVE_WEAPON_TO_CHAR mafia_1X WEAPONTYPE_UZI 999

Historically, complex commands stand out over the simple counterpart in the way they are implemented compiler-wise:

  • Variable and local scope declarators are true, non-compilable commands;
  • File includers assemble multiple files in a single source and require the rightmost argument to be a filename if inside the main script or main extension, otherwise START_NEW_SCRIPT is expected (this behaviour is originally buggy);
  • Script starters/streamers and function callers involve a type-checking of the optional parameters passed basing on the variables declared in the local scope, whose opening brace must precede the script label reference even few lines earlier since the second Trilogy chapter (the first one needs it right after instead but it's likely it is merely due to good style programming);
  • SCRIPT_NAME defines an univocal script name immune to redefinitions but not among mission scripts because they can only run one at a time;
  • SKIP_CUTSCENE_START and SKIP_CUTSCENE_END mark a specific region of code (mostly inside mission scripts). Several blocks cannot be nested together;
  • Dynamic counters expect one argument to be a zero-value which gets updated automatically/internally on compilation, keeping track of the times few commands are used (unless, if applicable, the only acceptable argument is a variable, then the command is not taken into account) or the total sum of the first argument values (of course, non-immediates are discarded):
Initializer Dependency/ies Check
arg.
Is
addend
SET_COLLECTABLE1_TOTAL CREATE_COLLECTABLE1
SET_PROGRESS_TOTAL PLAYER_MADE_PROGRESS
SET_TOTAL_NUMBER_OF_MISSIONS REGISTER_MISSION_PASSED
REGISTER_ODDJOB_MISSION_PASSED
SET_MISSION_RESPECT_TOTAL AWARD_PLAYER_MISSION_RESPECT

A third category consisting of special commands or command pairs, is able to look for the matching signature into a list of akin commands on the basis of the data type of the passed arguments and choose, accordingly, the equivalent alternative in a direct and effortless way. Although the alternative commands are also accessible by and can share the same definition, the selection process is not entirely conform to function overloading because these still maintain their own unique name, they are just smartly resolved through common aliases. The complete lists are reported below:

Trilogy and first Stories chapters Second Stories chapter
Command Game
support
Alternative
Command
Alternative

Control flows

Insofar as subprograms, scripts are organized in a systematic arrangement through which goto branches, subroutine branches, function calls and returns are executed to form control flow statements and structures. These alter the program counter most of the time affecting the top-down order all commands are fetched by. Facing off code duplication is quite recurring especially when the tasks to perform vary only in the input data, the case where a piece of code or subroutine, built once in the source, is invoked many times from various different places and returns back, as if the GOSUB statement is substituted in-place by the subroutine's body without RETURN during the control transferring, shrinking long codes and reducing the script overall size. The flow of execution can also be broken up conditionally by means of:

  • Decision-making structures (IF, IFNOT, SWITCH), which evaluate the result of one or more conditions and choose what path to follow based off the trueness or falseness of the check being tested. Been deemed the most basic tool of structured programming, IF is a bidirectional statement that proceeds with the execution of the underneath code only if the test carried out evaluates to true otherwise it transfers the control next to ENDIF, unless a preceding and optional ELSE clause, establishing an alternative path, is specified. In the first Trilogy and both Stories chapters where GOTO_IF_TRUE is handled by game code, the barely used IFNOT can be deployed as a placeholder to easily invert the compare-flag, a boolean state which is set or cleared as a result of the bitwise conjunction or disjunction with the true/false state caught by a condition, applying the inversion according to the presence of the not-flag before updating. Logical operators make possible the connection among multiple conditions via the AND conjunction and OR disjunction giving the chance to verify if conditions are all true or if just one of them is satisfied bearing in mind that the NOT negation, inverting the boolean state of a single condition, may be supplied. Connectivity information are held by ANDOR, whose argument depicts a value in the range [1,8) or [21,28) for logical conjunction and disjunction respectively, limiting the amount of total conditions to provide to a maximum of 8 per check (the prominent intervals discrepancy also suggests NAND and NOR operators might have been a plan). A value of 0 does nothing relevant functional-wise at runtime, what led programmers to not compile said command in such a situation for Stories chapters. The inability to create subexpressions enforces to not combine AND with OR in a check, plus evaluations are eager and therefore not short-circuited meaning all conditions are executed prior potentially branching through GOTO_IF_FALSE in the common case after the compare-flag gets processed. Nesting lots of IF-ELSE-ENDIF structures of one-condition checks testing the equality of the same variable against a few integer literals or string constants can add a ridiculous code redundancy and performance overhead, sorted out in the last Trilogy chapter thanks to the introduction of the SWITCH statement, a multiway statement either branching to the switch section labelled by fall-through CASE statements of which one passses a value that shall match the variable content to compare or optionally branching to DEFAULT in the worst-case scenario, each ending with a nonmandatory BREAK statement goto-ing past ENDSWITCH. On compilation, the implementation somehow mimics the pattern of a jump table sorting case label references by value to fulfil the runtime's binary search among at least 1 of 75 entries (default case aside);
  • Looping structures (REPEAT, WHILE, WHILENOT), which repeatedly execute a block of code certain number of times (count-controlled) or by constantly and successfully evaluating a check (condition-controlled).

IF/IFNOT-ELSE-ENDIF SWITCH-CASE/DEFAULT-BREAK-ENDSWITCH

WHILE/WHILENOT-ENDWHILE REPEAT-ENDREPEAT

Code layout

Main script and Main extensions

Scripts and Streamed scripts

Subscripts and Mission scripts

[...] The so-called official compiler is custom by War Drum Studios.

[...] LOAD_SPRITE expects a variable-length text label of 14 characters but then the game code enforces an useless uppercase conversion of a fixed-length 15 character identifier, incorrectly including the null-terminator at 15th position during the process. [...] Variable and text label identifiers are limited to 40 characters, the reason why 4 TEXT_LABEL32 parameters are needed to store 128-byte strings. They can be passed individually as 32-byte aligned blocks but the first character is trimmed out. [...] In the last Trilogy and Stories chapter, text labels must begin with an alphanumeric character or an underscore, provided that they aren't valid integer or floating-point literals. [...] It is prohibited to fetch or handle a long text label using a variable of shorter length but this one is rather passable to those text label parameters also permitting long-lengthed literals. [...] Variable-length text labels are kind of Pascal strings. Reference: https://en.wikipedia.org/wiki/String_(computer_science)#Length-prefixed.

[...] In the last Trilogy chapter, local variables start at index 34 in mission scripts so local timers are also ignored.

[...] Some commands have non-typified arguments which are referred to as parameters.

[*] No more than 8 conditions are allowed per check [*] Checks are not short-circuited at runtime meaning all conditions are executed before branching [*] NAND and NOR might have been planned considering ANDOR values (0, 1 to 7, 21 to 27). Hint: mention the compare flag. [*] ANDOR is not compiled in Stories games for one condition checks [*] IFNOT and WHILENOT are not supported in VC and SA because GOTO_IF_TRUE is not handled by game code there. [*] REPEAT is supported since VC [*] REPEAT cycles at least one-time [*] REPEAT wrongly accepts a value lesser than 1 for the times argument [*] SWITCH is supported only in SA [*] SWITCH allows fall-through CASEs so BREAK is not mandatory [*] SWITCH handles up to 75 CASEs chosen as a result of a binary search which requires CASEs to be sorted on compilation [*] In contrast to scope-free subroutines which feature no argument... [*] Boolean-valued gosub and function [*] Recursion is allegedly not supported albeit gosubs and functions have 8 global levels of nesting in Trilogy chapters and 16 in Stories'. [*] Decision-making statement (IF, IFNOT, SWITCH) [*] Count-controlled loop (REPEAT) [*] Condition-controlled loop (WHILE, WHILENOT) [*] An unconditional branch, despite considered harmful in the programming literature, is the only way to go for breaking loops prematurely and enhance the simplistic code logic. [*] Infinite loops are achieved by means of a backward GOTO

[...] Although it is able to infer nothing regarding the aim exclusive mission scripts were planned for which swings among testing, mission pack and multiplayer purposes, there are bunch of irrefutable evidences implementation-wise. The functionality is analoguous to usual mission scripts but, on the other hand, the opposing kind of them is totally superseded and completely overlooked during the compilation phase. Their coexistence is perfectly legal, though leftover launchers are bad style and dangerous in so far as noncompilable unless an exclusive variation is also provided. Additionally, they are a lot limited in quantity: the first Trilogy chapter expects in theory only an intro mission (INTRO, shame not at runtime), the second chapter an auxiliary initialization mission (INITIAL), the third one an extra initialization mission (INITIL2) and whereas Stories chapters have game provision for such feature along the lines of Vice City, their compilers have allegedly no support because of deprecation (the trigger command is still there, however the too many initialization missions seen in the script binary might speak from themselves). Hints: one's complement

[...] Early in development, STREAM_SCRIPT was compiled to STREAM_SCRIPT_INTERNAL.

Despite streamed scripts may receive an entity handle as input parameter, they are not necessarily callable and so an on-top, unreachable, explicit entity's creation is due:

{
    VAR_INT test_char sanity

    sanity = 0
    IF sanity = -1
        CREATE_CHAR PEDTYPE_CIVMALE male01 0.0 0.0 0.0 test_char
    ENDIF
}

This scenario also extends to any embedded script or script file

Originally, explicit entity creations are conventionally put on top of any sort of script by mean of unreachable code to confer specific entity types to declared variables for better error-checking: