

BW's GTA SA Mission Builder version v0.33
---------------------------------------------------------------

1  What you get
1.1  Legal stuff
1.2  Included files
1.2.5  List of opcodes
1.3  Version info


2  Installation
2.1  Starting the mission builder
2.2  First time usage


3  The IDE
3.1  Buttons and menues
3.1.1 The F1 key


4  Mission coding
4.1  Definitions used in this readme
4.2  The mission script
4.2.1  The segments
4.2.2  The MAIN part of the mission script
4.2.3  The MISSION part of the mission script
4.2.4  The External Scripts part of the mission script
4.3  Data types
4.3.1  Arrays
4.3.1.2  Defining arrays / allocating memory for arrays
4.3.2  Floating-point numbers
4.4  Local variables
4.5  Global variables
4.6  Equates
4.8  Mathematical coding
4.8.1  Setting variables
4.8.2  Addition
4.8.3  Subtraction
4.8.4  Division
4.8.5  Multiplication
4.9  Conditional coding
4.10  Conditional math coding
4.10.1  Checking the value of variables
4.10.2  Using the NOT operator
4.11  Setting the data type of operations
4.12  Jump instructions
4.12.1  Using variables in jump instructions
4.13  Writing a mission script from scratch
4.14  Writing a mission from scratch
4.15  Rules that must be followed when coding
4.15.1  wait codes
4.15.2  create_thread commands
4.15.3  Requesting models
4.16  Practical Issues

5  Mission coding for newbies and retards :p

6  List of helpful people

7  Support




------------------

1  What you get

1.1  Legal stuff

I take no responsibility for any persons use of the
mission builder in any way. Use it at your own risk.

Since this mission builder is based on others work and
since those other people made some rules about what their
work could be used for, I included some information about
that in the STUFF folder. You should read through these
files since some of them have some useful information
about using the IDE.


1.2  Included files

1.2.5  List of opcodes

The OPCODES.TXT file has most of the opcodes used in the
mission script. Some math opcodes are not included. It is
in alphabetical order.


1.3  Version info

New stuff in version 0.33:
- Proper support for custom global variables and arrays
  (because the new memory system has finally been debugged).
- Setting up an array at address 0 didn't work. Fixed.
- New label format in decompiler.
- Decompiler now supports custom label names.
- Custom global variable names removed from the 'sascm.ini'
  and put in 'variables.ini' with a new easier format.



New stuff in version 0.32:
- Opcode parameter definition 't%' in the 'SAscm.ini' file was changed
  to use objects from the 'default.ide' file only while 'o%' is used
  with any objects.
- Named references to the second segment objects added.
- Original mission titles added to hardcoded mission descriptions.
- Some cosmetical bugs fixed. :-)



New stuff in Version 0.31:
- Main scripts with empty segments can now be decompiled
  and recompiled.
- A debug message was removed.
- Some tiny potentional bugs removed.
- Math system complete. CyQ found the new math codes.

Code tested with the new math system using the compiler
and decompiler. Opcode 08FA could be wrong. The code has
not been tested ingame:

if  0
  $728($727,32i) ==  0
  $728($727,32f) ==  0.0
  $728($727,32s) ==  'test'
  $728($727,32v) ==  "test"
jf Label0146EB

if  0
  @728($727,32i) ==  0
  @728($727,32f) ==  0.0
  @728($727,32s) ==  'test'
  @728($727,32v) ==  "test"
jf Label0146EB

$1735 = $760($727,32i)
$1735 = $760($727,32f)
s$1735 = $760($727,32s)
v$1735 = $760($727,32v)
$760($727,32s) = 'test'
$760($727,32v) = "test"
s$1735 = 'test'
v$1735 = "test"

@1735 = $760($727,32i)
@1735 = $760($727,32f)
s@1735 = $760($727,32s)
v@1735 = $760($727,32v)
@760($727,32s) = 'test'
@760($727,32v) = "test"
s@1735 = 'test'
v@1735 = "test"

$728(1) = 123  ; same as $729 when DMA support enabled
$728(2) = 234  ; same as $730 when DMA support enabled
$728(3) = 345  ; same as $731 when DMA support enabled


Same code decompiled:
00D6: if  0
0038:   $728($727,32i) ==  0  ;; integer values
0042:   $728($727,32f) ==  0.0  ;; floating-point values
05AD:   $728($727,32s) == 'TEST'  ;; 8-byte strings
08F9:   $728($727,32v) == "TEST"  ;; 16-byte strings
004D: jump_if_false Label0118A1

00D6: if  0
0039:   @728($727,32i) ==  0  ;; integer values
0043:   @728($727,32f) ==  0.0  ;; floating-point values
05AE:   @728($727,32s) == 'TEST'  ;; 8-byte strings
08FA:   @728($727,32,3) == "TEST"  ;; 16-byte strings
004D: jump_if_false Label0118A1

0084: $1735 = $760($727,32i)  ;; integer values and handles
0086: $1735 = $760($727,32f)  ;; floating-point values only
05A9: s$1735 = $760($727,32s)  ;; 8-byte strings
06D1: v$1735 = $760($727,32v)  ;; 16-byte strings
05A9: $760($727,32s) = 'TEST'  ;; 8-byte strings
06D1: $760($727,32v) = "TEST"  ;; 16-byte strings
05A9: s$1735 = 'TEST'  ;; 8-byte strings
06D1: v$1735 = "TEST"  ;; 16-byte strings

008B: @1735 = $760($727,32i)  ;; integer values and handles
0089: @1735 = $760($727,32f)  ;; floating-point values only
05AA: s@1735 = $760($727,32s)  ;; 8-byte strings
06D2: v@1735 = $760($727,32v)  ;; 16-byte strings
05AA: @760($727,32s) = 'TEST'  ;; 8-byte strings
06D2: @760($727,32,3) = "TEST"  ;; 16-byte strings
05AA: s@1735 = 'TEST'  ;; 8-byte strings
06D2: v@1735 = "TEST"  ;; 16-byte strings

0004: $728(1) =  123  ;; integer values
0004: $728(2) =  234  ;; integer values
0004: $728(3) =  345  ;; integer values




---------------------------------------------------------------

2  Installation

Unzip to anywhere. Copy your 'default.ide', 'peds.ide' and
'VEHICLES.IDE' to this location. 



2.1  Starting the mission builder

Run 'SABuilder03.exe'. 



2.2  First time usage

Run 'SABuilder03.exe' to start it up. Press the
"open existing file" / map icon (or use the file menu and select
open file). 

GTA San Andreas has two binary files with scripts in them, the
"main.scm" and "script.img". To make things as easy as possible
for the user, both these files are decompiled to one huge text
file.

Select "All files *.*" in the file type combo box and navigate
to your "main.scm" and "script.img" file. These two files must
be in the same direcory to get things working properly. If they
aren't, use your windows explorer and copy them to the same
directory.

You now get a another dialog box that is used to create and/or
select a work/project directory for the decompiled file. The MB
for SA needs this as it creates "table" files that are loaded
when the script is recompiled. 

Replace the text "<new folder>" in there with "Original SCM"
and press the "Create New Folder" button. Now select the newly
created "Original SCM" folder in the directory list and press
the "Ok" button.

The mission builder now decompiles the "main.scm" and
"script.img" and creates a file called "main.txt" in the
destination directory you chose. A sub folder called
"tables" is also created and the table data is stored
in several files here.

-----------------------------------

3  The IDE

3.1  Buttons and menues

The menues and buttons should to some extent explain
themselves. The button that looks like 'open multiple files'
does something completely different - it disables global
variable names set in the 'vicescm.ini' file when decompiling.


3.1.1 The F1 key

Press F1 to find opcodes and parameters for commands.

Example, if you write:

   end_thread


and press the F1 key, the line changes to:

   004E: end_thread


This feature is pretty complex. It is based on 3 different
files that are loaded when the mission builder loads. It
searches for word matches. You can combine words by putting
and underscore between them. The above example searches for
the exact match "end thread" (or "end_thread") only. If you
just write:

   thread


and press the F1 key, every time you press F1, you get another
match. When you press F1 on lines that doesn't have any
underscores at all, the result doesn't include any either.
With "thread", you get one of these:

   00D7: create thread with wasted busted check Label011C74
   004F: create thread Label0091D0
   004E: end thread
   03A4: name thread "MAIN"


Another example, you want to know what opcodes are used with
"create_actor". Every time you press F1, the line toggles
between these commands:

   0129: $912 = create_actor  8 #HNB in_car $94C driverseat
   01C8: $8F5 = create_actor  10 #CLB in_car $8F8 passenger_seat  0
   009A: $2D3 = create_actor  4 #PGA at  @10  @11  @12


This version also allows you to search for keywords and logic
synonyms to keywords. Some keywords have up to 5 synonyms.
The list is in the 'keywords.txt' file. The MB reads this
list, so if you want more synonyms, you can add them to this
file.

If you want to add keywords to this file, you must follow
these rules:
- Use letters and numbers only.
- Spaces and underscores are not allowed inside keywords.
- After the keyword, add a single space.
- After the space, add the opcode that the synonym is to
  be linked with. The opcode must be in hexadecimal format
  and always 4 letters (or numbers) long.






------------------------

4  Mission coding

4.1  Definitions used in this readme

In this readme, a mission script is either a compiled '.scm'
file or a text file containing script source code.
A segment is a chunk of compiled code. The term "script code"
or "code line" is any line of text looking like this:

03CB: set_camera 807.0 -937.0  36.5625 
  |          |                     |
  |          |                     |
  |          |                     |
  |          |                     |_____ *3
  |          |                           
  |          |___________________________ *2
  |                                     
  |______________________________________ *1  


*1  This is an opcodes.

*2  This is the command string. This part is ignored by this
    version of this mission builder (and any future versions).

*3  This is a number.


When the opcode is not specified, the code line is processed
either as a code line containing only math instructions or
as a code line containing a mix of conditional checks or
commands related to functions in the mission builders.
The term "math coding" is related to code lines where the
opcode is not specified and commands related to math codes
or conditional checks are used.




4.2  The mission script

4.2.1  The segments

In this readme, a compiled mission script has 7 segments.
Segment 1 is the mission script memory.
Segment 2 is a table of 3D objects. When I talk about
"second segment objects", I talk about these 3D objects.
Segment 3 is a table of mission pointers.
Segment 4 is a table of external scripts.
Segment 5 is currently unknown.
Segment 6 is currently unknown.
Segment 7 is where the script code starts.



4.2.2  The MAIN part of the mission script

The MAIN part of the mission script is where the script code
starts. In other words, in this readme, the MAIN part of the
code is where the 7th segment starts. To find the MAIN part of
the mission script in the original decompiled mission script,
look for a line like this:

;-------------MAIN---------------



4.2.3  The MISSION part of the mission script

The MISSION part of the mission script is where the MAIN part
of the mission script ends. To find the mission part of the
mission script in the original decompiled mission script, look
for a line like this:

;-------------Mission 0---------------


4.2.4  The External Scripts part of the mission script

The External Scripts part of the mission script is where the
MISSION part of the mission script ends. To find the
External Scripts part of the mission script in the original
decompiled mission script, look for a line like this:

EXTERNAL_SCRIPT_START





4.3  Data types

If you are familiar with the Mission Builder for GTA 3 or GTA VC, these
are the changes made to the San Andreas versions:

  Local variables used with integer and floating point numbers have been
  changed from  1@  to  @1

  Fixed-length strings (8 bytes) have been changed from "text" to 'text'

  Global 8 byte string variables look like this: s$VariableName

  Local 8 byte string variables look like this: s@123

  Variable length strings look like this: "text"

  Global variable length string variables look like this: v$VariableName

  Local variable length string variables look like this: v@123


Data types are used to identify numbers and labels. This version of the
mission builder uses  different data types. Variable length strings that
appear in the mission scripts are enclosed in quotes. Fixed length strings
are enclosed in ''.

DATA TYPE           MEANING

                  Used with global jump instructions to labels in the MAIN
                    part of the mission script and with create thread commands
                    in missions and external scripts that starts threads in the
                    MAIN part of the script.

                   Used with local jump instructions in missions to labels
                    in missions and with local jump instructions in external
                    scripts to labels in the external scripts.

   @                Stores 16-bit numbers used with internal timers and local
                    variables. The use of local variables in GTA SA is very
                    different from earlier versions of the game. These variables
                    can be set using the create_thread command like this:
                    create_thread <label> <parameter 1> <parameter 2>

   $                Used with global variables. 

   #                Used as equates. To find the numbers, look inside the
                    'default.ide' file.


NEW DATA TYPES      MEANING

   s$               Used with global fixed-length (8-byte) string variables.
                    Example: s$VariableName

   s@               Used with local fixed-length (8-byte) string variables.
                    Example: s@123

   v$               Used with global variable length string (16-bytes max)
                    variables.
                    Example: v$VariableName

   v@               Used with local variable length string (16-bytes max)
                    variables.
                    Example: v@123


4.3.1  Arrays

There are 2 types of arrays. If a number is used as index, the
format goes like this:

  <variable>(<index>)

If a variable is used as index, the format goes like this:

  <variable>(<index>,<number of elements in the array><array type>)

<number of elements in the array> is the size of the array. If the size
is set to 1, then the array isn't really an array. 0 would be invalid.
Variables can't be used to set the size of an array. If the size is 4
then the highest index is 3.

<array type> is one of the following:
i: integer
f: float
s: fixed length strings (8 bytes long)
v: variable length strings


A global integer variable array using a global variable as index with 4
elements looks like this:

  $VariableName($VariableName,4i)


A global floating-point variable array using a global variable as index with 4
elements looks like this:

  $VariableName($VariableName,4f)


A local fixed-length string variable array using a local variable as index with 4
elements looks like this:

  @123(@234,4s)


4.3.1.2  Defining arrays / allocating memory for arrays / redefining arrays

This only applies to custom global arrays (meaning arrays with a custom global
variable name). All you need to do to define one is to use this:

  <custom global variable name>(<any variable as index>,<number of elements in the array><array type>)

When it's defined (or allocated), you can use this:

  <custom global variable name>(<number as index>)


Example code:
  @1 = 0
  $CustomArray(@1,10i) = 0  ; "reserves" 44 bytes (40 used) of memory. The memory can be
                            ; changed using "methods of direct memory access"
  $CustomArray(1) = 1
  $CustomArray(2) = 2
  $CustomArray(3) = 3
  $CustomArray(4) = 4
  $CustomArray(5) = 5
  $CustomArray(6) = 6
  $CustomArray(7) = 7
  $CustomArray(8) = 8
  $CustomArray(9) = 9
  ; $CustomArray(10) would be out of range


Redefining custom global arrays isn't useful because you never know where in
memory they are stored. You can however redefine them if you want to anyway.
The results would ofcourse be unpredictable.

Defining and redefining arrays at specific memory addresses is always useful
since arrays like that aren't really ever allocated. They are simply set up
to access memory at certain addresses. To set up an array that uses memory
already used (or memory not already used), use:

$<memory address divided by 4>(<variable as index>, <memory range divided by 4><array type>)

To set up an array that overlaps all global variables from address 400 to 800
(meaning all global variables from $100 to $200), use
$100(<variable as index>,101<array type>)






4.3.2  Floating-point numbers

All floating point operations require numbers to be set up as floating
point numbers. To set a number to a floating-point number, make sure it has
a DOT in it. Valid floating-point numbers:  0.0  1.0  1.2  2.3
If a number is NOT set up as a floating-point number, it is automatically
set up as an integer number.


4.4  Local variables

Local variables are local to the threads or missions they are used in.
I have no idea how local variables are used in GTA SA at this time.


4.5  Global variables

Global variables are global to the entire mission script. They can be set
in the MAIN part of the mission script and used in the mission part of the
mission script by any mission. The total size of the mission script memory
is not set automatically in this version. Use the DEFINE MEMORY command
to set the total size of the mission script memory. This version 
uses a direct memory access system with the global variables.

Any global variables that start with
a number will be allocated at the address specified by that number and
multiplied by 4. A global variable named $100Test will be allocated at
address 400. Please note that the decompiler no longer uses hexadecimal
numbers when outputting global variable names. Any global variable that
doesn't start with a number will be allocated at an available address at
the end of the memory (specified by the DEFINE MEMORY command at the
start of the script). This allocation method will require more memory
than any mission editor that doesn't. The reason I chose to code the
mission builder like this was to keep the original script in its original
state or as close to it as possible when recompiling, preserving memory
addresses that was unused originally and perhaps avoiding problems related
to unknown memory issues. Future mission builders (for the PC version)
will not have this DMA system.




4.6  Equates

Equates are variables set up internally in the mission builder. When
the mission builder is loading, it reads the 'default.ide', 'peds.ide'
and 'VEHICLES.IDE' file and stores all the definitions it finds in those
files into equates. This means that if you want to create a car and you
need the number of the model name of that car, you just use the equate
of that car instead. Like:  $CarModelNumber = #cheetah





4.8  Mathematical coding (or math coding, see definitions)

  The local and global variables below can be replaced with integer and
  floating-point arrays. String arrays can be set using <array> = '<text>'
  or <array> = "<text>"

4.8.1  Setting variables

To set a global variable to an integer value, use
$<global variable name> = <integer number>

To set a global variable to a floating-point value, use
$<global variable name> = <floating-point number>

See '4.3.1  Floating-point numbers' for more information
about floating-point numbers and integer numbers.

To copy a global variable containing a floating-point number
to another global variable, use
FLOAT $<global variable name> = $<global variable name>

To copy a global variable containing an integer number
to another global variable, use
INT $<global variable name> = $<global variable name>
or INTEGER $<global variable name> = $<global variable name>

Use the same method to copy local variables to global variables.


4.8.2  Addition

To add an integer number to a global variable, use
$<global variable name> += <integer number>

To add a floating-point number to a global variable, use
$<global variable name> += <floating-point number>

To add a global variable containing an integer value to
another global variable also containing an integer value, use
INT $<global variable name> += $<global variable name>

To add a global variable containing a floating-point value to
another global variable also containing a floating-point value, use
FLOAT $<global variable name> += $<global variable name>

Use the same method with local variables and any combinations
of global and local variables. See '4.3.1  Floating-point numbers'
for more information about floating-point numbers and integer numbers.


4.8.3  Subtraction

To subtract an integer number from a global variable, use
$<global variable name> -= <integer number>

To subtract a floating-point number from a global variable, use
$<global variable name> -= <floating-point number>

To subtract a global variable containing an integer value from
another global variable also containing an integer value, use
INT $<global variable name> -= $<global variable name>

To subtract a global variable containing a floating-point value from
another global variable also containing a floating-point value, use
FLOAT $<global variable name> -= $<global variable name>

Use the same method with local variables and any combinations
of global and local variables. See '4.3.1  Floating-point numbers'
for more information about floating-point numbers and integer numbers.


4.8.4  Division

To divide a global variable with an integer number, use
$<global variable name> /= <integer number>

To divide a global variable with a floating-point number, use
$<global variable name> /= <floating-point number>

To divide a global variable containing an integer value with
another global variable also containing an integer value, use
INT $<global variable name> /= $<global variable name>

To divide a global variable containing a floating-point value with
another global variable also containing a floating-point value, use
FLOAT $<global variable name> /= $<global variable name>

Use the same method with local variables and any combinations
of global and local variables. See '4.3.1  Floating-point numbers'
for more information about floating-point numbers and integer numbers.


4.8.5  Multiplication

To multiply a global variable with an integer number, use
$<global variable name> *= <integer number>

To multiply a global variable with a floating-point number, use
$<global variable name> *= <floating-point number>

To multiply a global variable containing an integer value with
another global variable also containing an integer value, use
INT $<global variable name> *= $<global variable name>

To multiply a global variable containing a floating-point value with
another global variable also containing a floating-point value, use
FLOAT $<global variable name> *= $<global variable name>

Use the same method with local variables and any combinations
of global and local variables. See '4.3.1  Floating-point numbers'
for more information about floating-point numbers and integer numbers.



4.9  Conditional coding

Example:

00D6: if  1
0038:   $ONMISSION ==  1
0038:   $BUSTED_PICKUP_MADE_FLAG ==  1
004D: jump_if_false Label008FCA

There are TWO conditional checks in this code. The first
conditional check checks if the player is currently on a mission.
The second conditional check checks if the $BUSTED_PICKUP_MADE_FLAG
variable is equal to 1.

The first line defines the NUMBER OF CONDITIONS to include in the
conditional check and if the checking is to be done in an INCLUSIVE
or EXCLUSIVE manner.

The example code uses INCLUSIVE checking. With INCLUSIVE checking,
the number in the first line is equal to the number of lines with
conditional checks MINUS 1. The BASIC programming language uses
the operand 'AND' for INCLUSIVE conditional checking.

With EXCLUSIVE checking, the number in the first line is equal to
the number of lines with conditional checks PLUSS 19. The BASIC
programming language uses the operand 'OR' for EXCLUSIVE conditional
checking.

This is the BASIC equivalent to the example code above:

IF $ONMISSION=1 AND $BUSTED_PICKUP_MADE_FLAG = 1 THEN

With EXCLUSIVE checking the code looks like this:

00D6: if  21
0038:   $ONMISSION ==  1
0038:   $BUSTED_PICKUP_MADE_FLAG ==  1
004D: jump_if_false Label008FCA

Two conditional checks + 19 for EXCLUSIVE checking = 21 in the first line.

This is the BASIC equivalent to the example code with EXCLUSIVE
checking:

IF $ONMISSION=1 OR $BUSTED_PICKUP_MADE_FLAG = 1 THEN

When all the conditional checks are checked, the result of all the
checks is controlled by the '004D: jump_if_false' opcode and
command. If the result is FALSE, the code "jumps" to the label
in the command. If the result is TRUE, the code following the
'004D: jump_if_false' opcode and command is executed.

See '4.12  Jump instructions' for more information about jump
instructions.



4.10  Conditional math coding (comparing variables to numbers and
     other variables)

Please not that you can't use conditional math coding without
first using the IF command. See 4.9 Conditional coding for more
information.

String arrays can be compared using <array> == '<text>',
<array> == "<text>", <array> == <array> or
<array> == <string variable>


4.10.1  Checking the value of variables

To check if a global variable is equal to a specific integer
number, use
$<global variable name> == <integer number>

To check if a global variable is bigger than a specific integer
number, use
$<global variable name> > <integer number>

To check if a global variable is smaller than a specific integer
number, swap the number with the variable, like
<integer number> > $<global variable name>

Use the same method with floating-point numbers.
You can also use the same method with the operator '>='

To check if a global variable is equal to a floating-point
number, use
$<global variable name> == <floating-point number>

See '4.3.1  Floating-point numbers' for more information
about floating-point numbers and integer numbers.

To check if a global variable containing a floating-point number
is equal to another global variable, use
FLOAT $<global variable name> == $<global variable name>

To check if a global variable containing an integer number
is equal to another global variable, use
INT $<global variable name> == $<global variable name>
or INTEGER $<global variable name> = $<global variable name>

Use the same method with the operator '>' or '>=' to check if
a variable is bigger than another variable, like:
00D6: if 0
        FLOAT $MyVar >= @0
004D: jump_if_false ...


4.10.2  Checking the value of variables using the NOT operator

To check if a global variable is NOT equal to a specific integer
number, use
NOT $<global variable name> == <integer number>

To check if a global variable is NOT bigger than a specific integer
number, use
NOT $<global variable name> > <integer number>

To check if a global variable is NOT smaller than a specific integer
number, swap the number with the variable, like
NOT <integer number> > $<global variable name>

Use the same method with floating-point numbers.
You can also use the same method with the operator '>='

To check if a global variable is NOT equal to a floating-point
number, use
NOT $<global variable name> == <floating-point number>

See '4.3.1  Floating-point numbers' for more information
about floating-point numbers and integer numbers.

To check if a global variable containing a floating-point number
is NOT equal to another global variable, use
FLOAT NOT $<global variable name> == $<global variable name>

To check if a global variable containing an integer number
is NOT equal to another global variable, use
INT NOT $<global variable name> == $<global variable name>
or
INTEGER NOT $<global variable name> = $<global variable name>

Use the same method with the operator '>' or '>=' to check if
a variable is NOT bigger than another variable, like:
00D6: if 0
        FLOAT NOT $MyVar >= @0
004D: jump_if_false ...



4.11  Setting the data type of operations

This part of the readme is for old users. It explains the
new feature about using INT and FLOAT.

Variables can hold integer values or floating-point values.
Sometimes, one set of opcodes is used with floating-point
operations and another set of opcodes is used with integer
operations. When doing math coding (see definition above),
it is sometimes necessary to specify the data type of
the operation. These are examples on how to specify the
data type of operations:

INT $test = $mycar
FLOAT $MyXvar = $MyOtherXVar
FLOAT $MyXvar += $AnotherXVar
INT $MyXvar = $SomeIntegerVariable

if
  INT $MyXvar == $SomeIntegerVariable
jf ...



4.12  Jump instructions

All jump instructions (gosub, jump, jump_if_false, create_thread call and such) use
labels. Labels are defined with a colon in the beginning of a line and referenced
with the data type '' or ''. LOCAL jumps, meaning jump instructions used in missions
only to labels in missions only, use the data type '' before the mission label. GLOBAL
jumps, meaning jump instructions from both the MAIN part of the mission script and from
the mission part of the mission script, use '' as data type. GLOBAL jumps ALWAYS
(except for the DEFINE MISSION command) jump to labels in the MAIN part of the mission
script.

There are lots of situations where some commands work and other do not.

Examples of WORKING jump instructions:

;----MAIN
...
:Label1
...
:Label2
...
0002: jump Label1
...
;---Mission 23
...
0050: gosub Label1
...
004F: create_thread Label2
0002: jump Label3
...
:Label3
...


Examples of INCORRECT jump instructions:

;----MAIN
...
:Label1
...
:Label2
...
0002: jump Label1  ; WRONG. Use 0002: jump Label1
...
0002: jump Label3  ; NOT ALLOWED. The only way to access mission code from MAIN is to use '0417: start_mission <mission>'
...

;---Mission 23
...
0002: jump Label1   ; NOT ALLOWED. Use '0050: gosub Label1' or '004F: create_thread Label1'
0050: gosub Label3  ; WRONG. Use 0050: gosub Label3
...
004F: create_thread Label3  ; NOT ALLOWED. All threads must be in MAIN.
0002: jump Label3  ; WRONG. Use 0002: jump Label3
...
:Label3
...


4.12.1  Using variables in jump instructions

You can use variables with jump instructions. This is however NOT
recommended if you want your scm files to be readable if they are
decompiled by others. You can't just recompile decompiled files
using variables with jump instructions without first manually
changing the decompiled code. To set up a global variable with a jump,
use a code like this:

0004: $<global variable> = <data type for local or global jump><label>
...
(any code to alter the global variable goes here)
...
0002: jump $<global variable>




4.13  Writing a mission script from scratch

(I'm too bloody lazy to rewrite this part of this readme)



4.14  Writing a mission from scratch

To write a mission from scratch, copy this code and change
everything enclosed in < > .

VERY IMPORTANT!!! All this code goes into the MISSION part of the code.

;-------------Mission <mission number>---------------

:Mission<mission number>  
0050: gosub <label where the mission code starts> 
00D6: if  0
0112:   wasted_or_busted
004D: jump_if_false <label for skipping the mission failure code>
0050: gosub <label for mission failure code. Executed if player dies or gets arrested during the mission>

:<label for skipping the mission failure code>
0050: gosub <label for the mission cleanup code>
004E: end_thread

:<label where the mission code starts>
0317: increment_mission_attempts
03A4: name_thread "<thread name>"
0004: $onmission =  1
0110: player $PLAYER_CHAR wanted_level = 0

:<Label for mission loop>
0001: wait 0 ms
0002: jump <Label for mission loop>

:<label for mission failure code. Executed if player dies or gets arrested during the mission>
00BA: text_styled "M_FAIL"  4000 ms  1  ; MISSION FAILED!
0051: return

:<label for the mission cleanup code>
0004: $ONMISSION =  0
00D8: mission_cleanup
0051: return


When you have done that, change this line 'DEFINE MISSIONS <number of missions>'
and add this line 'DEFINE MISSION <mission number> AT Mission<mission number>'.
Adding code in the MAIN part of the code for starting the new mission is also
a good idea :-)



4.15  Rules that must be followed when coding

Obviessly, when coding with non-math codes, each code line
must fit the definition of a code line in
'4.1  Definitions used in this readme'.

Lines can be remarked using a semicolon.  ;

Old saved games are not compatible with newer mission scripts.
This means you must ALWAYS start a new game after modifying
the mission script.


4.15.1  wait codes

You can't code without using wait commands. If the script loops and the
loop doesn't have any wait codes, the game will crash. In the MAIN
part of the code, it is recommended that you use 250 or higher values
with the wait codes. In the mission part of the code, use 0.


4.15.2  create_thread commands

Unless proven otherways, these are the rules:

- NEVER use the 'create_thread' command unless you actually want your
  missions to run multiple mission codes simultaniously.

- GTA Vice City has a limit of 64 threads.

- When using 'create_thread <label>' the label and the code following
  it must in the MAIN part of the code.

- The 'create_thread' command can be issued from both the MAIN part of
  the code and the MISSION part of the code.

- In the original script, most of the threads started with the
  'create_thread' command runs in a 'low-priority' manner. Use
  the 'wait' command to set the priority of a thread.

  Example:
      0001: wait 250 ms


- It might be possible to "overload" the mission script by running
  a certain number of high priority threads simultaniously. If it is
  possible, it might hurt the frame-rate or the time it takes to
  load the scenery.


4.15.3  Requesting models

You can't create anything without loading the models for the stuff
you want to create. To load the model of something, use

0247: request_model #<model name>

When you request something, it isn't loaded instantly. To check if
the stuff you have requested has been loaded, use a loop like this:

:LoadStuff
00D6: if 0
8248:   NOT   model #<model name> available
004D: jump_if_false StuffLoaded
0001: wait 0 ms
0002: jump LoadStuff

:StuffLoaded




4.16  Practical Issues

Doing simple changes, speeding stuff up
- Have the builder and SA (PC version) running at the same time.
- Press ESC in SA to exit to the main menu when you
  want to change something.
- Press Alt-TAB to switch between the builder and SA.
- Use the same video resolution in the game and in your
  windows "desktop"
- Use the 'Compile & Copy' feature in the builder to
  compile (PC version).
- Start a new game in SA when changes have been made.
- Use the F1 key to find the opcodes.


You can create missions to run in a single- or multi-task manner.
To make a mission run in multiple tasks, use the 'create_thread'
or the 'create_thread_with_wasted_busted_check' commands (with
the multi-thread code in MAIN).


You should NEVER EVER remove lines with the  DEFINE OBJECT  command
because you must then change ALL the commands in the mission script
that access these objects by their numbers. If you need to add an
object, add it to the end of the list and then change the total
number of objects defined.


If you think it looks ugly, you can to some extent change it.
All the commands in my mission builders can be changed.
Just change the 'vicescm.ini' file. Don't blame me if you
mess it up. Create a backup first.

With version 0.125 and later of the Vice mission builders,
you MUST put a space between the parameters in the
'vicescm.ini' file.


------------------

5  Mission coding for newbies and retards :p

(removed because it got silly)

------------------

6  List of helpful people

Providing vital information, like the format of the mission script:
CyQ

Providing opcodes descriptions and general guesswork (in no particular
order):
CyQ, CtlAltDel, Opius, steve-m, Delfi, Craig Kostelecky, PatrickW,
TbM2k, Y-less and perhaps others.

Providing custom global variable names used by the decompiler:

Providing custom label names used by the decompiler:



---------

7  Support

Just go to

  http://www.gtaforums.com

for all the support you'll ever need.


My web sites (GTA 3 and GTA VC only at this time):
  http://home.c2i.net/barton49
  http://home.no.net/barton57
  http://home.no/bobby-stalefish/  (not updated)




