Quantcast

Jump to content

» «
Photo

[GTA SA] ~ CLEO Script Tutorial ~

631 replies to this topic
ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#1

Posted 20 March 2009 - 10:17 PM Edited by ZAZ, 30 August 2012 - 06:35 PM.

CLEO Script Tutorial
english language

CLEO Script Tutorial deutschsprachig



INDEX
Chapter lesson
First Steps in Cleo scripting
with Sannybuilder
- Start for newbies
The Editor - The main functions
- Option: different view of the decompiled code
- Classes and Keywords
Data types - locals @, globals $, "strings '
and hash # to enter modelname
Scripting/Writing a Thread

coding in praxis,
a must-read for newbies
- Using conditional checks
- The IF - Variation
- Script structure simple
- Script structure extended
- Script exemble: Slowmotion

- Spawn a 3D model
- Placing cars by using parked_car_generator
Special Particularities in Cleo - enable_thread_saving
- special cleo global var

- Script Exemble by using Special Global Cleo Variable/ Store a car at any place
- Template for Cleo Mission Script
gosub ... to read a subscript - basic knowledge to understand mission scripts



Chapter lesson
Additional Themes

the lessons are in one post
- Create a FXT file
- Load a special actor
- Tuning parts
- Animations
- sounds of Audio folder
Math coding

the lessons are in one post
- give access with math coding
- Access check with local variables
- Declare or not declare (first reason)
- Time check for milliseconds in real time
- Time check for game hours
- Integer values and floating points
- Declare or not declare (second reason)
- Integer to float and reversed
- Show the calculated values with text_draw opcode
- Math calculations
Save script - simple save script example
Arrays - advanced method to unify same functions of more instances in one process
Memory Coding

the lessons are in one post
-cheat codes
- Gravity
- ASCII Table
- related links to car struct, actor struct, object struct
Advanced Memory Access to learn the basics
Changing Car Handling
call_scm_function - for advanced
Catch random actor - get_actor_in_sphere
- RandomActor_for_to_step_method
KEY_PRESS - external topic about key_press
Car Drive Tutorial

the lessons are in one post
- car drive_to
- drive-to commands
- Let the driver do corrections
- Let the driver drive
- Define a scmpath for the driver
- Car drive scripts in praxis
Carrec Paths - Record a path with Seemanns carrec.cs
- assign_car to_path
Particle Effects - show particle effects of effects.fxp
Special opcodes to show particles - sparks, gunflash, blood, corona, shadow, smoke
LIGHT and shadow - the light in gta
- Flash_Light_Illumination
- create_searchlight
- shadow
Object - COLLISION - check

the lessons are in one post
- object.dat definitions
- beachball and bball_col
- throw object
- Missilescript
MENUE-interactive - create_panel
JumpTable - 0871: init_jump_table
Teleport - Sphere (red marker)
- Location Check
Teleport into interior - Interior Entrance
related links
gtamodding.com: List_of_opcodes
GTA:SA Opcodes, Discussion thread
PLPyntons_UnifiedOpcodes
opcode descriptions by PLPynton in sascm.ini format
(be careful, some opcodes are nevermore compatible
because of changed parameter order)
my opcodes.txt
Dejis Opcode Database

______________________________________________________________________________________
______________________________________________________________________________________



First Steps in Cleo scripting with Sannybuilder

Download newest version of Sannybuilder from Seeman at http://sannybuilder.com/


Install Sannybuilder and create a folder for your scripts
Therefor youre promt to indicate your GTASA-Install dir.

Then start Sannybuilder,
Open a new blank page, copy the script below and insert it into the new page.

CODE
{$CLEO .cs}
:DEMOTEXT
03A4: name_thread "DEMO"
wait 1000

:DEMOTEXT_1
wait 0
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @DEMOTEXT_1
if
00E1:   key_pressed  0  17
004D: jump_if_false @DEMOTEXT_1
00BA: text_styled 'FEM_OK'  1000 ms  1
0A93: end_custom_thread


Save it in your Sannyscript folder and give it a name.
user posted image

Compile the script. Click on menue icon with "running man" to choose compile + copy
If the CLEO - Library is installed, the script will be compiled and copied in to GTASA\CLEO - folder

The Cleo script file get then the file extension, which is written in the Cleo Script directive at the beginning of the script

{$CLEO .cs} = Cleo directive will be compiled to *.cs
As DEMOTEXT.txt saved and compiled as DEMOTEXT.cs

______________________________________________________________________________________

If CLEO is not installed, then sannybuilder will prompt you to do it and at the lower right corner of the editor
appears the CLEO - box with a red border. Click on it and Sannybuilder installs Cleo immediately.
Or download the cleo auto install exe at http://cleo.sannybuilder.com
______________________________________________________________________________________

If the compiling process was successful you get then a report message
user posted image
click on OK to confirm
the lower value "Largest Script" shows the script file size
the other values belongs to a compiling process of a main.scm

Test then the script ingame, press fire button to display the text message "OK"
The script ends then, will be deactivated because it ends with opcode 0A93: end_custom_thread

______________________________________________________________________________________
______________________________________________________________________________________



The Editor

The main functions can be found as icon button in the menue bar

1. Decompile: sanny opens script files with extensions .CS , .CM or .SCM

2. Compile: sanny compiles by default to a [Name]main.SCM

Sanny compiles automaticly to Cleoscript files, if the script have a Cleo-Direktive as entry

{$CLEO .cs} = Cleo-Direktive, will be compiled to Name.CS
{$CLEO .cm} = Cleo-Direktive, will be compiled to Name.CM

user posted image



Useful tools

Choose TOOLS on menue, then IDE Tools >> Coords Manager
to read the x,y,z coordinate and the z-angle of the current player position if the game is running

Choose TOOLS on menue, then IDE Tools >> Opcode Search
to search for opcodes
type any keyword to find a codeline which include this word
or type an opcode to find the description
the foundings are allways existing lines of original main.scm
The opcode search tool requires to create the opcode.txt in Sanny Builder 3\data\sa folder
Load the decompiled original main into sannybuilder then choose TOOLS on sanny menue, then: make opcodes.txt

user posted image


Line numbers
Choose TOOLS, then options
in option menu EDITOR you can find the feature to switch Line numbers off/on
The line number is part of the editor, not of the script


The Sannybuilder HELP

Choose HELP on menue, then Content to find informations,
such like key_press numbers, weapon numbers, bodyparts etc..

user posted image

______________________________________________________________________________________
______________________________________________________________________________________



Option: different view of the decompiled code

Choose TOOLS, then options
in option menu GENERAL you can find the feature to switch between 2 ways for decompiling

either decompile by writing opcodes
or decompiling without opcodes

user posted image


1. Writing Opcodes
All entries are shown with their opcodes
The opcodes are the real programm codes of the script functions
and by showing them is like to see the name of the command
Script with opcodes:
CODE
:CARSL_6439
00D6: if
00E1:   player 0 pressed_key 16
004D: jump_if_false @CARSL_6535
010B: 5@ = player $PLAYER_CHAR money
00D6: if
002D:   5@ >= 14@ // (int)
004D: jump_if_false @CARSL_6512
0012: 14@ *= -1
0109: player $PLAYER_CHAR money += 14@  
0002: jump @CARSL_6700


2. Without Opcodes
The script is more slim, maybe more clear (but not for me)
especially 004D: jump_if_false will be now jf
But not all opcodes are disappeared. Many codes must be used furthermore by applying their opcodes.
Script without opcodes:
CODE
:CARSL_6439
if
00E1:   player 0 pressed_key 16
jf @CARSL_6535
5@ = Player.Money($PLAYER_CHAR)
if
002D:   5@ >= 14@ // (int)
jf @CARSL_6512
14@ *= -1
Player.Money($PLAYER_CHAR) += 14@
jump @CARSL_6700


By compiling it doesnt matter if you use codes with opcodes or without opcodes
You can merge everything and sanny compile it as well,
provided that the code is correct and codelines which includes opcodes by decompiling without opcodes
must be used furthermore by using opcodes


A special feature by decompiling without opcodes is to translate opcode based commands into
Classes and Keywords

For a couple of codes can be used CLASSES
Read more about classes in Sannybuilder-HELP theme: Coding >> Classes

This code by decompiling with writing opcodes
00AB: put_car 22@ at -1577.942 52.6333 40.0

will by shown by decompiling with without opcodes in this kind:

Car.PutAt( 22@ , -1577.942, 52.6333, 40.0)

the meaning of the code is defined by the class entries

Car= class-name
PutAt= class-member
name and member are combined with a dot in the middle
22@ = class-owner
class-owner and parameters are placed in brackets and separated with comma
(parameter = needed information for the command)



Sanny allows to use some KEYWORDS instead using opcodes

Opcode = Keyword
_____________
0001: = wait
00d6: = if
004d: = else_jump
004d: = jf
0002: = jump
0051: = return
0050: = gosub
016a: = fade
01B6: = set_weather
03a4: = thread
04BB: = select_interior
0417: = start_mission
00d8: = mission_cleanup
0317: = increment_mission_attempts


Instead writing
004D: jump_if_false @MAIN_6
can be written
jf @MAIN_6
or
else_jump @MAIN_6
you also can merge it
004D: jf @MAIN_6


______________________________________________________________________________________
______________________________________________________________________________________


Data types


: (doublepoint) marks a Label (adress)
CODE
:MAIN_1


@ is used for 2 different functions

1. in jump instruction to mark the label which should be reached
CODE
004D: jump_if_false @SAVE_5
0050: gosub @SAVE_14
0002: jump @SAVE_1


2. to mark LOCAL VARIABLES

The stuff in the game needs a identity for registration to can handle with it
The identities can be variable, for exemble by calculating something

The local variable is builded with the @ sign and a number
0@, 1@, ... 30@ from 0@ up to 31@ is possible, 32@ and 33@ are for timers, thats maximum in an .cs file

1@ defines a parked_car generator
CODE
014B: 1@ = init_parked_car_generator #PCJ600 0 17 1 alarm 0 door_lock 0 0 10000 at 2490.0 -1682.0 13.5 angle 90.0

1@ can then be used furthermore as variable name of the parked_car generator
CODE
014C: set_parked_car_generator 1@ cars_to_generate_to 101



$ is used to mark a GLOBAL VARIABLE

The stuff in the game needs a identity for registration to can handle with it
The identities can be variable, for exemble by calculating something

The global variable is builded with the $ sign and a a letter or a word or a number or both
But using global variables in Cleo scripts can cause heavy bugs or crashs
only $PLAYER_CHAR, $PLAYER_ACTOR, $ONMISSION are valid



global, local, whats that ?
Global variables are used in the main.scm to communicate between different threads
Local variables are also used in the main.scm but they can not communicate between different threads
You can create a car with a LOCAL variable in a thread as 1@ and also with 1@ in an other thread of main.scm
1@ = create_car
You have then 2 different cars, commanded from 2 different threads

You can create a car with GLOBAL variable in a thread but dont use again the same global to create it again in an other thread.
$mycar5 = create_car
But you can command the car from an other thread of the main.scm by using a GLOBAL variable
At least:
The GLOBAL variables are storable, the LOCAL variables not

But dont using global variables in Cleo scripts because they can cause heavy bugs or crashs
only $PLAYER_CHAR, $PLAYER_ACTOR, $ONMISSION are valid


# marks the connected entry as filename of a loadable model
CODE
0247: load_model #BMYCG
0247: load_model #HMYCM
0247: load_model #SWATVAN
0247: load_model #M4
0247: load_model #COLT45

For Cleo can only be used models which are defined in vehicles.ide, peds.ide or default.ide
Other models needs to use their ID number


'...' short string to insert letters or numbers like GXT entrynames or names of special IPL entries
CODE
03A4: name_thread 'MAIN'
0917: audio_zone 'BEACH' enable_sound 0
00BA: show_text_styled GXT 'INTRO_1' time 1000 style 2
0299: activate_garage 'MODLAST'
07FB: set_interior 'GYM1' access 1  // Ganton Gym
0390: load_txd_dictionary 'LD_BEAT'
076C: set_zone 'GAN1' gang 1 density_to 25


"..." long string to insert letters or numbers like animation- and IFP file names, bodypart names, particel names, etc...
CODE
087B: set_player $PLAYER_CHAR clothes_texture "PLAYER_FACE" model "HEAD" body_part 1
038F: load_texture "DOWN" as 1 // Load dictionary with 0390 first
0605: actor -1 perform_animation_sequence "DAN_LOOP_A" IFP_file "DANCING" 4.0 loop 1 0 0 0 time -1 // versionA
0674: set_car_model #GREENWOO numberplate "GROVE4L_"
0245: set_actor 5@ walk_style_to "GANG2"
064B: 25@ = create_particle "EXPLOSION_MOLOTOV" at 2010.0 -1610.0 16.5 type 1


To set entries of strings equal to variable names must be used special opcodes and extended variable signs
05AA:
05A9:
06D2:
06D1:
furthermore can strings also replaced with variables by using extended variable signs

@s - local-string-variable
CODE
05AA: 5@s = 'FEM_OK'
00BC: show_text_highpriority GXT 5@s time 10000 flag 1


s$ - global-string-variable
Attension by using Global vars in cleo scripts, it can cause bugs or crashes!
CODE
05A9: s$Actor_Speech_GXT_Reference = 'CATX_UA'  // ~z~Carl, you are a f*cking idiota!                    
00BC: show_text_highpriority GXT s$Actor_Speech_GXT_Reference time 10000 flag 1
05AA: 5@s = s$Actor_Speech_GXT_Reference
00BC: show_text_highpriority GXT 5@s time 10000 flag 1


@v - local-long-string-variable
CODE
06D2: 28@v = "LAPDAN1" // @v = string
0812: AS_actor $PLAYER_ACTOR perform_animation "LAPDAN_P" IFP_file 28@v 1000.0 loopA 0 lockX 0 lockY 0 lockF 1 time -1


v$ - global-long string-variable
Attension by using Global vars in cleo scripts, it can cause bugs or crashes!
CODE
06D1: v$1225 = "Bat_block"// 16-byte strings                    
0605: actor $PLAYER_ACTOR perform_animation_sequence v$1225 from_file "BASEBALL"  4.0  1  0  0  0 -1 ms



______________________________________________________________________________________
______________________________________________________________________________________


Scripting /Writing a Thread

The scripts which are running in GTA are called THREAD
They are defined in the main.scm as thread with the create_thread command or a mission script as mission
As well the Extern scripts of script.img are also threads.

The cleo programm checks if there is .cs file in the Cleo folder
and if yes, it start this script as thread

Script structur / short version:

At first, the head, it beginns with the Cleo directive
CODE
{$CLEO .cs}

First Label (adress)
CODE
:Akt

Then give the thread a name
CODE
03A4: name_thread 'AKT'

now put a code inthere which will doing something and then end_custom_thread as last code
its ready then to test it ingame

CODE
{$CLEO .cs}
:Akt
03A4: name_thread 'AKT'
08B2: toggle_thermal_vision 1
0A93: end_custom_thread

Script above activates the Infrarot view unless in cutscenes
The script ends then, will be deactivated because it ends with opcode 0A93: end_custom_thread
The script will be started by each loading of savegame or by start new game

______________________________________________________________________________________



Next step / using conditional checks

A conditional check requires minimum 3 opcodes

1. the IF-variation
2. the real question
3. the jump instruction by negation




1. if

2. 0AB0: key_pressed 8

3. 004D: jump_if_false @akt_01



We use the previous script again but now we wonna be able to switch into normal view
Therefore we use a conditional check and build a "LOOP"

Loop means that a jump instruction can send the reading process to a previous adress
I call such an adress "Loop-adress"
Important:
The first opcode after such a Loop-adress must be the wait opcode
mostly wait 0 millisecond

the jump instruction can be a jump instruction by negation
or also a normal jump instruction

CODE
004D: jump_if_false @akt_01

or
CODE
0002: jump @akt_01



The conditional check of a key press in the script below should be passed by pressing BACKSPACE

CODE
{$CLEO .cs}
:Akt
03A4: name_thread 'AKT'
08B2: toggle_thermal_vision 1

:Akt_01//----------------------------Loop adresse
0001: wait 0 ms
if
0AB0:   key_pressed 8
004D: jump_if_false @Akt_01//--------jump instruction by negation
08B2: toggle_thermal_vision 0
0A93: end_custom_thread

Script above activates the Infrarot view and toggle back to normal view by key_press
The reading process is looping as long as BACKSPACE is not pressed
the jump instruction by negation sends the reading process allways to the label :Akt_01
1000 times per second

______________________________________________________________________________________



The IF - Variation


CODE
if
00FF:   actor $PLAYER_ACTOR  1 (in-sphere)near_point_on_foot 2493.5  -1682.5  13.35 radius  1.0  1.0  1.0
004D: jump_if_false @Teleport_2


By more than one question in an conditional check requires to determine,
if it means if or or if and

CODE
if and
00DF:   actor $PLAYER_ACTOR driving
8119:   NOT   car 0@ wrecked
004D: jump_if_false @AD_5

CODE
if or
00E1: key_pressed 0 0
00E1: key_pressed 0 1
00E1: key_pressed 0 14
00E1: key_pressed 0 18
004D: jump_if_false @AD_7

CODE
if or
8118:   NOT   actor 7@ dead
8118:   NOT   actor 8@ dead
004D: jump_if_false @AD_25
0002: jump @AD_12


The most question codes can be changed into the opposite question
by changing the ciro of the opcode into 8 and insert "not" into the code line

exemble:
CODE
00E1: key_pressed 0 10

and
CODE
80E1: NOT key_pressed 0 11


______________________________________________________________________________________



Next Step/ Script structure simple

The previous scripts ended because of the opcode 0A93: end_custom_thread
Instead let the script ending we use a jump instruction at script end to the 1.Loop adress
So the reading process is permanent looping
CODE
0002: jump @Akt_01

And since now we add a check in our loop which we add allways after a Loop adress.
It is:
CODE
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Akt_01

It should prevent crashes if the player dies or gets arrested
The "IF Player- Defined-check" should allway be the first check in a loop

Script structure simple with 1 Loop:
-Script head
-1.Loop-Adress
-wait code
-IF player_defined-check
-Conditional Check
-Event
-Normal jump instruction to 1.LoopAdress

CODE
{$CLEO .cs}
:Akt
03A4: name_thread 'AKT'

:Akt_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Akt_01
if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @Akt_01
08B2: toggle_thermal_vision 1
0001: wait 3000 ms
08B2: toggle_thermal_vision 0
0002: jump @Akt_01//--------Normal jump instruction to 1.LoopAdress

Script above activates the Infrarot view after key_press
and toggle back to normal view after 3 seconds

______________________________________________________________________________________



Next Step/ Script structure extended

To start an event with our script will change the game state and the conditions.
This needs to redirect the reading process to prevent that the same code will be read again.
Therefore we add a second Loop in the script
Loop 1 - before the event
Loop 2 - after the event

Script structure extended with 2 Loops:
-Script head
-1.Loop-Adress
-wait code
-IF player_defined-check
-Conditional Check
-Event
-2.Loop-Adress
-wait code
-IF player_defined-check
-Conditional Check
-Normal jump instruction to 1.LoopAdress

CODE
{$CLEO .cs}
:akt
03A4: name_thread 'AKT'

:akt01//----------------------------1.Loop Adress
0001: wait 0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @akt01
if
00DF:   actor $PLAYER_ACTOR driving
004D: jump_if_false @akt01

03C0: 1@ = actor $PLAYER_ACTOR car
0229: set_car 1@ color_to 17 0
02AC: set_car 1@ immunities BP 1 FP 1 EP 1 CP 1 MP 1
053F: set_car 1@ tires_vulnerability 0


:akt03//----------------------------2.Loop Adress
0001: wait 0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @akt03
if
80DF:   not actor $PLAYER_ACTOR driving
004D: jump_if_false @akt03

01C3: remove_references_to_car 1@

0002: jump @akt01//--------Normal jump instruction to 1.LoopAdress

The script above makes the player_car undestructable as soon as a car is entered
Therefore we must registrate the instance of the car and define it with a variable name
03C0: 1@ = actor $PLAYER_ACTOR car
Then we can use this variable name 1@ to make the car immun

After player has left the car, the reading process jumps back into the first Loop.

Youre not restricted by 2 Loops and there are also other kinds of script structure
But I recommand to build your scripts with this structure as long as you have not much experience

user posted image


______________________________________________________________________________________



Script exemble: Slowmotion

The script toggle by key_press between slowmotion and normal speed
set_gamespeed .3 make the game slow and also the reading process
wait 50 milliseconds needs ca. 1 second
A "if_player_defined"-check is not nessesary because the script dont have any codes which belongs to the player
After a passed key_press check it makes sense to set a wait of one second otherwise the key_press check will be repeated to fast.

CODE
{$CLEO .cs}
:slow_0
03A4: name_thread 'SLW'

:slow_1
0001: wait  0 ms
if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @slow_1
015D: set_gamespeed  .3
0001: wait  50 ms

:slow_2
0001: wait  0 ms
if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @slow_2
015D: set_gamespeed  1.0
0001: wait  1000 ms
0002: jump @slow_1


______________________________________________________________________________________



Next Step/ Spawn a 3D model

Using models requires 5 steps by applying with models and their definition in its variable name

1. first step to load the model
CODE
0247: request_model #INFERNUS

2. second step to prove if the model is loaded in an extra "load-model-check-Loop"
CODE
:Load_Model_Check
0001: wait  0 ms
if
0248:   model #INFERNUS available
004D: jump_if_false @Load_Model_Check

3. The model can be created as soon as the model file is loaded and define it with a variable name
CODE
00A5: 1@ = create_car #INFERNUS at 2487.5  -1660.5  13.35
0175: set_car 1@ z_angle_to 90.0

4. release the loaded model file if it not needed anymore
CODE
0249: release_model #INFERNUS

5. Release the defined item from script when the script has done its work
The script can then go to the status quo by jumping back into the first Loop
CODE
01C3: remove_references_to_car 1@  // Like turning a car into any random car

Releasing a spawned car by using 01C3: remove_references_to_car deletes the instance of the car for our script
but its still available in the game but can not used anymore in our script.

An other way to release the car is to delete it complete:
CODE
00A6: destroy_car 1@


This 2 different kinds for releasing exist for vehicles, actors and objects each with own opcodes

CODE
{$CLEO .cs}
:3dModels_1
03A4: name_thread 'MODL'

:3dModels_2
0001: wait  0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @3dModels_2
if
00FF:   actor $PLAYER_ACTOR  1 (in-sphere)near_point_on_foot 2491.5  -1667.5  13.35 radius  1.0  1.0  1.0
004D: jump_if_false @3dModels_2

0247: request_model #INFERNUS

:Load_Model_Check
0001: wait  0 ms
if
0248:   model #INFERNUS available
004D: jump_if_false @Load_Model_Check

00A5: 1@ = create_car #INFERNUS at 2487.5  -1660.5  13.35
0175: set_car 1@ z_angle_to 90.0
0249: release_model #INFERNUS

:3dModels_3
0001: wait  0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @3dModels_3
if
80FF:   NOT   actor $PLAYER_ACTOR  0 ()near_point_on_foot 2491.5  -1667.5  13.35 radius  2.0  2.0  2.0
004D: jump_if_false @3dModels_3
01C3: remove_references_to_car 1@  // Like turning a car into any random car
0002: jump @3dModels_2

Script above spawns the car Infernus in Grovestreet if player goes into red marker(sphere)
If player leave the spot the car will be released from script and the reading process jumps back into 1.Loop


# marks the connected entry as filename of a loadable model
For Cleo can only be used models which are defined in vehicles.ide, peds.ide or default.ide
Other models needs to use their ID number

For exemble to spawn the object 1655, waterjumpx2 of data\maps\generic\multiobj.ide
CODE
{$CLEO .cs}
:JumpR00
03A4: name_thread 'JPR'

:JumpR01
0001: wait  0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @JumpR01
if
00E1:   key_pressed  0  10//--------- No key  
004D: jump_if_false @JumpR01
0247: request_model 1655

:JumpR02
0001: wait  0 ms
if
0248:   model 1655 available
004D: jump_if_false @JumpR02
0172: 2@ = actor $PLAYER_ACTOR z_angle
04C4: create_coordinate 11@ 12@ 13@ from_actor $PLAYER_ACTOR offset 0.0 14.5 -1.8
0107: 1@ = create_object 1655 at  11@ 12@ 13@
0177: set_object 1@ z_angle_to  2@
0001: wait  0 ms
0249: release_model 1655
0001: wait  1000 ms
01C4: remove_references_to_object 1@  // This object will now disappear when the player looks away
0002: jump @JumpR01

Script above spawns a jumpramp by key_press

You can allways use the ID number to spawn models, also for cars and actors
As next we use 120 intead #TRIBOSS to spawn an actor

CODE
{$CLEO .cs}
:Actor_1
03A4: name_thread 'Actor'

:Actor_2
0001: wait  0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Actor_2
if
00FF:   actor $PLAYER_ACTOR  1 (in-sphere)near_point_on_foot 2491.5  -1667.5  13.35 radius  1.0  1.0  1.0
004D: jump_if_false @Actor_2

0247: request_model 120
0247: request_model #AK47

:Load_models_check
0001: wait  0 ms
00D6: if  and
0248:   model 120 available
0248:   model #AK47 available
004D: jump_if_false @Load_models_check

009A: 1@ = create_actor  24 120 at  2486.5  -1664.5  13.45
0173: set_actor 1@ z_angle_to  180.0
01B2: give_actor 1@ weapon  30 ammo  99999  // Load the weapon model before using this
02E2: set_actor 1@ weapon_accuracy_to  100
0223: set_actor 1@ health_to  1000
05E2: AS_actor 1@ kill_actor $PLAYER_ACTOR
0249: release_model 120

:Loop_1
0001: wait  0 ms
if
8118:   NOT   actor 1@ dead
004D: jump_if_false @Cleanup_1
if
0104:   actor $PLAYER_ACTOR near_actor 1@ radius  80.0  80.0  10.0 sphere  0
004D: jump_if_false @Cleanup_1
0002: jump @Loop_1

:Cleanup_1
01C2: remove_references_to_actor 1@ // Like turning an actor into a random pedestrian
0002: jump @Actor_2

Script above spawns the actor Triboss with gun in Grovestreet
If player leave the area with radius 80.0 80.0 or if the actor is dead,
the actor will be released from script and the reading process jumps back into 1.Loop

To give the actor or the player a weapon requires also to load first the model file
But to give it then really into his hands needs to insert a special weapon number which is not documented in any game file.
To find the right weapon number look in Sannybuilder HELP: SCM Documentation >> GTA SA >> Weapon numbers

Weapon given to actors are not created in same sense like the other models,
so it dont it to release them from script like other items

The spawned actors have predefined execodet behaviors which is dependent by the pedtype parameter of the create_actor opcode.
Look for pedtypes in Sannybuilder HELP: SCM Documentation >> GTA SA >> PedTypes

An actor with pedtype 8 is recruitable like a homie
CODE
009A: 1@ = create_actor  8 #TRIBOSS at  2486.5  -1664.5  13.45

An actor with pedtype 7 is agressive like an enemy gangmember
CODE
009A: 1@ = create_actor  7 #TRIBOSS at  2486.5  -1664.5  13.45


______________________________________________________________________________________



Placing cars by using parked_car_generator

Init parked_car_generators or pickups need to insert the Cleo opcode:

0A95: enable_thread_saving

Read the discription about enable_thread_saving in the theme:
Special Particularities in Cleo >> Registrate (store) the Script State

The placing of cars by using parked_car_generator dont allows the using of its variable name in vehicle associated opcodes
because its not a car but a car_generator

CODE
{$CLEO .cs}
:PaCar_1
03A4: name_thread "PACR"
0001: wait  1000 ms
0A95: enable_thread_saving

014B: 1@ = init_parked_car_generator #BANSHEE -1 -1  1 alarm  0 door_lock  0  0  10000 at  920.1994  2020.546  11.79 angle  100.0
014C: set_parked_car_generator 1@ cars_to_generate_to  101

032B: 2@ = create_weapon_pickup #MINIGUN  15 ammo  5000 at  2113.373 1520.674  10.82

0A93: end_custom_thread

Script above adds a parked_car_generator to spawn the car Banshee
and a weapon pickup with MINIGUN


generate_to 101 means that the car will be spawned again and again
generate_to 0 deactivates the car_generator

the two parameters after the model name -1 -1 gives the secondary and primary color
by setting -1 -1the game choose the colors randomly

by setting 0 17 it give black (0) to primary and red (17) to secondary color

alarm 0 can be a value between 0 and 100 and means the probable chance to execute an alarm

door_lock 0 can be a value between 0 and 100 and means the probable chance to execute a door lock


For pickups exist 2 different opcodes for 2 different kinds of pickups
032B: for weapons with ammo and for the Jetpack
0213: for melee weapons and objects like parachute (GUN_PARA) or bodyarmour (1242, bodyarmour)
the parameter after the model ID #MINIGUN 15 is the pickup-typ
Typ 15 is a pickup, which appears again and again
Typ 3 is a pickup, which appears only for one time


______________________________________________________________________________________
______________________________________________________________________________________




Special Particularities in Cleo

The extra-Cleo opcodes can be found in Sannybuilder-HELP
CLEO 3 Code Library >> CLEO 3: opcodes CLEO 3 Code Library>> CLEO 3: opcodes

______________________________________________________________________________________


Two major codes to start scripts are those which already exist in the main.scm and have been re-created for Cleo:

1.) 004F: create_thread @SAVEGAME starts an ordinary thread in the main.scm.
We dont need it in Cleo because it will be allready started from Cleo programm
To start an other thread of a cleo script, started from a cleo script needs following opcode:

0A92: create_custom_thread "New_Test_thread.cs"

The code needs to insert the name of the script file which should get started inclusiv dot and extension

The Cleo script file get then the file extension, which is written in the Cleo Script directive at the beginning of the script
{$CLEO .cs} = Cleo directive will be compiled to *.cs
As New_Test_thread.txt saved and compiled as New_Test_thread.cs

The script get then started at second once. Once from Cleo programm and once from the 0A92: create_custom_thread
It needs to set a conditional check at script beginn to let the script ending when it was started from Cleo programm.

An other chance is to give the script the extension .s
This needs to insert following:

0A92: create_custom_thread "New_Test_thread.s"

The Cleo script file which should get started, must have {$CLEO .cs} as directive and will be compiled as *.cs
You must change the extension manual by renaming from *.cs into *.s
In this case the Cleo script will only run if it was started with 0A92: create_custom_thread from an other Cleo script.

The opcode 0A92: create_custom_thread can transport more information to the script which should be started
This opcode can be extended with up to 30 values or variables as parameters
exemble:
CODE
0A92: create_custom_thread "PimpmyCarFULL2A1.cs" 1 2 0 3@ 4@ 5@ 6@ 29@ 8@ 9@ 10@

The started thread recieves these parameter values with following rule
0@ get value of 1.parameter
1@ get value of 2.parameter
2@ get value of 3.parameter
3@ get value of 4.parameter
4@ get value of 5.parameter
etc...
Its also possible to start much threads in one and the same Cleo script, started from the same script which recieve the create_thread commands.


2.)

0417: start_mission 3
starts a mission script of the main.scm. It needs to insert the number which the mission script get from the listing of the mission table

In Cleo dont exist a mission table and its listing.
But it needs allways a Cleo mission starter script with following command:

0A94: start_custom_mission "DriftMission"

The code needs to insert the name of the script file which should get started but without extension

The Cleo script file get then the file extension, which is written in the Cleo Script directive at the beginning of the script
{$CLEO .cm} = Cleo directive will be compiled to *.cm
As DriftMission.txt saved and compiled as DriftMission.cm

______________________________________________________________________________________


0A93: end_custom_thread let a script ending. Its disabled then.

The original version of this code of the main.scm is 004E: end_thread

And this original version must be used furthermore in Cleo mission scripts (*.cm)

004E: end_thread

Again:

0A93: end_custom_thread in normal Cleo scripts, compiled to a *.cs file
CODE
{$CLEO .cs}
0A93: end_custom_thread


004E: end_thread in mission scripts, compiled to a *.cm file
CODE
{$CLEO .cm}
004E: end_thread


______________________________________________________________________________________


Cleo creates extra save files if a save was done,
stored in folder CLEO\Cleo_save


By loading a save file must taken care to check that the presence of the scripts in Cleo folder
is the same as it was as the save was done.
Special attention in this case are going to those scripts which includes the Cleo opcode
to registrate and store the Script State

______________________________________________________________________________________



Registrate (store) the Script State

The Cleo scripts with extension .cs are started allways from new by loading a save game or start new game,
If such a script includes for exemble a parked car generator and execute it and after this a save game is made,
and then this save game is loaded,
will be created a duplicate of the item, in this case a duplicate of a parked car generator.
This happens with parked car generator, pickups as well as placed objects.

To prevent this or to read the script state by using special special Cleo-variable
must be used following Cleo opcode:
CODE
0A95: enable_thread_saving

This instruct Cleo to store the script state by making a savegame

______________________________________________________________________________________


Special Global Cleo Variable

This theme requires the understanding of the description about Local Variables and Global Variables
of the previous theme Datatype
especially this part which tells why there exist Local Variables and Global Variables
Global Variables are used in main.scm to communicate between different scripts and they are storable.
Using Global Variables in Cleo scripts can cause bugs and crashes

To realize Global Variables for Cleo scripts exist following Cleo opcode connected with a special expression:

Opcode 0AB3: and 0AB4:

The expression var together with a number, <var><space><number> is builing the Special Global Cleo Variable

CODE
0AB3: var 0 = 10
or
0006: 13@ =  10  // integer values
0AB3: var 0 = 13@

and
0AB4: 0@= var 0

var 0 up to var 999 will be stored, in exemble var 0 is stored with 10

to get then stored value into your script needs to submit into a local:
CODE
0AB4: 13@ = var 44
if
0039:   13@ ==  1  // integer values
004D: jump_if_false @nextlabel


______________________________________________________________________________________
______________________________________________________________________________________



Script Exemble by using Special Global Cleo Variable/ Store a car at any place
(requires to understand all previous themes of this tut)

Script below saves a car at any place
If player is in car and key F7 is pressed, it stores x,y,z coords and angle, also the car ID, its primary and secondary color and its paintjob.

The player exit then the car and car will be locked and made immun
If player leave the location and the distance to the car will be greater then 100.0
the car will be released from script and the reading process jumps back into an other Loop

If player then comes back to the location, near 80.0 the car will be spawned as new
Only to store the car settings by making savegame needs to give the values into the Special Global Cleo Variable

As I wrote in the theme "Registrate (store) the Script State"
is the Carstore script running from new by loading a save game or start new game"...

...and checks first if var 955 is ciro
its only not ciro if a car was stored in the loaded savegame

If var 955 is ciro, the script starts with the 1.Loop
If var 955 is not ciro, the reading process jumps into the 3.Loop with the check if player is near the car store location

A special side effect of this kind of car store is that the storable entries then available in memory for all savefiles.
Only by shut down the game and start again is the stored car only stored in the savegame which was done to store the car.

CODE
{$CLEO .cs}
:CARSTORE
03A4: name_thread 'CARSTOR'
0001: wait 1000 ms
0AB4: 7@ = var 955
00D6: if
8039:   not  7@ == 0
004D: jump_if_false @CARSTOR_150
0AB4: 3@ = var 951
0AB4: 4@ = var 952
0AB4: 5@ = var 953
0AB4: 6@ = var 954
0AB4: 7@ = var 955
0AB4: 8@ = var 956
0AB4: 9@ = var 957
0AB4: 10@ = var 958
0093: 3@ = integer 3@ to_float
0093: 4@ = integer 4@ to_float
0093: 5@ = integer 5@ to_float
0093: 6@ = integer 6@ to_float
0001: wait 1000 ms
0002: jump @CARSTOR_555

:CARSTOR_150
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @CARSTOR_150
00D6: if and
00DF:   actor $PLAYER_ACTOR driving
0AB0:   key_pressed 118//-------------------key F7
004D: jump_if_false @CARSTOR_150
01B4: set_player $PLAYER_CHAR can_move 0
03C0: 2@ = actor $PLAYER_ACTOR car
00AA: store_car 2@ position_to 3@ 4@ 5@
0174: 6@ = car 2@ Z_angle
0441: 7@ = car 2@ model
0988: get_car 2@ paintjob 8@
03F3: get_car 2@ primary_color_to 9@ secondary_color_to 10@
020A: set_car 2@ door_status_to 0
02AC: set_car 2@ immunities BP 1 FP 1 EP 1 CP 1 MP 1
0519: set_car 2@ locked 1
0633: AS_actor $PLAYER_ACTOR exit_car
0092: 13@ = float 3@ to_integer
0092: 14@ = float 4@ to_integer
0092: 15@ = float 5@ to_integer
0092: 16@ = float 6@ to_integer
0AB3: var 951 = 13@
0AB3: var 952 = 14@
0AB3: var 953 = 15@
0AB3: var 954 = 16@
0AB3: var 955 = 7@
0AB3: var 956 = 8@
0AB3: var 957 = 9@
0AB3: var 958 = 10@
0001: wait 2000 ms
01B4: set_player $PLAYER_CHAR can_move 1
0002: jump @CARSTOR_403

:CARSTOR_403
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @CARSTOR_550
00D6: if
82BF:   not car 2@ sunk
004D: jump_if_false @CARSTOR_738
00D6: if
8119:   not car 2@ wrecked
004D: jump_if_false @CARSTOR_550
00D6: if
0202:   actor $PLAYER_ACTOR near_car 2@ radius 100.0 100.0 flag 0
004D: jump_if_false @CARSTOR_550
00D6: if
00DF:   actor $PLAYER_ACTOR driving
004D: jump_if_false @CARSTOR_403
00D6: if
00DB:   actor $PLAYER_ACTOR in_car 2@
004D: jump_if_false @CARSTOR_403
02AC: set_car 2@ immunities BP 0 FP 0 EP 0 CP 0 MP 0
0519: set_car 2@ locked 0
0002: jump @CARSTOR_738

:CARSTOR_550
01C3: remove_references_to_car 2@ // Like turning a car into any random car

:CARSTOR_555
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @CARSTOR_555
00D6: if
00FE:   actor $PLAYER_ACTOR sphere 0 in_sphere 3@ 4@ 5@ radius 80.0 80.0 50.0
004D: jump_if_false @CARSTOR_555
0002: jump @CARSTOR_624

:CARSTOR_624
0247: load_model 7@

:CARSTOR_629
0001: wait 0 ms
00D6: if
0248:   model 7@ available
004D: jump_if_false @CARSTOR_629
0001: wait 0 ms
00A5: 2@ = create_car 7@ at 3@ 4@ 5@
0175: set_car 2@ Z_angle_to 6@
06ED: set_car 2@ paintjob 8@
0229: set_car 2@ primary_color_to 9@ secondary_color_to 10@
020A: set_car 2@ door_status_to 0
02AC: set_car 2@ immunities BP 1 FP 1 EP 1 CP 1 MP 1
0519: set_car 2@ locked 1
0249: release_model 7@
0002: jump @CARSTOR_403

:CARSTOR_738
01C3: remove_references_to_car 2@ // Like turning a car into any random car
0AB3: var 955 = 0
0002: jump @CARSTOR_150


______________________________________________________________________________________
______________________________________________________________________________________



Template for Cleo Mission Script
(requires to understand all previous themes of this tut)

To run a Cleo mission script requires allways 2 Cleo script files
1. A .cs file to start the Cleo mission script file
2. The Cleo mission script file itself with extension .cm


The mission starter thread below is done with a conditional check to check if the player is near a specified point,
which must passed to start the mission.

The coordinates of the near_point check are the location in San Fierro/Carlton Heights near savehouse
Edit the coordinates to set your own location for starting

The parameter 1 of the near_point opcode 00FE: actor $PLAYER_ACTOR 1 (in-sphere)near_point
is displaying a red marker (sphere).
If the parameter is ciro 00FE: actor $PLAYER_ACTOR 0 (in-sphere)near_point does not displaying a red marker.
To display a red marker in this way needs to set 0ms as maximum in the wait code of this Loop
CODE
{$CLEO .cs}
:Test_M_Start_1
03A4: name_thread 'TSTM'

:Test_M_Start_2
0001: wait  0 ms
00D6: if  0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Test_M_Start_2
00D6: if  0
0038:   $ONMISSION ==  0  // integer values
004D: jump_if_false @Test_M_Start_2

:Test_M_Start_6
00D6: if  0
00FE:   actor $PLAYER_ACTOR  1 (in-sphere)near_point 2480.1343 -1665.475 13.3348 radius  3.5  3.5  5.5
004D: jump_if_false @Test_M_Start_2
00BA: text_styled 'STAD_02'  1000 ms  2
0004: $ONMISSION =  1  // integer values
0A94: start_custom_mission "TestMission"  //
0002: jump @Test_M_Start_2

The mission starter script includes the following Cleo opcode to start the Cleo mission script:
0A94: start_custom_mission "TestMission"

The code needs to insert the name of the script file which should get started but without extension

The Cleo script file get then the file extension, which is written in the Cleo Script directive at the beginning of the script
{$CLEO .cm} = Cleo directive will be compiled to *.cm
As TestMission.txt saved and compiled as TestMission.cm

CODE
{$CLEO .cm}
:TestMiss_1
03A4: name_thread "TESTM"  
0050: gosub @TestMiss_main_1
00D6: if  0
0112:   wasted_or_busted
004D: jump_if_false @TestMiss_end_1
0050: gosub @TestMiss_fail_1                    

:TestMiss_end_1
0050: gosub @TestMiss_clep_1
004E: end_thread

:TestMiss_main_1
0317: increment_mission_attempts//here starts the missionscript
0004: $ONMISSION =  1
054C: use_GXT_table 'MENU2P'
00BC: text_highpriority 'MENU_18'  5000 ms  1

:TestMiss_11
0001: wait 0 ms
if and
02D8:   actor $PLAYER_ACTOR currentweapon == 0
00E1:   key_pressed 0 17
004D: jump_if_false @TestMiss_11

:TestMiss_pass_1
00BA: text_styled 'M_PASS'  5000 ms  1
0051: return

:TestMiss_fail_1
00BA: text_styled 'M_FAIL'  5000 ms  1
0051: return

:TestMiss_clep_1
0004: $ONMISSION =  0
00D8: mission_cleanup
0051: return


When the mission script from above is running it can be completed by pressing fire key while player have weapon 0/naked fist.


The secret of the onmission mode

$ONMISSION is not only a variable to check if a mission script is running or not.
Set $ONMISSION to 1 activates a special mission mode if some important conditions are accomplished.
R*s mission scripts run allways in a subroutine which will be cancled from the exe if player is wasted or busted like reading a return code in the script.

1. At first it needs to set $ONMISSION equal to on_mission_flag
CODE
0180: set_on_mission_flag_to $ONMISSION// Note: your missions have to use the variable defined here

This code is set by default in the main part of the original main.scm

2. By starting the mission script must sended the reading precess with a gosub command into a subroutine for the main part of the mission script.
It must be the first gosub of the mission script.
CODE
0050: gosub @TestMiss_main_1


3. By starting the mission script must be activated the onmission mode with
CODE
0004: $ONMISSION =  1
0317: increment_mission_attempts//here starts the missionscript


Then the mission is running in a subroutine and dont needs to check if player is defined or dead or busted.
If player dies or get busted, the exe cancels the subroutine as like as a return code of our script is readed

The rest of the mission script is just a cunning gosub construct.

______________________________________________________________________________________
______________________________________________________________________________________



gosub

The gosub command leads the reading process to an excluded subscript.
Excluded means the codes of the subscript are not binded in code following of our thread.
CODE
0050: gosub @MODLSUBROUTINE

The subscript must end with return
CODE
0051: return


If the subscript ends with 0051: return, our thread then continues with reading the codes after the 0050: gosub command

Exemble:
CODE
{$CLEO .cs}
:MODLSUB_1
03A4: name_thread 'MODLSUB'

:MODLSUB_2
0001: wait  0 ms
00D6: if  0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @MODLSUB_2
00D6: if  0
00FF:   actor $PLAYER_ACTOR  1 (in-sphere)near_point_on_foot 2491.5  -1667.5  13.35 radius  1.0  1.0  1.0
004D: jump_if_false @MODLSUB_2
0050: gosub @MODLSUBROUTINE

:Loop_1
0001: wait  0 ms
00D6: if  0
8118:   NOT   actor 1@ dead
004D: jump_if_false @Cleanup_1
00D6: if  0
0104:   actor $PLAYER_ACTOR near_actor 1@ radius  80.0  80.0  10.0 sphere  0
004D: jump_if_false @Cleanup_1
0002: jump @Loop_1

:Cleanup_1
01C2: remove_references_to_actor 1@ // Like turning an actor into a random pedestrian
0002: jump @MODLSUB_2


:MODLSUBROUTINE
0005: 1@ = 2473.25
0005: 2@ = -1657.79
0005: 3@ = 13.4
0005: 4@ = 2501.12
0005: 5@ = -1676.5
0005: 6@ = 13.4
0208: 7@ = random_float_in_ranges 1@ 4@
0208: 8@ = random_float_in_ranges 2@ 5@
0208: 9@ = random_float_in_ranges 3@ 6@
0247: request_model #TRIBOSS
0247: request_model #AK47

:Load_MODLSUB_Check
0001: wait  0 ms
00D6: if  and
0248:   model #TRIBOSS available
0248:   model #AK47 available
004D: jump_if_false @Load_MODLSUB_Check

009A: 1@ = create_actor  24 #TRIBOSS at  7@ 8@ 9@
0173: set_actor 1@ z_angle_to  180.0
01B2: give_actor 1@ weapon  30 ammo  99999  // Load the weapon model before using this
02E2: set_actor 1@ weapon_accuracy_to  100
0223: set_actor 1@ health_to  1000
05E2: AS_actor 1@ kill_actor $PLAYER_ACTOR
0249: release_model #TRIBOSS
0051: return

Script above spawns the actor Triboss with gun in Grovestreet at different places
The coords are generated random
The part with the coords generation and actor spawn is excluded in a subscript

If player leave the area with radius 80.0 80.0 or if the actor is dead,
the actor will be released from script and the reading process jumps back into 1.Loop


______________________________________________________________________________________
______________________________________________________________________________________


Additional Themes

  • Slave Boy, In45do, TheGodfather. and 1 other like this

coin-god
  • coin-god

    High Roller

  • $outh $ide Hoodz
  • Joined: 18 Mar 2007

#2

Posted 22 March 2009 - 12:24 AM

Great work on the Tuto ZAZ icon14.gif

Dutchy3010
  • Dutchy3010

    Female SCM coder!

  • Moderator
  • Joined: 30 Jul 2006
  • Netherlands
  • Best Script 2013 [DYOM]
    Best Script 2012 [DYOM]

#3

Posted 22 March 2009 - 12:32 AM

Nice ZAZ. smile.gif

I already told you, this was the tutorial I was missing on this forum. A tutorial all about CLEO. smile.gif

cookie.gif

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#4

Posted 23 March 2009 - 04:42 PM Edited by ZAZ, 30 December 2013 - 03:53 PM.

Additional Themes
- Create a FXT file
- Load a special actor
- Tuning parts
- Animations
- sounds of Audio folder

Give access with math coding


______________________________________________________________________________________

______________________________________________________________________________________


Create a FXT file to show your own text message

Cleo makes possible to use a custom file to store text for using ingame
its called fake XT, according to the gxt file of the game
This requires to install the GxtHook.cleo in Cleo folder and an extra folder for the fxt files

Much users make it wrong, so again the explanation:
GxtHook.cleo must be placed in Cleo folder, not in a sub folder
Cleo_text folder must be a sub folder of Cleo folder
The fxt file must be placed in Cleo_text folder

GTASA game dir
- Cleo:GxtHook.cleo
- Cleo\Cleo_text: text.fxt

The fxt file will be read by game start.
If you have modified your fxt file it needs first to close the game complete
and then start again to apply the changes.

To create a fxt file needs to insert an entry name for the script and the real text to show, in a normal txt file
Then rename the file by chaning the extension from .txt into .fxt
Or create it directly with Sannybuilder and save it as .fxt , choose Any file (*.*) as extension

Entry name for the script and the real text to show must be done in this way:
<Entryname><space><text message>
only 1 space between Entryname and text message
Important:
only 1 space between words of the text message are allowed and NO space at the end
Maximum 7 symbols as entry name are allowed

Exemble:
Copy this line into a blanc page and save it as anyname.fxt
TXT_01 This is text of Cleo fxt file
Then use the script below to show the text by key_press
{$CLEO .cs}
:FXT
03A4: name_thread 'FXT'

:FXT_01
0001: wait 0 ms
if
0AB0:   key_pressed 84//--------- key = T
004D: jump_if_false @FXT_01
00BA: text_styled 'TXT_01'  1000 ms  1
0A93: end_custom_thread

The opcodes to show text are the same like to show text of american.gxt
There exist several opcodes to show text in different kinds. Look in opcode search tool.
Or look in Dutchys coding tut

If you wonna use entry names of american.gxt to use its text messages,
so look for a complete translation txt file in Sanny Install directory:
Sanny Builder 3\help\GXT Strings\GTASA.text


______________________________________________________________________________________
______________________________________________________________________________________



Load a specialactor

There exist 2 kinds of actor models in the game.
One kind are models which are defined with a ID number in peds.ide and must be loaded with opcode 0247:

The other kind of actor models are not defined in peds.ide and must be loaded with opcode 023C:
These are called special actors and there are ID numbers reserved in peds.ide. From 290 up to 299
So 10 different special actors can be spawned at same time.

According to the theme Spawn a 3D model we need also 5 steps but with other opcodes

1. first step to load the special actor needs to insert the model name as short string
023C: load_special_actor 'ogloc' as 1
2. second step to prove if the model is loaded in an extra "load-model-check-Loop"
:Load_Model_Check
0001: wait  0 ms
00D6: if  0
023D:   special_actor  1 loaded
004D: jump_if_false @Load_Model_Check
3. The model can be created as soon as the model file is loaded and define it with a variable name
009A: 0@ = create_actor_pedtype 24 model #SPECIAL01 at 2491.5  -1667.5  13.35
4. release the loaded special actor model file if it not needed anymore

0296: unload_special_actor  1
5. Release the defined item from script when the script has done its work
same like other actors
01C2: remove_references_to_actor 0@

The script below spawns a special actor by key_press at 4 virtual meters infront of the player
The script reads also the current interior to can spawn everywhere by using opcode 0860:
If the actor is dead he will be released from script und the reading process jumps back into 1.Loop

{$CLEO .cs}
:SPLACTOR_1
03A4: name_thread 'SPACTOR'

:SPACTOR_11
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @SPACTOR_11
00D6: if
0AB0:   key_pressed 57//--------------------------------- key 9
004D: jump_if_false @SPACTOR_11
077E: get_active_interior_to 29@
023C: load_special_actor 'ogloc' as 1 // models 290-299

:SPACTOR_51
0001: wait 0 ms
00D6: if
823D:   not special_actor 1 loaded
004D: jump_if_false @SPACTOR_90
023C: load_special_actor 'OGLOC' as 1 // models 290-299
0002: jump @SPACTOR_51

:SPACTOR_90
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset 0.0 4.0 0.2
009A: 0@ = create_actor_pedtype 24 model #SPECIAL01 at 11@ 12@ 13@
0223: set_actor 0@ health_to 10000
0860: link_actor 0@ to_interior 29@
0296: unload_special_actor 1

:SPACTOR_158
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @SPACTOR_201
00D6: if
8118:   not actor 0@ dead
004D: jump_if_false @SPACTOR_201
0002: jump @SPACTOR_158

:SPACTOR_201
01C2: remove_references_to_actor 0@ // Like turning an actor into a random pedestrian
0002: jump @SPACTOR_11




The opcode to create the actor is the same like for a normal ped.
Instead of inserting the peds model name will be used the entry #SPECIAL01
SPECIAL01 represent the ID 290 which the actor then get from the script
Its also possible to use the ID numbers instead of SPECIAL01

By creating more different special actors needs to give it then entries with numbers in ascending order
#SPECIAL01 and #SPECIAL02 or 290 and 291

The script below spawns 5 special actors
If one actor is dead all actors will be released from script und the reading process jumps back into 1.Loop
An advantage of special actors is to can add a new actor model with new model name without editing data files
Important: Maximum 7 symbols are allowed as model name

{$CLEO .cs}
:SPLACTOR_1
03A4: name_thread 'SPACMOR'

:SPACMOR_11
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @SPACMOR_11
00D6: if
0AB0:   key_pressed 57//--------------------------------- key 9
004D: jump_if_false @SPACMOR_11
077E: get_active_interior_to 29@
023C: load_special_actor 'OGLOC' as 1 // models 290-299
023C: load_special_actor 'SMOKE' as 2 // models 290-299
023C: load_special_actor 'SWEET' as 3 // models 290-299
023C: load_special_actor 'RYDER2' as 4 // models 290-299
023C: load_special_actor 'CESAR' as 5 // models 290-299

:SPACMOR_116
0001: wait 0 ms
00D6: if or
823D:   not special_actor 1 loaded
823D:   not special_actor 2 loaded
823D:   not special_actor 3 loaded
823D:   not special_actor 4 loaded
823D:   not special_actor 5 loaded
004D: jump_if_false @SPACMOR_223
023C: load_special_actor 'OGLOC' as 1 // models 290-299
023C: load_special_actor 'SMOKE' as 2 // models 290-299
023C: load_special_actor 'SWEET' as 3 // models 290-299
023C: load_special_actor 'RYDER2' as 4 // models 290-299
023C: load_special_actor 'CESAR' as 5 // models 290-299
0002: jump @SPACMOR_116

:SPACMOR_223
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset -2.0 2.0 0.2
009A: 0@ = create_actor_pedtype 24 model #SPECIAL01 at 11@ 12@ 13@
0223: set_actor 0@ health_to 10000
0860: link_actor 0@ to_interior 29@
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset 0.0 2.0 0.2
009A: 1@ = create_actor_pedtype 24 model 291 at 11@ 12@ 13@
0223: set_actor 1@ health_to 10000
0860: link_actor 1@ to_interior 29@
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset 2.0 2.0 0.2
009A: 2@ = create_actor_pedtype 24 model #SPECIAL03 at 11@ 12@ 13@
0223: set_actor 2@ health_to 10000
0860: link_actor 2@ to_interior 29@
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset -2.0 4.0 0.2
009A: 3@ = create_actor_pedtype 24 model 293 at 11@ 12@ 13@
0223: set_actor 3@ health_to 10000
0860: link_actor 3@ to_interior 29@
04C4: store_coords_to 11@ 12@ 13@ from_actor $PLAYER_ACTOR with_offset 2.0 4.0 0.2
009A: 4@ = create_actor_pedtype 24 model #SPECIAL05 at 11@ 12@ 13@
0223: set_actor 4@ health_to 10000
0860: link_actor 4@ to_interior 29@
0296: unload_special_actor 1
0296: unload_special_actor 2
0296: unload_special_actor 3
0296: unload_special_actor 4
0296: unload_special_actor 5

:SPACMOR_563
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @SPACMOR_626
00D6: if and
8118:   not actor 0@ dead
8118:   not actor 1@ dead
8118:   not actor 2@ dead
8118:   not actor 3@ dead
8118:   not actor 4@ dead
004D: jump_if_false @SPACMOR_626
0002: jump @SPACMOR_563

:SPACMOR_626
01C2: remove_references_to_actor 0@ // Like turning an actor into a random pedestrian
01C2: remove_references_to_actor 1@ // Like turning an actor into a random pedestrian
01C2: remove_references_to_actor 2@ // Like turning an actor into a random pedestrian
01C2: remove_references_to_actor 3@ // Like turning an actor into a random pedestrian
01C2: remove_references_to_actor 4@ // Like turning an actor into a random pedestrian
0002: jump @SPACMOR_11



______________________________________________________________________________________
______________________________________________________________________________________


Tuningparts

According to the theme Spawn a 3D model we need in this case only 4 steps and with other opcodes

1. first step to load the tuning part
06E9: request_car_component #hydralics
06E9: request_car_component #NTO_B_S
06E9: request_car_component 1115
2. second step to prove if the model is loaded in an extra "load-model-check-Loop"
:Load_Model_Check
0001: wait  0 ms
if  and
06EA:   car_component_available #hydralics
06EA:   car_component_available #NTO_B_S
06EA:   car_component_available 1115
004D: jump_if_false @Load_Model_Check
3. The tuning part can be created as soon as the model file is loaded by attaching to the car
06E7: 1@ = add_car_component #NTO_B_S to_car 0@
06E7: 2@ = add_car_component #hydralics to_car 0@
06E7: 3@ = add_car_component 1115 to_car 0@
4. release the loaded tuning part model file if it is not needed anymore
06EB: release_car_component #hydralics
06EB: release_car_component #NTO_B_S
06EB: release_car_component 1115
To release the defined item from script is not nessesary

The script below spawns the car SLAMVAN with nitro, hydraulics and front bumper
and the paintjob 1 in Grovestreet if player goes into red marker
Adding paintjobs needs first to give the car white colors
Painjobs requires existing paintjob textures
These are additional txd files which have the same name like the dff model and its basic txd with an additional number
slamvan.dff and slamvan.txd as basic model files
slamvan1.txd as paintjob 0, slamvan2.txd as paintjob 1, etc...
If player leave the spot the car will be released from script and the reading process jumps back into 1.Loop

{$CLEO .cs}
:TuneP_1
03A4: name_thread 'TuneP'

:TuneP_2
0001: wait  0 ms
00D6: if  
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @TuneP_2
00D6: if  
00FF:   actor $PLAYER_ACTOR  1 (in-sphere)near_point_on_foot 2491.5  -1667.5  13.35 radius  1.0  1.0  1.0
004D: jump_if_false @TuneP_2

0247: request_model #SLAMVAN
06E9: request_car_component #hydralics
06E9: request_car_component #NTO_B_S
06E9: request_car_component 1115

:Load_Model_Check
0001: wait  0 ms
if  and
0248:   model #SLAMVAN available
06EA:   car_component_available #hydralics
06EA:   car_component_available #NTO_B_S
06EA:   car_component_available 1115
004D: jump_if_false @Load_Model_Check

00A5: 0@ = create_car #SLAMVAN at 2487.5  -1660.5  13.35
0175: set_car 0@ z_angle_to 180.0

06E7: 1@ = add_car_component #NTO_B_S to_car 0@
06E7: 2@ = add_car_component #hydralics to_car 0@
06E7: 3@ = add_car_component 1115 to_car 0@

0229: set_car 0@ color_to  1  1
06ED: set_car 0@ paintjob  1

06EB: release_car_component #hydralics
06EB: release_car_component #NTO_B_S
06EB: release_car_component 1115
0249: release_model #SLAMVAN

:TuneP_4
0001: wait  0 ms
00D6: if  
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @TuneP_4
00D6: if  
80FF:   NOT   actor $PLAYER_ACTOR  0 ()near_point_on_foot 2491.5  -1667.5  13.35 radius  2.0  2.0  2.0
004D: jump_if_false @TuneP_4
01C3: remove_references_to_car 0@  // Like turning a car into any random car
0002: jump @TuneP_2




______________________________________________________________________________________
______________________________________________________________________________________



Animations

To use animations exist 2 opcodes, 0605: and 0812:
0605: actor $PLAYER_ACTOR perform_animation_sequence "TAI_CHI_IN" IFP_file "PARK" 4.0 loop 0 1 1 0 time -1
0812: AS_actor $PLAYER_ACTOR perform_animation "SWIM_BREAST" IFP_file "SWIM" 1.0 loopA 1 lockX 1 lockY 1 lockF 1 time -2
The animations are embeded in the IFP files

Important:

The IFP file ped.ifp is placed in GTASA\anim folder and all animations of ped.ifp are loaded by gamestart
It dont need to load the animation for the script. Never load the ifp file "ped" !!

The other IFP files are archived in gta3.img
It needs first to load the IFP file before using an animation of its file

The script below is an exemble to assign an animation of IFP file "ped" by key_press to player actor
{$CLEO .cs}
:IFP_PED
03A4: name_thread 'IFP_PED'

:IFP_PED_01
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @IFP_PED_01
if  and
0AB0:   key_pressed 8//-----------------key = Backspace
80DF:   not actor $PLAYER_ACTOR driving
004D: jump_if_false @IFP_PED_01
0605: actor $PLAYER_ACTOR perform_animation_sequence "CAR_ROLLOUT_RHS" IFP_file "PED" 4.0 loop 0 1 1 0 time -1
0001: wait 2000 ms
0002: jump @IFP_PED_01

Several animations are defined as extra opcodes
Some exembles:
05C7: AS_actor $PLAYER_ACTOR use_atm
05C2: AS_actor $PLAYER_ACTOR show_the_finger
05C9: AS_actor $PLAYER_ACTOR on_guard 2000 ms
05C4: AS_actor $PLAYER_ACTOR hands_up 15000 ms
0729: AS_actor $PLAYER_ACTOR hold_cellphone 1// requires to load first the model #cellphone
0729: AS_actor $PLAYER_ACTOR hold_cellphone 0
05BC: AS_actor $PLAYER_ACTOR jump 1
05C3: AS_actor $PLAYER_ACTOR hands_cower
05C5: AS_actor $PLAYER_ACTOR cower 3000 ms




The other IFP files are archived in gta3.img and needs first to load the IFP file before using an animation of its file
According to the theme Spawn a 3D model we need also 5 steps but with other opcodes

1. first step to load the IFP file needs to insert the IFP file name as long string
04ED: load_animation "PARK"
2. second step to prove if the file is loaded in an extra "load-model-check-Loop"
:Load_Model_Check
0001: wait  0 ms
00D6: if  0
04EE:   animation "PARK" loaded
004D: jump_if_false @Load_Model_Check
3. The animation can now assigned to an actor as soon as the IFP file is loaded and the actor is available.
It requires to insert animation name and name of IFP file as long string

0812: AS_actor $PLAYER_ACTOR perform_animation "TAI_CHI_IN" IFP_file "PARK" 1.0 loopA 1 lockX 1 lockY 1 lockF 1 time -2
4. release the loaded IFP file if it is not needed anymore
04EF: release_animation "PARK"
5. Release a defined item is not possible but in some cases it needs to remove the animation from actor
0792: disembark_instantly_actor $PLAYER_ACTOR
In addition by using animation packs, it needs to release the pack

061B: remove_references_to_AS_pack 0@

The script below is an exemble to assign an animation of IFP file "PARK" by key_press to player actor
The animation will be repeated as long as the key is not pressed again, because of the value 1 in the parameter of loopA
{$CLEO .cs}
:IFP_PARK
03A4: name_thread 'IFPPARK'

:IFP_PARK_11
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @IFP_PARK_11
00D6: if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @IFP_PARK_11
04ED: load_animation "PARK"

:IFP_PARK_54
0001: wait 0 ms
00D6: if
04EE:   animation "PARK" loaded
004D: jump_if_false @IFP_PARK_54

0812: AS_actor $PLAYER_ACTOR perform_animation "TAI_CHI_IN" IFP_file "PARK" 1.0 loopA 1 lockX 1 lockY 1 lockF 1 time -2 // versionB
0001: wait 1000 ms

:IFP_PARK_141
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @IFP_PARK_141
00D6: if and
8AB0:   not key_pressed 8//-----------------key = Backspace
80E1:   not player 0 pressed_key 15
004D: jump_if_false @IFP_PARK_221
0002: jump @IFP_PARK_141

:IFP_PARK_221
0792: disembark_instantly_actor $PLAYER_ACTOR
04EF: release_animation "PARK"
0001: wait 1000 ms
0002: jump @IFP_PARK_11

Combine several animation to an AS_pack
The script below assigns sevaral animations of different IFP files combined in an AS_pack by key_press to player actor
{$CLEO .cs}
:AMPAK_00
03A4: name_thread 'APK'
0001: wait  2000 ms

:AMPAK_1
0001: wait 50 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @AMPAK_1
if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @AMPAK_1
04ED: load_animation "STRIP"
04ED: load_animation "DANCING"

:AMPAK_12
0001: wait  0 ms
if  and
04EE:   animation "STRIP" loaded
04EE:   animation "DANCING" loaded
004D: jump_if_false @AMPAK_13
0002: jump @AMPAK_14

:AMPAK_13
04ED: load_animation "STRIP"
04ED: load_animation "DANCING"
0002: jump @AMPAK_12

:AMPAK_14
0615: define_AS_pack_begin 0@
0605: actor -1 perform_animation_sequence "STR_B2C" from_file "STRIP"  4.0  0  0  0  1 -1 ms  
0605: actor -1 perform_animation_sequence "DNCE_M_A" from_file "DANCING"  4.0  0  0  0  1 -1 ms
0605: actor -1 perform_animation_sequence "STR_B2C" from_file "STRIP"  4.0  0  0  0  1 -1 ms
0605: actor -1 perform_animation_sequence "DNCE_M_A" from_file "DANCING"  4.0  0  0  0  1 -1 ms
0605: actor -1 perform_animation_sequence "STR_B2C" from_file "STRIP"  4.0  0  0  0  1 -1 ms
0605: actor -1 perform_animation_sequence "DAN_LOOP_A" from_file "DANCING"  4.0  0  0  0  1 -1 ms
0605: actor -1 perform_animation_sequence "DNCE_M_D" from_file "DANCING"  4.0  0  0  0  1 -1 ms
0643: set_AS_pack 0@ loop 1
0616: define_AS_pack_end 0@
0618: assign_actor $PLAYER_ACTOR to_AS_pack 0@
0001: wait 1000 ms

:AMPAK_21
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @AMPAK_end
if
80E1:   not key_pressed  0  15
004D: jump_if_false @AMPAK_end
if  or
0611:   actor $PLAYER_ACTOR animation == "STR_B2C"
0611:   actor $PLAYER_ACTOR animation == "DNCE_M_A"
0611:   actor $PLAYER_ACTOR animation == "STR_B2C"
0611:   actor $PLAYER_ACTOR animation == "DNCE_M_D"
004D: jump_if_false @AMPAK_end
0002: jump @AMPAK_21

:AMPAK_end
061B: remove_references_to_AS_pack 0@
04EF: release_animation "STRIP"
04EF: release_animation "DANCING"
0002: jump @AMPAK_1

Animation in air needs to move the actor with opcode 083C: and to use animation code 0812: with -2 as last parameter
Script below let the player swimming in air by key_press
{$CLEO .cs}
:Airswim
03A4: name_thread 'Airswim'

:AIRSWIM_11
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @AIRSWIM_11
00D6: if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @AIRSWIM_11
04ED: load_animation "SWIM"

:AIRSWIM_54
0001: wait 0 ms
00D6: if
04EE:   animation "SWIM" loaded
004D: jump_if_false @AIRSWIM_54
083C: set_actor $PLAYER_ACTOR velocity_in_direction_XYZ 0.0 0.0 20.0
0001: wait 1000 ms
0812: AS_actor $PLAYER_ACTOR perform_animation "SWIM_BREAST" IFP_file "SWIM" 1.0 loopA 1 lockX 1 lockY 1 lockF 1 time -2 // versionB

:AIRSWIM_141
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @AIRSWIM_141
083C: set_actor $PLAYER_ACTOR velocity_in_direction_XYZ 0.0 2.0 2.0
00D6: if and
8AB0:   not key_pressed 8
0611:   actor $PLAYER_ACTOR performing_animation "SWIM_BREAST"
004D: jump_if_false @AIRSWIM_221
0002: jump @AIRSWIM_141

:AIRSWIM_221
0792: disembark_instantly_actor $PLAYER_ACTOR
04EF: release_animation "SWIM"
0001: wait 1000 ms
0002: jump @AIRSWIM_11

How to find Animations:
use Ryosukes Animation Manager
The animations are stored in *.ifp files
One ifp file is the GTASA\anim\ped.ifp
(GTASA\anim\anim.img is unused)
The other ifp files are in gta3.img like colt45.ifp, python.ifp, rifle.ifp, tec.ifp, weapons.ifp
Import these and play these with Animation Manager
Deji provides a list of the animation names: List of animations in San Andreas

______________________________________________________________________________________
______________________________________________________________________________________


Music, wave and sounds of Audio folder

GTASA\AUDIO\Streams includes *.ogg files for music in vehicle, interiors, some missions and for cutscene
GTASA\AUDIO\SFX includes *.wav files for sounds and dialoge
look at GTA: SA SFX Directory

The Radio Musicfiles can only be played in vehicles:
There is no chance for scripting to play them on foot
For radio exist only these codes to set radio station, to get radio staion number and to set to favourites station

041E: set_radio_station 3
051E: 1@ = get_current_radio_station
0A26: set_radio_to_favorite_station
Music of GTASA\AUDIO\Streams\BEATand AMBIENCEcan be played with other opcodes

0953: get_soundtrack_status_to 17@
if
0039:   17@ ==  0;; integer values
004D: jump_if_false @
//
0952: load_soundtrack 12
//
0954: start_playing_loaded_soundtrack
//
0955: end_playing_loaded_soundtrack


//use following track numbers: 1, 2, 3, 4, 8, 9, 10, 12, 13
Play titel song
0394: play_music 1
//or
0394: play_music 2


its mostly used as flourish by mission comlete
find the song file in GTASA\AUDIO\Streams\BEAT



Sounds or speeches of GTASA\AUDIO\SFXare used for "wav"- or "sound"- playing
But the sounds of GENRL can not be played with scripting


A part of them are documented in data\AudioEvents.txt
These for the story dialoges and sounds for gameplay


///////SOUNDS/////
A small part of the listed sounds in AudioEvents can be startet with play sound opcodes: 018C: 097A: 09F1:
Find sounds in the range from SOUND_1002 to SOUND_1191. Not all worked by me. It seems that someone only can used from the exe
Someone of these sounds are durable and must be started with 018D: and stoped with 018E:

Some other ones of these sounds have a replay mode (music for minigames) and can be stoped with a stop sound
SOUND_PILOT_AWARD_TRACK_START 1187 start sound
SOUND_PILOT_AWARD_TRACK_STOP 1188 stop sound


///////WAVE/////
The most part of AudioEvents.txt includes waves and must used with

03CF: load_wav  1828 as  1
00D6: if  
03D0:   wav  1 loaded
004D: jump_if_false @
03D1: play_wav 1
can be attached to actor or object
0949: link_wav 1 to_actor 0@
if wave is finish should be unloaded
040D: unload_wav 1

in original is usual to unload wav before loading a wav
:AUDIOL_33
00D6: if  
0039:   4@ ==  0  // integer values
004D: jump_if_false @AUDIOL_38
040D: unload_wav 3@
03CF: load_wav 7@ as 3@

you can also check if the sound is finish
00D6: if 
03D2:   wav 1 ended
004D: jump_if_false @

The sounds which are used with 03CF: load_wav 1828 as 1
are mostly dialog sounds of missions
The names of these waves, listed in AudioEvents.txt are the entry names from gxt dialog texts
exemble:
SOUND_MAN5_BK 24412
search in american.gxt for MAN5_BK
and find the dialog text:
~z~You got ice cold gangstas running through your veins!

The sound numbers have NO association with Audio file numbers, folder, banks
Only way I know to find sounds is to write a sound test script



///autom. phrases///////
Other way to let actor speak which is not written in AudioEvents.txt is
09D5: play_sound_of_actor $PLAYER_ACTOR soundslot 342 flags 1  1  1 as 2@
first param, $PLAYER_ACTOR is the actor variable name
second param (342) is a slot with some different phrases sounds
third, fourth, fift param of flags are unknown
last param, 2@ is variable name of this sound function, isnt need to release or deload it in any way
and cant used further more in any other opcode.

Note: the soundslots includes more sounds which are changed automaticly if the same soundslot runs again
The soundslot with same number includes different sounds for different actors

PLAYER_ACTOR, special actors, Females and males have different sounds
only with the special girlfriends actors (GANGRL2) is it possible to play the sex voices of GFSEX script
The shop sellers have own sounds and can not played with other actors

opcode 09D5 is the only way to play these voice sounds which are also mostly used from exe for random peds on street
like pain sounds, breathing, coughing ect...
presumable uses PAIN_A SFX, SPC_FA SFX, SPC_PA SFX Archive Directory,

look at GTA: SA SFX Directory


______________________________________________________________________________________
______________________________________________________________________________________
  • In45do likes this

PatrickW
  • PatrickW

    GTA Juggernaut

  • Inactive Staff
  • Joined: 07 Jan 2004
  • Netherlands
  • Best Script 2013 [DYOM]
    Best Script 2012 [DYOM]

#5

Posted 23 March 2009 - 08:14 PM

Good work, ZAZ. icon14.gif


ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#6

Posted 29 March 2009 - 03:00 PM Edited by ZAZ, 25 April 2011 - 10:02 PM.

QUOTE (PatrickW @ Mar 23 2009, 20:14)
Good work, ZAZ.  icon14.gif

Thx master


Math coding
- Give access with math coding
- Access check with local variables
- Declare or not declare (first reason)
- Time check for milliseconds in real time
- Time check for game hours

- Integer values and floating points
- Declare or not declare (second reason)
- Integer to float and reversed
- Show the calculated values with text_draw opcode

- Math coding for calculations


______________________________________________________________________________________
______________________________________________________________________________________


Give access with math coding

Math coding is not only for calculating.
A very imortant aspect to use math coding is to give access to script parts

Therfore we declare a variable with an value
CODE
//example:
$RYDER_TOTAL_PASSED_MISSIONS = 0
0@ = 0

As following we can check if this variable is equal to this value
If yes the reading process can pass the check

The 2 most famouse check for access are in the misson starter scripts of original main.scm and the check if onmission is zero

$ONMISSION is declared in the main part of the original main.scm as special mission mode controler
CODE
0180: set_on_mission_flag_to $ONMISSION


the first change of onmission by new game start is in Intro mission at Airport
CODE
:INTRO_47
$ONMISSION = 1


The scriptpart below is a ripped version of the RYDER mission starter script
it checks if $ONMISSION == 0 and if $RYDER_TOTAL_PASSED_MISSIONS == 0
if the check is passed, it gives access to the mission start
but first it changes $ONMISSION into 1 to prevent access to more mission starts from the starter script

the value of $RYDER_TOTAL_PASSED_MISSIONS changes in the Ryder mission in case of mission complete

Attension by using Global vars in cleo scripts, it can cause bugs or crashes. Only $PLAYER_CHAR, $PLAYER_ACTOR, $ONMISSION are valid

CODE
:RYDER_11
wait 0
if
  Player.Defined($PLAYER_CHAR)
else_jump @RYDER_342
if
 $ONMISSION == 0
else_jump @RYDER_342
if
00FF:   actor $PLAYER_ACTOR sphere 0 in_sphere $X_RYDER_HOUSE $Y_RYDER_HOUSE $Z_RYDER_HOUSE radius 1.6 1.2 2.0 on_foot
else_jump @RYDER_342  
if
 $RYDER_TOTAL_PASSED_MISSIONS == 0
else_jump @RYDER_238
$ONMISSION = 1  
start_mission 24  // Home Invasion
jump @RYDER_238


:RYDER_238
if
 $RYDER_TOTAL_PASSED_MISSIONS == 1
else_jump @RYDER_290
$ONMISSION = 1
start_mission 25  // Catalyst

:RYDER_290
if
 $RYDER_TOTAL_PASSED_MISSIONS == 2
else_jump @RYDER_342
$ONMISSION = 1
start_mission 26  // Robbing Uncle Sam

:RYDER_342
jump @RYDER_11


the value of $RYDER_TOTAL_PASSED_MISSIONS changes in the Ryder mission in case of mission complete
there will be added a value
CODE
$RYDER_TOTAL_PASSED_MISSIONS += 1



the mission passed variable then is equal to 1
$RYDER_TOTAL_PASSED_MISSIONS = 1

the check for $RYDER_TOTAL_PASSED_MISSIONS == 1 gives then access to start the next mission
CODE
if
 $RYDER_TOTAL_PASSED_MISSIONS == 1
else_jump @RYDER_290
$ONMISSION = 1
start_mission 25  // Catalyst




Access check with local variables

Use one equals sign to give a variable a value
CODE
1@ = 0

Use 2 equals sign to check if this variable is equal to a specified value
CODE
1@ ==  0

The script below removes the access to the Johnsons House and gives it free if the actor 5@ is killed
The checks for the value of the variable 1@ subdivide the script in 3 steps
So we need only one Loop to manage more seguences
(and a model load check loop which doesnt belongs to the script steps)

In first step the script checks if the player is in interior 0; this means in the outside map
to prevent that the player will be locked in Johnsons House
077E: get_active_interior_to 29@ declares the variable 29@ and its value
If player is outside, the access to the house will be removed and the value for the access check will be changed
1@ = 1

Now the script gives access to second step which checks if the player is going into red marker to start the action
if
0039: 1@ == 1
if
00FF: actor $PLAYER_ACTOR 1 (in-sphere)near_point_on_foot 2491.5 -1667.5 13.35 radius 1.0 1.0 1.0


If both conditions are accomplished the actor 5@ will be spawned to give the player a fight
and the value for the access check will be changed again to gives access to third step which checks if the actor 5@ is dead

If actor 5@ is dead enables the interior access to the Johnsons House and the script ends

If player doesnt fight and goes away brings back the second step
therefore the check if distance of actor 5@ to the player is greater than 80.0
actor 5@ then will be released from our script and 1@ get the value 1



CODE
{$CLEO .cs}
:Access_1
03A4: name_thread 'Access_'
1@ = 0

:Access_2
0001: wait  0 ms
00D6: if  0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Access_2

if//-- first access check
0039:   1@ ==  0
004D: jump_if_false @Access_3//------ jumps to next access check
077E: get_active_interior_to 29@
if
0039:   29@ ==  0
004D: jump_if_false @Access_2
07FB: set_interior 'CARLS' access 0
1@ = 1//--- gives access for second access check

:Access_3//-- second access check
if
0039:   1@ ==  1
004D: jump_if_false @Access_7//------ jumps to next access check
if
00FF:   actor $PLAYER_ACTOR  1 (in-sphere)near_point_on_foot 2491.5  -1667.5  13.35 radius  1.0  1.0  1.0
004D: jump_if_false @Access_2
0247: request_model #TRIBOSS
0247: request_model #AK47

:Access_4//-- load model check loop
0001: wait  0 ms
00D6: if  and
0248:   model #TRIBOSS available
0248:   model #AK47 available
004D: jump_if_false @Access_4//-- load model check loop
009A: 5@ = create_actor  24 #TRIBOSS at  2486.5  -1664.5  13.45
01B2: give_actor 5@ weapon  30 ammo  99999
05E2: AS_actor 5@ kill_actor $PLAYER_ACTOR
0249: release_model #TRIBOSS
1@ = 2//--- gives access for third access check

:Access_7//-- third access check
if
0039:   1@ ==  2
004D: jump_if_false @Access_2//------ jumps back to loop adress
00D6: if  0
0118:   actor 5@ dead
004D: jump_if_false @Access_9
01C2: remove_references_to_actor 5@
07FB: set_interior 'CARLS' access 1
0A93: end_custom_thread

:Access_9
00D6: if  0
8104:   NOT actor $PLAYER_ACTOR near_actor 5@ radius  80.0  80.0  10.0 sphere  0
004D: jump_if_false @Access_2
009B: destroy_actor 5@
1@ = 1//--- gives access for second access check
0002: jump @Access_2




______________________________________________________________________________________
______________________________________________________________________________________


Declare or not declare (first reason)

It doesnt need allways to declare the variables value
Without declaration the variabels are set to ciro by default

It refers to the situation and its purpose
I recommand to declare the variable if it is used for an access check
It makes the script more stable because it prevends bugs which can happen by crossover calculation of more threads if they are running at same time

An argument to declare it not is to select a step by script start.
An exemple script for this case is "Store a car at any place"

Read the theme: Special Particularities in Cleo
- Script Exemble by using Special Global Cleo Variable/ Store a car at any place

this script beginns with:
CODE
{$CLEO .cs}
:CARSTORE
03A4: name_thread 'CARSTOR'
0001: wait 1000 ms
0AB4: 7@ = var 955
00D6: if
8039:   not  7@ == 0
004D: jump_if_false @CARSTOR_150


If the Carstore script is running from new by loading a save game or start new game ...

..it checks first if var 955 is ciro
its only not ciro if a car was stored in the loaded savegame

If var 955 is ciro, the script starts with the 1.Loop
If var 955 is not ciro, the reading process jumps into the 3.Loop with the check if player is near the car store location


One more exemple is the check if a script was started from Cleo programm
or from an other thread by using create_custom_thread
0A92: create_custom_thread "ThreadStartTest.cs"
Read the description of the theme: Special Particularities in Cleo >> create_custom_thread

The .CS script is started from Cleo programm by default.
To cancel the the initialisation of Cleo programm because it should only be started from an other thread with create_custom_thread
can be done with an access check for a variables value which was not declared.

Without declaration the variabels are set to ciro by default,
especially if it was started from Cleo programm

We can now use the create_custom_thread command to declare a local variable of the other thread
by using create_custom_thread with parameter
0A92: create_custom_thread "ThreadStartTest.cs" 1
The started thread recieves these parameter value with following rule
0@ get value of 1.parameter

The script below must be saved as ThreadStartTest.txt and compiled as ThreadStartTest.cs
because of the entry of the create_thread command
CODE
0A92: create_custom_thread "ThreadStartTest.cs" 1

If it was started from Cleo programm the variabel 0@ is set to ciro by default
and reads as next the end_custom_thread to cancel the thread execution

If it was started from an other thread with the create_thread command of above
the variable 0@ gets the value 1
in this case the access check leads the reading process into the Loop to can enable the thermal_vision

CODE
{$CLEO .cs}
:ThreadStartTest
if
0039:   0@ ==  0
004D: jump_if_false @ThreadStartTest_1
0A93: end_custom_thread

:ThreadStartTest_1
03A4: name_thread "THREADST"

:ThreadStartTest_2
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @ThreadStartTest_2
if
0AB0:   key_pressed 8//-----------------key = Backspace
004D: jump_if_false @ThreadStartTest_2
08B2: toggle_thermal_vision 1
0001: wait 3000 ms
08B2: toggle_thermal_vision 0
0002: jump @ThreadStartTest_2



This variation of access check and using create_custom_thread with parameter
allows to place more than one threads into a .CS file and let them all running at same time
The create_custom_thread command with parameter can be placed in the same script file which includes the thread to start


______________________________________________________________________________________
______________________________________________________________________________________


Time check for milliseconds in real time

The local variables 32@ and 33@ are reserved for using in time checks
Its values are permanently counting ascending in milliseconds
They are allways integer values
We can restore the counting by setting the variable to ciro
CODE
33@ = 0

After this its permanently counting again ascending from the specified value
Then it is possible to check if a specified time is passed
CODE
if
33@ > 5000


The script below checks permanently if 5 seconds are passed
If yes will show a text message and restore the counter
CODE
{$CLEO .cs}
:Timecheck_1
thread "TIME"
33@ = 0

:Timecheck_2
wait 0 ms
if
33@ > 5000
jf @Timecheck_2
00BA: text_styled 'FEM_OK'  1000 ms  1
33@ = 0
jump @Timecheck_2

Important:
To set the game speed slow makes the real time slow in same relation


______________________________________________________________________________________
______________________________________________________________________________________


Time check for game hours
The opcode 00BF: gives the values of hours and minutes of the game time
CODE
00BF: 0@ = current_time_hours, 1@ = current_time_minutes

Using math symbols like "if greater than" > or "if greater than or equal" >=
let check a duration of the game time

The script below enables the thermal_vision in the night between 22 o`clock and 2 o`clock
The variable 3@ prevent that the opcode 08B2: will be read permanently
The time check gets the duration which should view the thermal_vision
It doesnt matter if you arrived at midnight after loading a savegame
or if you are present before the view change and can experience the change
CODE
{$CLEO .cs}
:GameTime_1
thread "GTIME"
3@ = 0

:GameTime_2
wait 0
00BF: 0@ = current_time_hours, 1@ = current_time_minutes
if or
 0@ >= 22
 2 > 0@
jf @GameTime_3  
if
 3@ == 0
jf @GameTime_3
08B2: enable_thermal_vision 1
3@ = 1

:GameTime_3
if and
 0@ > 1
 22 > 0@
 3@ == 1
jf @GameTime_2
08B2: enable_thermal_vision 0
3@ = 0
jump @GameTime_2



______________________________________________________________________________________
______________________________________________________________________________________


Integer values and floating points

The explanation above includes only the using of Integer values
For sevarel cases must be used floating points e.g. coords checks or calculation of coords values

The script below puts the player into the sky in a height of 500.0 virtual meters
The player falls down and will put again into the sky if the distance to the ground is to near
At first a check for the interior to make shure that the player is in the outside map
The script reads pemanently the distance of the player_actor to the ground if he is outside
The opcode to check if a specified floating point value is greater than the floating point value of the variable
gives access to read the put_actor code
if
0023: 25.0 > 3@


CODE
{$CLEO .cs}
:Floatcheck_1
03A4: name_thread "FLOAT"

:Floatcheck_2
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Floatcheck_2
077E: get_active_interior_to 29@
if
0039:   29@ ==  0
004D: jump_if_false @Floatcheck_2
0819: 3@ = actor $PLAYER_ACTOR distance_from_ground
if
0023:   25.0 > 3@
004D: jump_if_false @Floatcheck_2
00A1: put_actor $PLAYER_ACTOR at 0.0 0.0 500.0
0002: jump @Floatcheck_2



______________________________________________________________________________________
______________________________________________________________________________________


Declare or not declare (second reason)

The game engine can not handle with intger values when floating points are required and reversed
In addition exist for math coding function different opcodes each if they are used with integer or with floats

Well, Sanny is intelligent and know when a fuction should use floats or integer and do the work for us by compiling
Compile the script of above and then decompile the created .cs file with the option "without opcodes"
and you will get this:
CODE
{$CLEO .cs}

//-------------MAIN---------------
thread "FLOAT"

:FLOAT_9
wait 0
if
  Player.Defined($PLAYER_CHAR)
jf @FLOAT_9
077E: get_active_interior_to 29@
if
 29@ == 0
jf @FLOAT_9
0819: 3@ = actor $PLAYER_ACTOR distance_from_ground
if
 25.0 > 3@
jf @FLOAT_9
Actor.PutAt($PLAYER_ACTOR, 0.0, 0.0, 500.0)
jump @FLOAT_9


The most opcodes are disappeared
Sanny knows that floats are meant in this function:
25.0 > 3@

But by sevaral fuctions is it unknown
for exemple to calculate 2 variables:
CODE
21@ -= 2@


Writing this function with the opcode is one solution to clarify if floats are meant or integer
CODE
0063: 21@ -= 2@ // (float)


An other solution is to declare if the variable is a float or an integer
Just set the variable equal to a value at script beginn,
either as integer
CODE
21@ = 0
2@ = 0

or as float
CODE
21@ = 0.0
2@ = 0.0


Read more about that theme in Sannybuilder HELP: Coding >> Variables
and in Sannybuilder HELP: Coding >> Constants


______________________________________________________________________________________
______________________________________________________________________________________



Integer to float and reversed

The opcodes 0092: changes a floating point into a integer value
CODE
0092: 3@ = float 2@ to_integer

2@ must be a float
3@ gives than the integer
The value behind comma disappear

The opcodes 0093: changes an integer value into a floating point
CODE
0093: 9@ = integer 8@ to_float

8@ must be an integer
9@ gives than the float
The value behind comma will than be .0


______________________________________________________________________________________
______________________________________________________________________________________


Show the calculated values with text_draw opcode
this can help to find failures or to prove running scripts
CODE
03F0: enable_text_draw 1
045A: text_draw_1number  250.0  40.0 'NUMBER' 3@


opcode 045A: can display the value of the inserted variable
but it can only display an integer value
to display floats need to invert the float first into an integer with opcode 0092:

opcode 045A: needs to be read permanently in a loop connected with opcode 03F0: which must be read before
opcode 045A: is a function of the categorie text_draw like the opcodes to display textures of GTASA\models\txd

To set opcode 03F0: to 1 as first and than the text_draw opcode in a permanent readed loop
is the mostly done variation to use the text_draw opcodes e.g. in the race tournament to show the time and the rank
It is also used to display Cleo speedometers

Text_draw opcodes have a disadvantage:
They disturb Text massages of some other kinds of text opcodes
Or invers, they will not be shown if a text is shown of some other kinds of text opcodes

To display a value with 045A: without permanent reading in a loop can be used a trick:
CODE
03F0: text_draw_toggle  1
0001: wait  50 ms
03F0: text_draw_toggle  0
0001: wait  50 ms
045A: text_draw_1number  250.0  40.0 'NUMBER' 3@

This shows the value till 03F0: will be read from anywhere


The script below is a mix of two scripts from above: Timecheck and Floatcheck
It displays the values of the real time counter 33@ (upper value)
the interior number (middle value)
the distance_from_ground (lower value)

If you arrive in a savehouse interior after gameload the distance_from_ground is not shown
but you can see the interior number
If you go outside the player will be put into the sky and you can see the distance_from_ground
The real time counter will be restored after 50 seconds which let show then the text message OK
The text message of opcode 00BA: disturbs then the text_draw displaying
CODE
{$CLEO .cs}
:ValueCheck_1
03A4: name_thread "VCHECK"
33@ = 0

:ValueCheck_2
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @ValueCheck_2
077E: get_active_interior_to 29@
03F0: enable_text_draw 1
045A: text_draw_1number  250.0  40.0 'NUMBER' 33@
045A: text_draw_1number  250.0  50.0 'NUMBER' 29@
if
0039:   29@ ==  0
004D: jump_if_false @ValueCheck_3
0819: 3@ = actor $PLAYER_ACTOR distance_from_ground
0092: 4@ = float 3@ to_integer
03F0: enable_text_draw 1
045A: text_draw_1number  250.0  60.0 'NUMBER' 4@
if
0023:   25.0 > 3@
004D: jump_if_false @ValueCheck_3
00A1: put_actor $PLAYER_ACTOR at 0.0 0.0 500.0

:ValueCheck_3
if
33@ > 50000
jf @ValueCheck_2
00BA: text_styled 'FEM_OK'  1000 ms  1
33@ = 0
jump @ValueCheck_2



______________________________________________________________________________________
______________________________________________________________________________________



Math coding for calculations

It allows to use the basic functions with integer and also with floats

add: +=
substract: -=
divide: /=
multiplicate: *=
is equal: =

To calculate a point in a circle by inserted angle can be used sine or cosine function
Only floats are allowed
02F7: 13@ = sine 45.0 // (float)
02F6: 14@ = cosine 45.0 // (float)
This function refers to a circle with radius 1.0 at game center

In conditional checks can be used
if greater than: >
if greater than or equal: >=
if is equal: ==

Additional commands can be found in Sannybuilder Help: Coding >> Additional commands

The script below applies smoke around the player by key_press
Keeping Backspaces key pressed creates smoke permanently in a circle
4@ is used as angle degrees and by calculating with cosine it gives the X-coord
by calculating with sine it gives the Y-coord
Then multiplicate it with 4.0 and we get XY coords which refers to a circle with radius 4.0 at game center
putting these values as offset into 04C4: represents than the coords around the player axis
At last we add 5.0 degrees to the angle for the next point to create smoke
CODE
{$CLEO .cs}
:Sine_1
03A4: name_thread 'SINE'
0007: 4@ = 0.0  // floating-point values

:Sine_2
0001: wait 0 ms
00D6: if  0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Sine_2
if
0AB0:   key_pressed 8//------Backspace  
004D: jump_if_false @Sine_2
02F6: 5@ = cosine 4@  // sinus swapped with cosine
0013: 5@ *= 4.0  // floating-point values (never used in VC or GTA 3)
02F7: 6@ = sinus 4@ // cosine swapped with sinus
0013: 6@ *= 4.0  // floating-point values (never used in VC or GTA 3)
04C4: create_coordinate 1@ 2@ 3@ from_actor $PLAYER_ACTOR offset 5@ 6@ 0.2
095C: create_smoke_at 1@ 2@ 3@ velocity 0.0 0.0 0.0 RGBA 1.0  1.0  1.0 1.0 size 0.2 last_factor 0.1
000B: 4@ += 5.0
if
0021:   4@ >  354.0  // floating-point values  
004D: jump_if_false @Sine_2
0007: 4@ = 0.0
jump @Sine_2





The last script shows the current coords of the player position
inklusiv the values behind the comma but a dot in the middle is not shown
You have to imagine it
CODE
{$CLEO .cs}
:coords_00
03A4: name_thread 'COO'
0006: 33@ =  0  // integer values
0006: 3@ =  0  // integer values
0006: 4@ =  0  // integer values
0006: 5@ =  0  // integer values
0006: 11@ =  0  // integer values
0006: 12@ =  0  // integer values
0006: 13@ =  0  // integer values
0006: 9@ =  0  // integer values

:coords_01
0001: wait  0 ms
00D6: if  0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @coords_01
03F0: enable_text_draw 1
045A: text_draw_1number  50.0  425.0 'NUMBER' 3@    // value
045A: text_draw_1number  200.0  425.0 'NUMBER' 4@    // value
045A: text_draw_1number  350.0  425.0 'NUMBER' 5@    // value
045A: text_draw_1number  100.0  425.0 'NUMBER' 11@    // value
045A: text_draw_1number  250.0  425.0 'NUMBER' 12@    // value
045A: text_draw_1number  400.0  425.0 'NUMBER' 13@    // value
045A: text_draw_1number  450.0  425.0 'NUMBER' 9@    // value
if
0019:   33@ >  1000  // integer values
004D: jump_if_false @coords_01
0006: 33@ =  0  // integer values
00A0: store actor $PLAYER_ACTOR position to 0@ 1@ 2@
0092: 3@ = float_to_integer 0@  
0092: 4@ = float_to_integer 1@  
0092: 5@ = float_to_integer 2@  

0093: 6@ = integer_to_float 3@  
0093: 7@ = integer_to_float 4@  
0093: 8@ = integer_to_float 5@  

0063: 0@ -= 6@  // floating-point values
0063: 1@ -= 7@  // floating-point values
0063: 2@ -= 8@  // floating-point values
0013: 0@ *=  100.0  // floating-point values
0013: 1@ *=  100.0  // floating-point values
0013: 2@ *=  100.0  // floating-point values

0092: 11@ = float_to_integer 0@  
0092: 12@ = float_to_integer 1@  
0092: 13@ = float_to_integer 2@

:coords_02
00D6: if  0
001B:    0 > 11@  // integer values
004D: jump_if_false @coords_03
0012: 11@ *= -1  // integer values

:coords_03
00D6: if  0
001B:    0 > 12@  // integer values
004D: jump_if_false @coords_04
0012: 12@ *= -1  // integer values

:coords_04
00D6: if  0
001B:    0 > 13@  // integer values
004D: jump_if_false @coords_05
0012: 13@ *= -1  // integer values

:coords_05
0172: 9@ = actor $PLAYER_ACTOR z_angle
0092: 9@ = float_to_integer 9@
0002: jump @coords_01


______________________________________________________________________________________
______________________________________________________________________________________


/!\ErManu/!\
  • /!\ErManu/!\

    /!\Custom Cars/!\

  • Members
  • Joined: 25 Jun 2008

#7

Posted 30 March 2009 - 03:40 PM

Thank you for using your time in this tutorial icon14.gif cookie.gif cookie.gif cookie.gif

This is very useful for all!

Thanks and bye!!good work icon14.gif

Rafinha
  • Rafinha

    But I just don't give a f*ck...

  • BUSTED!
  • Joined: 08 Feb 2009

#8

Posted 09 May 2009 - 02:20 PM

OMG, ZAZ, you waste your time for us!
Thanks for this!

AB033
  • AB033

    Hustler

  • Members
  • Joined: 14 May 2009

#9

Posted 14 May 2009 - 08:46 AM Edited by AB033, 14 May 2009 - 08:51 AM.

Yeah, ZAZ, thank you!

But, I'm looking at this text 2 months and I just don't get it!
Can you pleeeeeeeeease put here, on forum, a video tutorial about making an own mission. That mission doesn't has to be big or something, I just wanna see how! Everybody is talking and putting tutorial text but nobody puts a video tutorial. I said, I'm learning 2 months and I just just just just can't f***ing understand it! Plleease, ZAZ!
I hope this ain't too much. If you can please do this but if you can't, no problem, you don't have to, I understand.

You're my only hope.

noelgamo
  • noelgamo

    LOL

  • Members
  • Joined: 30 Jan 2009

#10

Posted 15 May 2009 - 07:55 AM

Great tut.... cookie.gif cookie.gif cookie.gif

uhm how to make savepoints? cause I dont think I seen one from the tut. but if there is can you tell me wich bit is it.sorry for being a noob. smile.gif smile.gif

spaceeinstein
  • spaceeinstein

    巧克力

  • Members
  • Joined: 17 Jul 2003
  • None

#11

Posted 16 May 2009 - 09:17 PM

Wow, this is impressive.

coin-god
  • coin-god

    High Roller

  • $outh $ide Hoodz
  • Joined: 18 Mar 2007

#12

Posted 16 May 2009 - 10:07 PM

Amazing work ZAZ. icon14.gif

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#13

Posted 17 May 2009 - 07:07 PM Edited by ZAZ, 05 April 2013 - 12:46 PM.

Ups, visitors. Thx friends.
QUOTE (noelgamo @ May 15 2009, 07:55)

uhm how to make savepoints? cause I dont think I seen one from the tut. but if there is can you tell me wich bit is it.sorry for being a noob. smile.gif   smile.gif

Right, I forgot it.
Here it is:

The savescript with savedisk_pickup needs to insert 2 or 3 coords points.
One for the savedisk_pickup
One to put Playerchar beside the pickup
One for the radar marker, same as pickup but If the savedisk is in an interior the location of the radar marker can be very different to pickup

Script below adds a save radar icon and a savedisk with save fuction at Ottos Autos in San Fierro
Edit the coords as descripted in the comments

CODE
{$CLEO .cs}
thread 'SAVE'
wait 1000
0A95: enable_thread_saving  
// 1@, 2@, 3@ = x,y,z coords for pickup
0007: 1@ = -1668.6
0007: 2@ = 1207.2
0007: 3@ = 7.25
// 11@, 12@, 13@ = x,y,z coords and 14@ = z_angle for put_actor $PLAYER_ACTOR at
0007: 11@ = -1666.4
0007: 12@ = 1209.2
0007: 13@ = 7.25
0007: 14@ = 315.9
0213: 0@ = create_pickup 1277 type 3 at 1@ 2@ 3@
0570: 5@ = create_asset_radar_marker_with_icon 35 at 1@ 2@ 3@
018B: show_on_radar 5@ 2
//00BC: show_text_highpriority GXT 'fem_on' time 3000 flag 1

while true
wait 0
   if
      Player.Defined($PLAYER_CHAR)
   then
       if
           0214:   pickup 0@ picked_up
       then
           if
               0038:   $ONMISSION == 0
           then
               03D8: show_save_screen
           end
           wait 0
           00A1: put_actor $PLAYER_ACTOR at 11@ 12@ 13@
           0173: set_actor $PLAYER_ACTOR Z_angle_to 14@
           01B4: set_player $PLAYER_CHAR can_move 1
           wait 1000
           0213: 0@ = create_pickup 1277 type 3 at 1@ 2@ 3@
           090D: highlight_all_inactive_gang_zones_as_available_for_gangwars
           //00BC: show_text_highpriority GXT 'fem_ok' time 1000 flag 1
           
       end                                                                                                  
   end
end


noelgamo
  • noelgamo

    LOL

  • Members
  • Joined: 30 Jan 2009

#14

Posted 17 May 2009 - 08:27 PM

Thanks it helps me saving in my new safehouse
Great tutorial cookie.gif cookie.gif cookie.gif cookie.gif

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#15

Posted 05 June 2009 - 02:13 PM Edited by ZAZ, 04 September 2010 - 01:09 PM.

Arrays

Generally the prinzip of arrays is really simple but the lot of context script arround the arrays makes confuse.
Furthermore the array construction seems complicate.

Basicly we can assign more content to the same variable
The variable then is like a family with childs
and the Index of the Family defines which part of the family is meant

Family[index 0] = father
Family[index 1] = mother
Family[index 2] = son
Family[index 3] = doughter
Family[index 4] = Carl


Family[index 1] goes in the kitchen
means:
mother goes in the kitchen

Lets go to GTA and local variables
We can use the same variable in the array construct
but we must reserve more local variables

6@[index 0] = father
6@[index 1] = mother
6@[index 2] = son
6@[index 3] = doughter
6@[index 4] = Carl


the assignment of ascending index values uses new locals in ascending order

6@ = father
7@ = mother
8@ = son
9@ = doughter
10@ = Carl


the most important entry in the array construct is the INDEX

the array construct:
6@(30@,5i)

30@ is the array index

we define the value of the index:
0006: 30@ = 4

now
6@(30@,5i) goes in the kitchen
means
Carl goes in the kitchen
its the same like:
10@ goes in the kitchen


Some script examples for the praxis:
The following 4 scripts spawns allways the same 5 item-pickups in the Grovestreet

modelID, name
1239, info
1240, health
1241, adrenaline
1242, bodyarmour
1247, bribe

each script in an other variation
step by step from simple pickup spawn till a script with an array-loop

1. the simple pickup spawn in the Grovestreet
CODE
{$CLEO .cs}
:more_items1
03A4: name_thread 'm_item1'

//1239, info
//1240, health
//1241, adrenaline
//1242, bodyarmour
//1247, bribe

0213: 0@ = create_pickup 1239 type 15 at 2490.0 -1662.0 13.5
0213: 1@ = create_pickup 1240 type 15 at 2492.0 -1662.0 13.5
0213: 2@ = create_pickup 1241 type 15 at 2494.0 -1662.0 13.5
0213: 3@ = create_pickup 1242 type 15 at 2496.0 -1662.0 13.5
0213: 4@ = create_pickup 1247 type 15 at 2498.0 -1662.0 13.5

0A93: end_custom_thread


2. now we use local variables to define the modelID
CODE
{$CLEO .cs}
:more_items2
03A4: name_thread 'm_item2'

0006: 6@ = 1239  // info        
0006: 7@ = 1240  // health      
0006: 8@ = 1241  // adrenaline  
0006: 9@ = 1242  // bodyarmour  
0006: 10@ = 1247  //bribe

0213: 0@ = create_pickup 6@ type 15 at 2490.0 -1662.0 13.5
0213: 1@ = create_pickup 7@ type 15 at 2492.0 -1662.0 13.5
0213: 2@ = create_pickup 8@ type 15 at 2494.0 -1662.0 13.5
0213: 3@ = create_pickup 9@ type 15 at 2496.0 -1662.0 13.5
0213: 4@ = create_pickup 10@ type 15 at 2498.0 -1662.0 13.5

0A93: end_custom_thread


3. now we use an array construct to define the modelID
30@ is the array index
after each pickup spawn we add 1 to the array index
000A: 30@ += 1
CODE
{$CLEO .cs}
:Array_items1
03A4: name_thread 'Array_1'

0006: 6@ = 1239  // info        
0006: 7@ = 1240  // health      
0006: 8@ = 1241  // adrenaline  
0006: 9@ = 1242  // bodyarmour  
0006: 10@ = 1247  //bribe

0006: 30@ = 0  // ---Array Index is 0
0213: 0@ = create_pickup 6@(30@,5i) type 15 at 2490.0 -1662.0 13.5

000A: 30@ += 1// ---Array Index is 1
0213: 1@ = create_pickup 6@(30@,5i) type 15 at 2492.0 -1662.0 13.5

000A: 30@ += 1// ---Array Index is 2
0213: 2@ = create_pickup 6@(30@,5i) type 15 at 2494.0 -1662.0 13.5

000A: 30@ += 1// ---Array Index is 3
0213: 3@ = create_pickup 6@(30@,5i) type 15 at 2496.0 -1662.0 13.5

000A: 30@ += 1// ---Array Index is 4
0213: 4@ = create_pickup 6@(30@,5i) type 15 at 2498.0 -1662.0 13.5

0A93: end_custom_thread


4. the array-loop contains only one line which creates 5 different pickups
the loop will be read 5 times
it adds allways 1 to the array index before the reading process jumps back to the loop adress
to read the pickup spawn again with a changed index value
We must protect that the loop will be read more than 5 times and add a check if the index is smaller than 5:
if
001B: 5 > 30@

furthermore we can not spawn the 5 different pickups at the same coords
we need to change minimum the x-coords and use an array construct in that parameter
so we must first define variables with coords.
CODE
{$CLEO .cs}
:Array_items2
03A4: name_thread 'Array_2'

0006: 6@ = 1239  // info        
0006: 7@ = 1240  // health      
0006: 8@ = 1241  // adrenaline  
0006: 9@ = 1242  // bodyarmour  
0006: 10@ = 1247  //bribe      

0007: 11@ = 2490.0
0007: 12@ = 2492.0
0007: 13@ = 2494.0
0007: 14@ = 2496.0
0007: 15@ = 2498.0

0006: 30@ = 0  // ---Array Index


:Array_items2_loop
0001: wait  0 ms
if
001B:   5 > 30@
004D: jump_if_false @Array_items2_end
0213: 0@(30@,5i) = create_pickup 6@(30@,5i) type 15 at 11@(30@,5f) -1662.0 13.5
000A: 30@ += 1
0002: jump @Array_items2_loop

:Array_items2_end
0A93: end_custom_thread


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

At last the complete array description:
6@(30@,5i)
<family variable>(<index varable>,<max amount of array definitions><kind of content: i means integer, f means floats, s means string>)

max amount of array definitions means the max amount of the example above is 5
so we can create only 5 items with arrays
if we use 6@(30@,2i)we can create only 2 items with arrays
but we can write 6@(30@,12i) to create only 5 items with arrays
and if we want to create 20 items we need to increase the max amount: 6@(30@,20i)
but its not possible to create 20 items in an array loop in a Cleo-CS file
because we need 20 locals for the item definitions and 20 locals for the different coords
and a normal thread like the cs file supports only 32 locals

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

Another way to write arrays looks a bit more clear,
only arrayname and the index in square brackets: 0@[30@]
requires to define the array at the beginnig:

var
0@: array 5 of Integer
end

script below without opcodes, this array construct will be changed after recompiling into the syntax from above
CODE
{$CLEO .cs}
thread 'ARRAY_2'

var
0@: array 5 of Integer
6@: array 5 of Integer
11@: array 5 of Float
end

6@ = 1239
7@ = 1240
8@ = 1241
9@ = 1242
10@ = 1247
11@ = 2490.0
12@ = 2492.0
13@ = 2494.0
14@ = 2496.0
15@ = 2498.0
30@ = 0

:ARRAY_1
wait 0
if
 5 > 30@
jf @ARRAY_3
0@[30@] = Pickup.Create(6@[30@], 15, 11@[30@], -1662.0, 13.5)
30@ += 1
jump @ARRAY_1

:ARRAY_3
0A93: end_custom_thread


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

The next script below shows how to use the array defined items forthermore in the script
either with using the simple local variable which is equal to a child of the family variable:
if
0214: pickup 2@ picked_up

or with using the array construct and set the index to a value:
0006: 30@ = 1 // ---Array Index
0164: disable_marker 16@(30@,5i)

or to restore the index and assigne markers to the pickups in an array loop:
:Array_items3_restore
0006: 30@ = 0 // ---Array Index restore

:Array_items3_marker
0001: wait 0 ms
if
001B: 5 > 30@
004D: jump_if_false @Array_items3_check1
03DC: 16@(30@,5i) = create_marker_above_pickup 0@(30@,5i)
000A: 30@ += 1
0002: jump @Array_items3_marker
CODE
{$CLEO .cs}
:Array_items3
03A4: name_thread 'Array_3'

0006: 6@ = 1239  // info        
0006: 7@ = 1240  // health      
0006: 8@ = 1241  // adrenaline  
0006: 9@ = 1242  // bodyarmour  
0006: 10@ = 1247  //bribe      

0007: 11@ = 2490.0
0007: 12@ = 2492.0
0007: 13@ = 2494.0
0007: 14@ = 2496.0
0007: 15@ = 2498.0

0006: 30@ = 0  // ---Array Index


:Array_items3_create
0001: wait  0 ms
if
001B:   5 > 30@
004D: jump_if_false @Array_items3_restore
0213: 0@(30@,5i) = create_pickup 6@(30@,5i) type 3 at 11@(30@,5f) -1662.0 13.5
000A: 30@ += 1
0002: jump @Array_items3_create

:Array_items3_restore
0006: 30@ = 0  // ---Array Index restore

:Array_items3_marker
0001: wait  0 ms
if
001B:   5 > 30@
004D: jump_if_false @Array_items3_check1
03DC: 16@(30@,5i) = create_marker_above_pickup 0@(30@,5i)
000A: 30@ += 1
0002: jump @Array_items3_marker

:Array_items3_check1
0001: wait  0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Array_items3_check1
if
0214:   pickup 0@ picked_up
004D: jump_if_false @Array_items3_check2
0006: 30@ = 0  // ---Array Index
0164: disable_marker 16@(30@,5i)

:Array_items3_check2
if
0214:   pickup 1@ picked_up
004D: jump_if_false @Array_items3_check3
0006: 30@ = 1  // ---Array Index
0164: disable_marker 16@(30@,5i)

:Array_items3_check3
if
0214:   pickup 2@ picked_up
004D: jump_if_false @Array_items3_check4
0006: 30@ = 2  // ---Array Index
0164: disable_marker 16@(30@,5i)

:Array_items3_check4
if
0214:   pickup 3@ picked_up
004D: jump_if_false @Array_items3_check5
0006: 30@ = 3  // ---Array Index
0164: disable_marker 16@(30@,5i)

:Array_items3_check5
if
0214:   pickup 4@ picked_up
004D: jump_if_false @Array_items3_check6
0006: 30@ = 4  // ---Array Index
0164: disable_marker 16@(30@,5i)

:Array_items3_check6
if or
075C:   marker 16@ enabled
075C:   marker 17@ enabled
075C:   marker 18@ enabled
075C:   marker 19@ enabled
075C:   marker 20@ enabled
004D: jump_if_false @Array_items3_Endrestore
0002: jump @Array_items3_check1

:Array_items3_Endrestore
0006: 30@ = 0  // ---Array Index
0002: jump @Array_items3_create



The next script below is a more useful script which spawns 10 actors with markers
it deletes the markers of each killed actor and counts the dead actors with an extra local variable
go to the street and press key 9 to activate the spawning
CODE
{$CLEO .cs}
:ArrayAct_1
03A4: name_thread 'ARRAY_A'
0006: 28@ =  0  // counter for dead actors
0006: 30@ =  0  // Array index
0007: 31@ = 2.5  // y offset for spawn coords

:ArrayAct_2
0001: wait  0 ms
00D6: if  0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @ArrayAct_2
if  and
0AB0:   key_pressed 57//----------------key 9
80DF:   not actor $PLAYER_ACTOR driving
004D: jump_if_false @ArrayAct_2
077E: get_active_interior_to 29@
00D6: if  0
0039:   29@ ==  0  // integer values
004D: jump_if_false @ArrayAct_2

0247: request_model #fbi

:ArrayAct_3
0001: wait  0 ms
if   and
0248:   model #fbi available
004D: jump_if_false @ArrayAct_3

:ArrayAct_4
0001: wait  10 ms
00D6: if  0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @ArrayAct_4
if
001B:    10 > 30@  // integer values
004D: jump_if_false @ArrayAct_10
04C4: create_coordinate 24@ 25@ 26@ from_actor $PLAYER_ACTOR offset 0.0  31@  0.2
009A: 0@(30@,12i) = create_actor_pedtype 6 model #fbi at 24@ 25@ 26@
0187: 10@(30@,12i) = create_marker_above_actor 0@(30@,12i)
000B: 31@ +=  2.0  // add 2.0 to the y offset for spawn coords
000A: 30@ +=  1  // Array index
0002: jump @ArrayAct_4


:ArrayAct_10
0006: 30@ =  0  // Array index

:ArrayAct_11
0001: wait  10 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @ArrayAct_40
if
001B:    10 > 30@  // integer values
004D: jump_if_false @ArrayAct_15
if
0118:  actor 0@(30@,12i) dead
004D: jump_if_false @ArrayAct_13
if
075C:   marker 10@(30@,12i) enabled
004D: jump_if_false @ArrayAct_13
0164: disable_marker 10@(30@,12i)
000A: 28@ +=  1  // counter for dead actors

:ArrayAct_13
000A: 30@ +=  1  // Array index
if
001B:    10 > 28@  // integer values
004D: jump_if_false @ArrayAct_40
0002: jump @ArrayAct_11

:ArrayAct_15
0006: 30@ =  0  // Array index
0002: jump @ArrayAct_11

:ArrayAct_40
0006: 30@ =  0  // Array index

:ArrayAct_45
if
001B:    10 > 30@  // integer values
004D: jump_if_false @ArrayAct_50
if
075C:   marker 10@(30@,12i) enabled
004D: jump_if_false @ArrayAct_47
0164: disable_marker 10@(30@,12i)

:ArrayAct_47
01C2: remove_references_to_actor 0@(30@,12i) // Like turning an actor into a random pedestrian
000A: 30@ +=  1  // Array index
0002: jump @ArrayAct_45

:ArrayAct_50
0006: 28@ =  0  // counter for dead actors
0006: 30@ =  0  // Array index
0007: 31@ = 2.5  // y offset for spawn coords
0249: release_model #fbi
0001: wait  1000 ms
0002: jump @ArrayAct_2


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

At the end I show how to use Global Variables as arrays.
But it can only be used in main.scm and will crash in Cleo

Its a bit easier to understand sigh.gif because it looks like the exemble from beginning:

Family[index 0] = father
Family[index 1] = mother
Family[index 2] = son
Family[index 3] = doughter
Family[index 4] = Carl

The global will be like a family
with assignement of an index in brackets

$ACTORS[0] = 0
$ACTORS[1] = 0
$ACTORS[2] = 0
$ACTORS[3] = 0
$ACTORS[4] = 0
$ACTORS[5] = 0

the array construct can look like this:
$ACTORS($ACT_INDEX,30i)
CODE
:Much_Actor_array
03A4: name_thread 'MACTARY'

:LABEL_start
0001: wait 1000 ms
0007: 0@ = -25.0     // Range
0007: 1@ = 25.0      // Range    
0007: 2@ = 5.0       // X
0007: 3@ = 0.0       // Y
0006: 4@ = 0         // PED ID
0006: 5@ = 0         // PED handle
0006: 6@ = 0         // PED creation counter
0006: 7@ = 29        // Max number of PEDs
0004: $ACTORS[0] = 0 // PED handle  
0004: $ACTORS[1] = 0 // PED handle
0004: $ACTORS[2] = 0 // PED handle
0004: $ACTORS[3] = 0 // PED handle
0004: $ACTORS[4] = 0 // PED handle
0004: $ACTORS[5] = 0 // PED handle
0004: $ACTORS[6] = 0 // PED handle
0004: $ACTORS[7] = 0 // PED handle
0004: $ACTORS[8] = 0 // PED handle
0004: $ACTORS[9] = 0 // PED handle
0004: $ACTORS[10] = 0 // PED handle
0004: $ACTORS[11] = 0 // PED handle
0004: $ACTORS[12] = 0 // PED handle
0004: $ACTORS[13] = 0 // PED handle
0004: $ACTORS[14] = 0 // PED handle
0004: $ACTORS[15] = 0 // PED handle
0004: $ACTORS[16] = 0 // PED handle
0004: $ACTORS[17] = 0 // PED handle
0004: $ACTORS[18] = 0 // PED handle
0004: $ACTORS[19] = 0 // PED handle
0004: $ACTORS[20] = 0 // PED handle
0004: $ACTORS[21] = 0 // PED handle
0004: $ACTORS[22] = 0 // PED handle
0004: $ACTORS[23] = 0 // PED handle
0004: $ACTORS[24] = 0 // PED handle
0004: $ACTORS[25] = 0 // PED handle
0004: $ACTORS[26] = 0 // PED handle
0004: $ACTORS[27] = 0 // PED handle
0004: $ACTORS[28] = 0 // PED handle
0004: $ACTORS[29] = 0 // PED handle
0004: $ACT_INDEX = 0

:LABEL_0
0001: wait 0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @LABEL_0
if
80DF:   not actor $PLAYER_ACTOR driving
004D: jump_if_false @LABEL_0
if
001F:   7@ > $ACT_INDEX // (int)
004D: jump_if_false @LABEL_2
0209: 4@ = random_int_in_ranges 209 264
0247: load_model 4@
038B: load_requested_models

:LABEL_1
0001: wait 0 ms
00D6: if 0
0248:   model 4@ available
004D: jump_if_false @LABEL_1
0208: 2@ = random_float_in_ranges 0@ 1@  
0208: 3@ = random_float_in_ranges 0@ 1@
04C4: store_coords_to $TEMPVAR_FLOAT_1 $TEMPVAR_FLOAT_2 $TEMPVAR_FLOAT_3 from_actor $PLAYER_ACTOR with_offset 2@ 3@ -1.0
009A: $ACTORS($ACT_INDEX,30i) = create_actor_pedtype 4 model 4@ at $TEMPVAR_FLOAT_1 $TEMPVAR_FLOAT_2 $TEMPVAR_FLOAT_3
05E2: AS_actor $ACTORS($ACT_INDEX,30i) kill_actor $PLAYER_ACTOR
0008: $ACT_INDEX += 1
0002: jump @LABEL_0

:LABEL_2
0004: $ACT_INDEX = 0

:LABEL_3
0001: wait 0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Cleanup_1
if
001F:   7@ > $ACT_INDEX
004D: jump_if_false @LABEL_5
if
8118:   not actor $ACTORS($ACT_INDEX,30i) dead
004D: jump_if_false @PED_CREATION_CONTROL_COUNT_UP
0332: set_actor $ACTORS($ACT_INDEX,30i) bleeding 1
0245: set_actor $ACTORS($ACT_INDEX,30i) walk_style_to "oldwoman"  
04C4: store_coords_to $TEMPVAR_FLOAT_1 $TEMPVAR_FLOAT_2 $TEMPVAR_FLOAT_3 from_actor $PLAYER_ACTOR with_offset 0.0 0.0 0.0
07CD: AS_actor $ACTORS($ACT_INDEX,30i) walk_to $TEMPVAR_FLOAT_1 $TEMPVAR_FLOAT_2 $TEMPVAR_FLOAT_3 stop_with_angle 0.0 within_radius 1.0

:PED_CREATION_CONTROL_COUNT_UP
0008: $ACT_INDEX += 1
0002: jump @LABEL_3

:LABEL_5
0001: wait 250 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @Cleanup_1
0002: jump @LABEL_5

:Cleanup_1
0004: $ACT_INDEX = 0

:Cleanup_2
0001: wait 0 ms
if
001F:   7@ > $ACT_INDEX
004D: jump_if_false @Cleanup_3
01C2: remove_references_to_actor $ACTORS($ACT_INDEX,30i)
0008: $ACT_INDEX += 1
0002: jump @Cleanup_2

:Cleanup_3
0002: jump @LABEL_start



ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#16

Posted 05 June 2009 - 08:34 PM Edited by ZAZ, 17 August 2012 - 04:34 AM.

read_memory

the cleo opcodes 0A8D: and 0A8C: to read the content of memory adresses
at first we must know which adress have a function
you can find a list at: gtamodding.com
for exemple:
0x863984 - [Int32] Gravity

a simple GRAVITY script with text_draw opcodes to show the content of the adress:
CODE
{$CLEO .cs}
thread 'GRAVITY'
wait 3000
:GRAVITY_1
0A8D: 1@ = read_memory 0x863984   size 4 virtual_protect 1
wait 100
03F0: text_draw_toggle  1
0001: wait  50 ms
03F0: text_draw_toggle  0
0001: wait  50 ms
045A: text_draw_1number  250.0  40.0 'NUMBER' 1@
0A8C: write_memory 0x863984   size 4 value 2 virtual_protect 1 //clear the buffer
0A93: end_custom_thread


at the end we pushes the value 2 into the memory adress
test the script and look for result
2 seems to have the best effect but this adress is really crazy and if we push a float value the effect is different
try
CODE
0A8C: write_memory 0x863984   size 4 value 10.0 virtual_protect 1 //clear the buffer

and you will see the trees deforming


You will need more information about menory handling and should read Seemanns topic:
SA Memory handling
as well as
Documenting GTA-SA memory adresses



CODE
0A8D: $result = read_memory 1@ size 4 virtual_protect 0

0A8D reads the game memory and stores the result to a variable.

Parameters:
1 – variable to store read result (any variable or array item)
2 – memory addressа to read (any integer value)
3 – number of bytes to read: 1, 2 or 4 bytes
4 – Virtual Protect: use 1 if the address is unreadable, 0 – if address is readable.


CODE
0A8C: write_memory 0x00969110 size 4 value 0 virtual_protect 0

0A8C writes a value to the game memory.

Parameters:
1 – memory address (any integer value)
2 – number of bytes to write: 1, 2 or 4 bytes
3 – value to write (any number)
4 – Virtual Protect: use 1 to write to the read-only address, 0 – if the address is rewritable.

we can use the adress 0x00969110 as cheat key_press check

we have to use the hex charackter of ASCII Table
to check for a key_press
40 = @
41 = A
42 = B
43 = C
44 = D
45 = E
46 = F
47 = G
48 = H
49 = I
4A = J
4B = K
4C = L
4D = M
4E = N
4F = O
50 = P
51 = Q
52 = R
53 = S
54 = T
55 = U
56 = V
57 = W
58 = X
59 = Y
5A = Z
5B = [
5C = \
5D =]
5E =^

ascii-table calculator



The check if key M is pressed requires first to read 1 byte of the adress 0x00969110
CODE
0A8D: 1@ = read_memory 0x00969110 size 1 virtual_protect 0

the check if the returned value is equal to the ascii character as hex of M
CODE
if
04A4:   1@ == 0x4D


check 2 keys: MM
CODE
0A8D: 1@ = read_memory 0x00969110 size 2 virtual_protect 0
if
04A4:   1@ == 0x4D4D


check 4 keys: WILD
CODE
0A8D: 1@ = read_memory 0x00969110 size 4 virtual_protect 1
if
04A4:   1@ == 0x57494C44 //checks if 1@ = WILD



The script below activate the Mega Jump if you type JUMP
CODE
{$CLEO .cs}
thread 'cheat'

:Cheatcode_1
wait 0
0A8D: 1@ = read_memory 0x00969110 size 4 virtual_protect 0
if
04A4:   1@ == 0x4A554D50 //checks if 1@ = JUMP
004D: jump_if_false @Cheatcode_1
03E5: text_box 'CHEAT1'
0109: player $PLAYER_CHAR money += 1000000
0A8C: write_memory 0x00969110 size 4 value 0 virtual_protect 0 //clear the buffer
0A8C: write_memory 0x96916C size 4 value 1 virtual_protect 0 //-- activates Mega Jump
0A93: end_custom_thread


To check for more than 4 charackter needs to use an additional memory adress: 0x00969114
It requires to assigne the first 4 charackter to this adress and the following 1, 2 or 4 charackter to 0x00969110

The script above spawns a Jump Ramp if you type JUMPRAMP
CODE
{$CLEO .cs}
thread 'cheat'

:Cheatcode_1
wait 0
0A8D: 1@ = read_memory 0x00969110 size 4 virtual_protect 0 //
0A8D: 2@ = read_memory 0x00969114 size 4 virtual_protect 0 //
if  and
04A4:   1@ == 0x52414D50 //checks if 1@ = RAMP
04A4:   2@ == 0x4A554D50 //checks if 2@ = JUMP
004D: jump_if_false @Cheatcode_1
03E5: text_box 'CHEAT1'
0109: player $PLAYER_CHAR money += 1000000
0A8C: write_memory 0x00969110 size 4 value 0 virtual_protect 0 //clear the buffer
0A8C: write_memory 0x00969114 size 4 value 0 virtual_protect 0 //clear the buffer
0247: request_model 1655

:Cheatcode_JRamp
0001: wait  0 ms
00D6: if  0
0248:   model 1655 available
004D: jump_if_false @Cheatcode_JRamp
0172: 2@ = actor $PLAYER_ACTOR z_angle
04C4: create_coordinate 11@ 12@ 13@ from_actor $PLAYER_ACTOR offset 0.0 14.5  -1.8
0107: 1@ = create_object 1655 at  11@ 12@ 13@
0177: set_object 1@ z_angle_to  2@
0001: wait  0 ms
0249: release_model 1655
0001: wait  1000 ms
01C4: remove_references_to_object 1@  // This object will now disappear when the player looks away
0002: jump @Cheatcode_1


type ARMOUR to have a bodyarmour pickup in Grovestreet
CODE
{$CLEO .cs}
thread 'cheat'

:Cheatcode_1//ARMOUR
wait 0
0A8D: 1@ = read_memory 0x00969110 size 4 virtual_protect 0 //
0A8D: 2@ = read_memory 0x00969114 size 2 virtual_protect 0 //
if  and
04A4:   1@ == 0x4D4F5552//MOUR
04A4:   2@ == 0x4152//AR
004D: jump_if_false @Cheatcode_1
03E5: text_box 'CHEAT1'
0109: player $PLAYER_CHAR money += 1000000
0A8C: write_memory 0x00969110 size 4 value 0 virtual_protect 0 //clear the buffer
0A8C: write_memory 0x00969114 size 2 value 0 virtual_protect 0 //clear the buffer
Pickup.Create(0@, 1242, 3, 2495.1387, -1680.1288, 13.3388)
0002: jump @Cheatcode_1


QUOTE (Rapier @ Aug 31 2009, 04:05)
QUOTE (ZAZ @ Jun 5 2009, 18:34)
we can use the adress 0x00969110 as cheat key_press check

This memory address is for version 1.0, but, for version 1.01 which will be?
That's because my mods did not work anymore after I did the upgrade to version 1.01 and all are activated as a cheat.

QUOTE (Wesser @ Aug 31 2009, 07:21)
It's 0x96B790 for 1.1. smile.gif



related topic about memory adress
car struct, actor struct, object struct
Help With Advanced Memory Access, Help me learn the basics
Changing Car Handling


coin-god
  • coin-god

    High Roller

  • $outh $ide Hoodz
  • Joined: 18 Mar 2007

#17

Posted 05 June 2009 - 09:38 PM

So.. you did have this in your german site all the time? tounge.gif


Awesome work ZAZ, its usefull for me to understand some things i didnt got during this years coding smile.gif

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#18

Posted 06 June 2009 - 02:23 AM Edited by ZAZ, 26 July 2010 - 04:18 PM.


call_scm_function


QUOTE (The_Siggi's sent pm)
Well, as it has been already explained in other ways, I'll try to let you understand a more confortable one hopefully.
0AB1 works like 004F does but it has the ability to return:

  • TRUE/FALSE, respectively with 0485 and 059A, but the function must end with 0AB2 without returned params, otherwise the game would crash. These are kinda useful when you want to make a contition function.

  • Any value by using 0AB2.

IN AN EXTERN THREAD

0AB1 is structured in such way:
CODE
0AB1: call_scm_func <thread> <param_count> | <param1> <param2> ...

As many as the parameters count says. Those params can be a number or a local/global var, indipendendlty for what it's their offset.

IN THE FUNCTION THREAD

All passed params are stored in a progressive offsets chain which starts always from 0. So the 1st passed param will be stored in 0@, the 2nd in 1@... and so on until the max local var offset (33@). Don't forget to end the function with 0AB2 which has about the same sintax:
CODE
0AB2: ret <param_count> | <param1> <param2> ...

If it returns at least one param, you should store the returned var/s at 0AB1 as follows:
CODE
0AB1: call_scm_func <thread> <param_count> | <param1> <param2> ... |  <param1> <param2> ...


FUNCTION SAMPLES

CONDITION
CODE
[...]
if
0AB1: call_scm_func @isActorDriving 1 actor $PLAYER_ACTOR
then
 03C0: 0@ = actor $PLAYER_ACTOR car
end
[...]

:isActorDriving
{
 0@ - actor
}
if
00DF:  actor 0@ driving
then
 0485: return_true
else
 059A: return_false
end
0AB2: ret 0

SET
CODE
[...]
0AB1: call_scm_func @setActorHealth 2 actor $PLAYER_ACTOR health 100
[...]

:setActorHealth
{
 0@ - actor
 1@ - health
}
0223: set_actor 0@ health_to 1@
0AB2: ret 0

GET
CODE
[...]
0AB1: call_scm_func @getActorArmour 1 actor $PLAYER_ACTOR armour_to 10@
[...]

:getActorArmour
{
 0@ - actor
}
04DD: 1@ = actor 0@ armour
0AB2: ret 1 1@

SET/GET
CODE
[...]
00A0: store_actor $PLAYER_ACTOR position_to 1@ 2@ 3@
0AB1: call_scm_func @getRandomPos 4 in 1@ 2@ 3@ radius 4@ out_to 5@ 6@ 7@
[...]

:getRandomPos
{
 0@ - X pos
 1@ - Y pos
 2@ - Z pos
 3@ - radius
}
0087: 4@ = 0@
0087: 5@ = 1@
0063: 4@ -= 3@
0063: 5@ -= 3@
005B: 0@ += 3@
005B: 1@ += 3@
0@ = random(4@, 0@)
1@ = random(5@, 1@)
02CE: 2@ = ground_z_at 1@ 2@ 3@
0AB2: ret 3 0@ 1@ 2@

how many parameter can 0AB1: have?
QUOTE (Wesser @ Jul 26 2010, 15:50)
I guess it takes 34 params as max since they're stored in the function from 0@ to 33@. biggrin.gif





Script to show text without gxt or fxt like the example script of the sannybuilder files
Script by Rapier
CODE
{$CLEO}

thread 'MSG_TEST'
wait 5000
0AB1: call_scm_func @LabelMSGMain 1 @LabelMSG01
wait 5000
0AB1: call_scm_func @LabelMSGMain 1 @LabelMSG02
0A93: end_custom_thread

:LabelMSGMain
0A9F: 1@ = current_thread_pointer
1@ += 16
0A8D: 1@ = read_memory 1@ size 4 virtual_protect 0
0062: 1@ -= 0@ // (int)
1@ += 4
if
0AA9:  is_game_version_original
jf @LabelMSGVersion101
0AA5: call 0x588BE0 num_params 4 pop 4 0 0 0 1@ // v1.0
jump @LabelMSGMain02

:LabelMSGVersion101
0AA5: call 0x5893B0 num_params 4 pop 4 0 0 0 1@ // v1.01

:LabelMSGMain02
0AB2: ret 0

:LabelMSG01
0900: "You are playing..."

:LabelMSG02
0900: "GTA San Andreas"
0000: nop



related topic
Help With Advanced Memory Access, Help me learn the basics

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


QUOTE (goin-god @ Jun 5 2009, 21:38)
So.. you did have this in your german site all the time? tounge.gif

Yes, since August 2008, but not all that themes like here.

DvD463
  • DvD463

    Player Hater

  • Members
  • Joined: 02 Dec 2008

#19

Posted 02 July 2009 - 11:47 AM

Can you please somebody make the tutorial to Czech?

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#20

Posted 02 July 2009 - 08:01 PM Edited by ZAZ, 05 September 2010 - 11:59 AM.

QUOTE (DvD463 @ Jul 2 2009, 11:47)
Can you please somebody make the tutorial to Czech?

use google translater click me

_____________________________________________________________________________________


Catch random actor



There are several opcodes to get random actors at several points :

CODE
089E: get_actor_in_sphere 3@ 4@ 5@ radius 5.0 handle_as 11@ // versionB
08E5: get_actor_in_sphere 27@ 28@ 29@ radius 50.0 handle_as 0@
073F: get_actor_in_sphere 4@ 7@ 10@ radius 20.0 with_pedtype_civilian 1 gang 1 criminal/prostitute 1 handle_as 27@


But they couldn't get gang type, drug dealer, and any other actors (especially custom actors in missions!)

furthermore there is a cleo opcde :

CODE
0AB5: store_actor $PLAYER_ACTOR closest_vehicle_to 0@ closest_ped_to 1@


But, it only get the nearest actor, otherwise you can't!
And also if these opcodes used in a place without any single human, it will gone crash!

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

Our member Wesser posted a method to get every actor in the gameworld, also those of missions, extern scripts as well as other cleo script except those of the food stores like burgershop etc.

find Wessers original template here: call_func @getActorInSphere

He used the opcode 0AB1: call_func which is explained above, in previous theme
furthermore the for-to-step-method which is used in several programming languages and supported in Sannybuilder
The for loop repeats a block of code while a control variable runs through an arithmetic progression.

A smaller and faster vaiation was done by Deji. Find the template >here<

To make it more clear I composed and recompiled Wessers script into an example for gta praxis
1. script with opcodes
2. script without opcodes
The script catches any random actor, shows his pedtype and let him die

1. script with opcodes
CODE
{$CLEO .cs}
:RandomActor_for_to_step_method
thread 'RAFSTEP'

:RAFSTEP_1
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @RAFSTEP_1
00A0: store_actor $PLAYER_ACTOR position_to 1@ 2@ 3@
0AB1: call_scm_func @RAFSTEP_func 4 1@ 2@ 3@ 5.0 0@
00D6: if
8039:   not  0@ == -1
004D: jump_if_false @RAFSTEP_1
00D6: if
8118:   not actor 0@ dead
004D: jump_if_false @RAFSTEP_1
089F: get_actor 0@ pedtype_to 31@
03F0: enable_text_draw 1
0001: wait 50 ms
03F0: enable_text_draw 0
0001: wait 50 ms
045A: draw_text_1number 250.0 40.0 GXT 'NUMBER' number 31@  // ~1~
05BE: AS_kill_actor 0@
01C2: remove_references_to_actor 0@ // Like turning an actor into a random pedestrian
0002: jump @RAFSTEP_1

:RAFSTEP_func
0006: 5@ = 0
0006: 4@ = 0

:RAFSTEP_countLoop
00D6: if
056D:   actor 4@ defined
004D: jump_if_false @RAFSTEP_11
00D6: if and
803B:   not  $PLAYER_ACTOR == 4@ // (int)
00FE:   actor 4@ sphere 0 in_sphere 0@ 1@ 2@ radius 3@ 3@ 3@
004D: jump_if_false @RAFSTEP_11
0006: 5@ = 1
0002: jump @RAFSTEP_12

:RAFSTEP_11
000A: 4@ += 1
00D6: if
0019:   4@ > 30000
004D: jump_if_false @RAFSTEP_countLoop

:RAFSTEP_12
00D6: if
0039:   5@ == 0
004D: jump_if_false @RAFSTEP_Result
0006: 4@ = -1

:RAFSTEP_Result
0AB2: ret 1 4@


2. script without opcodes
CODE
{$CLEO .cs}
:RandomActor_for_to_step_method
thread 'RAFSTEP'

:RAFSTEP_1
wait 0
if
  Player.Defined($PLAYER_CHAR)
jf @RAFSTEP_1
Actor.StorePos($PLAYER_ACTOR, 1@, 2@, 3@)
0AB1: call_scm_func @RAFSTEP_func 4 1@ 2@ 3@ 5.0 0@
if
  not 0@ == -1
jf @RAFSTEP_1
if
  not Actor.Dead(0@)
jf @RAFSTEP_1
089F: get_actor 0@ pedtype_to 31@
03F0: enable_text_draw 1
wait 50
03F0: enable_text_draw 0
wait 50
045A: draw_text_1number 250.0 40.0 GXT 'NUMBER' number 31@  // ~1~
05BE: AS_kill_actor 0@
Actor.RemoveReferences(0@)
jump @RAFSTEP_1

:RAFSTEP_func
5@ = 0
4@ = 0

:RAFSTEP_countLoop
if
  Actor.Defined(4@)
jf @RAFSTEP_11
if and
803B:   not  $PLAYER_ACTOR == 4@ // (int)
00FE:   actor 4@ sphere 0 in_sphere 0@ 1@ 2@ radius 3@ 3@ 3@
jf @RAFSTEP_11
5@ = 1
jump @RAFSTEP_12

:RAFSTEP_11
4@ += 1
if
 4@ > 30000
jf @RAFSTEP_countLoop

:RAFSTEP_12
if
 5@ == 0
jf @RAFSTEP_Result
4@ = -1

:RAFSTEP_Result
0AB2: ret 1 4@



DarthGrijo
  • DarthGrijo

    V.I.P MEMBER! yeah, i wish

  • Members
  • Joined: 01 May 2008

#21

Posted 03 July 2009 - 08:12 AM

Hey,

How would u make a cleo mod that displays the vehicle( your currently in)'s health?

like if i were in a slamvan it would display the slamvan's current health? suicidal.gif

Thanx biggrin.gif

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#22

Posted 03 July 2009 - 09:28 AM

QUOTE (DarthGrijo @ Jul 3 2009, 08:12)
Hey,

How would u make a cleo mod that displays the vehicle( your currently in)'s health?

like if i were in a slamvan it would display the slamvan's current health?  suicidal.gif

Thanx  biggrin.gif

Please post here questions which belongs to the tutorial.
Generell questions of mission coding will be answerd in the mission coding forum
use opcode search tool to find opcodes for your plan
you need to get the instance of the player car, then read the health of the car and use any text opcode which allows to display a value.

DvD463
  • DvD463

    Player Hater

  • Members
  • Joined: 02 Dec 2008

#23

Posted 03 July 2009 - 10:11 AM

Ok, Thanks wink.gif

DaBeast.
  • DaBeast.

    I can has polygon?

  • Members
  • Joined: 12 Jan 2009
  • None

#24

Posted 03 July 2009 - 12:19 PM

Awesomely detailed tutorial ZAZ, truly awesome. I also like the flowchart. Keep it up man! icon14.gif

bull.04
  • bull.04

    :D

  • Members
  • Joined: 11 Apr 2008

#25

Posted 14 August 2009 - 06:43 AM

I know it's kind of A bump, but I need to load from SPC_GA the bank_087 sound_023 how would I load that from a script?

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#26

Posted 16 August 2009 - 09:35 AM

QUOTE (bull.04 @ Aug 14 2009, 06:43)
I know it's kind of A bump, but I need to load from SPC_GA the bank_087 sound_023 how would I load that from a script?

Sorry, I don't know. I think there is no way to execute this sound by script.
Maybe it's possible with 09D5: but it needs to do a lot of trail and error to find out which sound number plays which sound.
The sound numbers for script use have no association to the file names.
opcode 09D5 plays voice sounds which are also mostly used from exe for random peds on street
like pain sounds, breathing, coughing ect...
presumable uses PAIN_A SFX, SPC_FA SFX, SPC_PA SFX Archive Directory

bull.04
  • bull.04

    :D

  • Members
  • Joined: 11 Apr 2008

#27

Posted 16 August 2009 - 03:55 PM

Hmmm, I was trying to get the sound from SPC_GA.

markbaker
  • markbaker

    Player Hater

  • Members
  • Joined: 26 Aug 2009

#28

Posted 26 August 2009 - 12:36 PM

Great Tutorial!

I have a couple simple questions - how can I spawn a vehicle & have it drive forward on it's own, either in a straight line or along a specified path? Also, is it possible to spawn a vehicle that has peds driving/riding in it?

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#29

Posted 28 August 2009 - 06:30 PM Edited by ZAZ, 03 October 2009 - 09:38 AM.


Car Drive Tutorial

QUOTE (markbaker @ Aug 26 2009, 12:36)
Great Tutorial!

I have a couple simple questions -  how can I spawn a vehicle & have it drive forward on it's own, either in a straight line or along a specified path?  Also, is it possible to spawn a vehicle that has peds driving/riding in it?

Ok, lets start with the base: "how can I spawn a vehicle" and use the exemple script of
tutorial theme: Scripting/Writing a Thread -- Next Step/ Spawn a 3D model

Script below spawns the car Infernus in Grovestreet if player goes into red marker(sphere)
If player leave the spot the car will be released from script and the reading process jumps back into 1.Loop
CODE
{$CLEO .cs}
:3dModels_1
03A4: name_thread 'MODL'

:3dModels_2
0001: wait  0 ms
00D6: if  0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @3dModels_2
00D6: if  0
00FF:   actor $PLAYER_ACTOR  1 (in-sphere)near_point_on_foot 2491.5  -1667.5  13.35 radius  1.0  1.0  1.0
004D: jump_if_false @3dModels_2

0247: request_model #INFERNUS

:Load_Model_Check
0001: wait  0 ms
00D6: if  0
0248:   model #INFERNUS available
004D: jump_if_false @Load_Model_Check

00A5: 1@ = create_car #INFERNUS at 2487.5  -1660.5  13.35
0175: set_car 1@ z_angle_to 90.0
0249: release_model #INFERNUS

:3dModels_3
0001: wait  0 ms
00D6: if  0
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @3dModels_3
00D6: if  0
80FF:   NOT   actor $PLAYER_ACTOR  0 ()near_point_on_foot 2491.5  -1667.5  13.35 radius  2.0  2.0  2.0
004D: jump_if_false @3dModels_3
01C3: remove_references_to_car 1@  // Like turning a car into any random car
0002: jump @3dModels_2



In the next step I spawn 2 actors in the car and let the car drive to a fix coord destination
fourthermore I add an marker to can see on radar where the car is.

To spawn the actor directly in the car I use opcode 0129: for the driver and 01C8: for the passenger.
It's also possible to spawn the actors by normal placement and let then the actors enter the car. Either as driver or as passenger, also with different opcodes.
The passenger opcodes needs to set the seat number in the last parameter:
0 = front passenger seat, 1 or 2 for the back seats

To let the car drive I use a simple "drive_to opcode"
There are a lot of other variation to let a car drive and it requires allways to set the speed.

The Loop after the "drive-to commands" needs now conditions which belongs to the car drive action
Very important is to check if the car is wrecked.
We need one or more ways to let the script refresh, I mean to release the car, it's marker and the actors from our script in some cases to can beginn the script from beginning.
Such situations can be if player dies or gets arrested, if the car is wrecked or if it is far away
if or
0119: car 1@ wrecked
01F4: car 1@ flipped
8202: not actor $PLAYER_ACTOR near_car 1@ radius 500.0 500.0 flag 0


Script below spawns the car Infernus in Grovestreet with two homies inthere,
if player goes into red marker(sphere)
It drives to the next crossroad and stays there till player is far away from car (500.0 units)
CODE
{$CLEO .cs}
:CarDrive_1
03A4: name_thread 'CDRIVE'

:CarDrive_2
0001: wait  0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @CarDrive_2
if
00FF:   actor $PLAYER_ACTOR  1 (in-sphere)near_point_on_foot 2491.5  -1667.5  13.35 radius  1.0  1.0  1.0
004D: jump_if_false @CarDrive_2

0247: request_model #INFERNUS
0247: request_model #fam1
0247: request_model #fam2

:CarDrive_3
0001: wait  0 ms
if  and
0248:   model #INFERNUS available
0248:   model #fam1 available
0248:   model #fam2 available
004D: jump_if_false @CarDrive_3

00A5: 1@ = create_car #INFERNUS at 2487.5  -1660.5  13.35
0175: set_car 1@ z_angle_to 90.0
0129: 2@ = create_actor  8 #fam1 in_car 1@ driverseat
01C8: 3@ = create_actor  8 #fam2 in_car 1@ passenger_seat  0
0186: 4@ = create_marker_above_car 1@
07E0: set_marker 4@ type_to 1

0249: release_model #INFERNUS
0249: release_model #fam1
0249: release_model #fam2

////////////////////  the drive-to commands --vv----

00A7: car 1@ drive_to 2353.1528 -1658.6493 13.3846//---simple drive-to command
00AD: set_car 1@ max_speed_to  20.0//---speed declaration, important!!
00AE: unknown_set_car 1@ to_ignore_traffic_lights  2//--optional, sets car to ignore red-lights and drive around traffic


////////////////////  the drive-to commands --^^----



:CarDrive_13
0001: wait  0 ms
if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @CarDrive_13
if  or
0119:     car 1@ wrecked
01F4:     car 1@ flipped
8202:   not actor $PLAYER_ACTOR near_car 1@ radius 500.0 500.0 flag 0
004D: jump_if_false @CarDrive_13
01C3: remove_references_to_car 1@  // Like turning a car into any random car
01C2: remove_references_to_actor 2@ // Like turning an actor into a random pedestrian
01C2: remove_references_to_actor 3@ // Like turning an actor into a random pedestrian
0164: disable_marker 4@
0002: jump @CarDrive_2



As I said, there are a lot of other variation to let a car drive. The opcode 00A7: of the exemple above is the simpliest.
The car drive then strictly along the gta paths. The paths are stored in the nodes.dat in gta3.img
These paths are the routes for the random cars in traffic.
If you place a car in an area without path like in middle of the desert and let then the car drive, it drives first to the path
and then to the destination.
The car can not reach the destination if the destination is not on a path.
A car drive script can be a very annoying work, also if the destinations are on paths.
It often won't drive that route which we want or it stucks.

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

We have several opcodes to force the car to let it do what we want

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

opcode 04e0: let the car ingnore the paths and let it drive straight ahead to the destination
04e0: car 1@ abandon_path_radius 200

replace the script part with the drive-to commands of script above with this drive-to commands:
CODE
////////////////////  the drive-to commands --vv----

00A7: car 1@ drive_to 2431.5864 -1628.0818 13.698//---simple drive-to command
00AD: set_car 1@ max_speed_to  20.0//---speed declaration, important!!
00AE: unknown_set_car 1@ to_ignore_traffic_lights  2//--optional, sets car to ignore red-lights and drive around traffic
04e0: car 1@ abandon_path_radius 200

////////////////////  the drive-to commands --^^----

the destination is between the highway and grovestreet at that empty area
without 04e0: the car drives a long way on the street
opcode 04e0: works only in the given radius,
it means: by radius 200 the startpoint and the next destination may not be bigger than 200 units
more than 250 is not possible

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

the car chases the player with opcode 00AF: and 2 as last parameter

CODE
////////////////////  the drive-to commands --vv----

00AD: set_car 1@ max_speed_to  20.0//---speed declaration, important!!
00AE: unknown_set_car 1@ to_ignore_traffic_lights  2//--optional, sets car to ignore red-lights and drive around traffic
00AF: set_car 1@ driver_behaviour_to  2//-- 2 as last param let chase the player

////////////////////  the drive-to commands --^^----


four valid settings for opcode 00AF:
1 - follow road, drive back if way is blocked
2 - kill the player
4 - drive to player and stop
8 - ignore road-paths

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

the car drives automaticly along the paths with opcode 00AF: and 1 as last parameter

CODE
////////////////////  the drive-to commands --vv----

00AD: set_car 1@ max_speed_to  20.0//---speed declaration, important!!
00AE: unknown_set_car 1@ to_ignore_traffic_lights  2//--optional, sets car to ignore red-lights and drive around traffic
00AF: set_car 1@ driver_behaviour_to 1

////////////////////  the drive-to commands --^^----


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

We can use an opcode to read the coords infront of the car and let it drive to that point

CODE
////////////////////  the drive-to commands --vv----

0407: create_coordinate 11@ 12@ 13@ from_car 1@ offset  -10.0  15.0  0.0
00A7: car 1@ drive_to 11@ 12@ 13@//---simple drive-to command
00AD: set_car 1@ max_speed_to  20.0//---speed declaration, important!!
00AE: unknown_set_car 1@ to_ignore_traffic_lights  2//--optional, sets car to ignore red-lights and drive around traffic


////////////////////  the drive-to commands --^^----


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

We can use an opcode to read the coords infront of the car and let it drive to that point
and give it a start boost with opcode 04BA:

CODE
////////////////////  the drive-to commands --vv----

0407: create_coordinate 11@ 12@ 13@ from_car 1@ offset  -10.0  15.0  0.0
00A7: car 1@ drive_to 11@ 12@ 13@//---simple drive-to command
00AD: set_car 1@ max_speed_to  20.0//---speed declaration, important!!
00AE: unknown_set_car 1@ to_ignore_traffic_lights  2//--optional, sets car to ignore red-lights and drive around traffic
04BA: set_car 1@ speed_instantly  50.0

////////////////////  the drive-to commands --^^----


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

Let the driver do corrections

R* use in the main.scm a stuck car check, but this function don't work in Cleo
But to let the driver do corrections can be used opcode 06C7:

CODE
////////////////////  the drive-to commands --vv----

06C7: AS_actor 2@ driver_of_car 1@ perform_action 14 timelimit 3000    //backward circle
00A7: car 1@ drive_to 2353.1528 -1658.6493 13.3846//---simple drive-to command
00AD: set_car 1@ max_speed_to  20.0//---speed declaration, important!!
00AE: unknown_set_car 1@ to_ignore_traffic_lights  2//--optional, sets car to ignore red-lights and drive around traffic

////////////////////  the drive-to commands --^^----


the driver make first a backward circle for ca. 3 seconds, then the car drives to the given point
----------------------------------------------------------------------------
some different versions of opcode 06C7:
CODE
06C7: AS_actor 2@ driver_of_car 1@ perform_action 6 timelimit 1000     //a short stop                    
06C7: AS_actor 2@ driver_of_car 1@ perform_action 6 timelimit 2000000  //a long stop                    
06C7: AS_actor 2@ driver_of_car 1@ perform_action 3 timelimit 3000     //backwards to the right side, than straight ahead
06C7: AS_actor 2@ driver_of_car 1@ perform_action 22 timelimit 3000    //backwards to the left side, than straight ahead  
06C7: AS_actor 2@ driver_of_car 1@ perform_action 14 timelimit 3000    //backward circle                  
06C7: AS_actor 2@ driver_of_car 1@ perform_action 9 timelimit 3000     //bump forward                        
06C7: AS_actor 2@ driver_of_car 1@ perform_action 7 timelimit 3000     //steer left                            
06C7: AS_actor 2@ driver_of_car 1@ perform_action 8 timelimit 3000     //steer right


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

Let the driver drive

Opcode 05D1: let the driver drive instead to let the car drive

This function can also ignore the paths (like using 04e0: car 1@ abandon_path_radius)
and let the driver drive the car directly to the given point
It's depending from the setting in the flags

0 0 5 let it drive on paths
2 0 5 ignore the paths

CODE
////////////////////  the drive-to commands --vv----

05D1: AS_actor 2@ drive_car 1@ to  2353.1528 -1658.6493 13.384 speed  20.0  0  0  5

////////////////////  the drive-to commands --^^----


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

Opcode 05D1: can be set more times as combo in an AS_Pack
It needs than to set -1 instead the variable name of the driver
and assign the actor 2@ after the AS_pack-setup to the defined AS_pack

CODE
////////////////////  the drive-to commands --vv----

0615: define_action_sequences 5@
05D1: AS_actor -1 drive_car 1@ to  2353.1528 -1658.6493 13.384 speed  20.0  0  0  5
05D1: AS_actor -1 drive_car 1@ to  2431.7739 -1674.7444 13.6643 speed  20.0  0  0  5
05D1: AS_actor -1 drive_car 1@ to  2431.5864 -1628.0818 13.698 speed  20.0  2  0  5
0616: define_action_sequences_end 5@
0618: assign_actor 2@ to_action_sequences 5@
061B: remove_references_to_AS_pack 5@

////////////////////  the drive-to commands --^^----



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

Define a scmpath for the driver

Set first opcode 05D6: to clear first a possibly created previous scmpath
Than set new coords for the scmpath and use opcode 07E7: to let the driver drive along this path

This function can also ignore the paths (like using 04e0: car 1@ abandon_path_radius)
and let the driver drive the car directly to the given point
It's depending from the setting in the flags

0 0 5 let it drive on paths
2 0 5 ignore the paths

CODE
////////////////////  the drive-to commands --vv----

05D6: clear_scmpath
05D7: add_point_to_scmpath  2353.1528 -1658.6493 13.384
05D7: add_point_to_scmpath  2431.7739 -1674.7444 13.6643
07E7: AS_assign_scmpath_to_actor 2@ in_car 1@ speed  20.0 flags  0  0  5

////////////////////  the drive-to commands --^^----


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

Car drive scripts in praxis

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

In praxis to write a car drive script with a longer specific route needs a more complex script,
which checks if the car reached the destination to can submit the new destination.
Because you can not check the same destination coords which you want to submit when the car reached it,
you must use access checks

Fourthermore it needs to check if the car do airborns because it looses the coord information
and we must give this information again in this case

A check if the car is fliped or wrecked makes allways sense, because it can not continue the route and the script should cancel the action in this case

R* use in the main.scm a stuck car check, but this function don't work in Cleo
a check if the car speed is smaller than 1.0 can help

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

The SF-Airport Circle version 1

The script below teleport the player to the SF airport on a motorbike and spawns an opponent driver on motorbike who drives around the airort building.
Go outside to the exterior map and press Backspace then follow the opponent driver to see what he do
Opcode 00A7: car 1@ drive_to is used and 04e0: car 1@ abandon_path_radius
The driver falls from bike sometimes and enters again his ride to continue the drive
Alternativ you can activte the opcode 08C6:
CODE
//08C6: set_actor 9@  stay_on_bike 1

To refresh the script needs to leave the aiport, you must have a distance of 700.0 units to the startpoint

CODE
{$CLEO .cs}
:Drive_1
03A4: name_thread 'DRIV'

:Drive_3
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @Drive_3
077E: 0@ = active_interior
if  and
0039:   0@ ==  0  // integer values
0AB0:   key_pressed 8//----------------------------------------Backspace  
jf @Drive_3
016A: fade  0 ()  250 ms
0001: wait 250 ms
01B4: set_player $PLAYER_CHAR frozen_state  0 (frozen)
0362: remove_actor $PLAYER_ACTOR from_car_and_place_at -1338.5  -408.1  14.1
0173: set_actor $PLAYER_ACTOR z_angle_to  90.8
0001: wait  500 ms
0247: request_model #NRG500
0247: request_model #MAFFA

:Drive_5
0001: wait  0 ms
if  and
0248:   model #NRG500 available
0248:   model #MAFFA available
jf @Drive_5
00A5: 1@ = create_car #NRG500 at -1333.5  -408.1  14.1
0175: set_car 1@ z_angle_to  280.0
0224: set_car 1@ health_to  2000
00A5: 7@ = create_car #NRG500 at -1354.5  -419.1  14.1
0175: set_car 7@ z_angle_to  280.0
0224: set_car 7@ health_to  2000
020A: set_car  7@ door_status_to 4
02AC: set_car 7@ immunities  1  1  1  1  1
01EC: make_car 7@ very_heavy  1
0129: 9@ = create_actor  24 #MAFFA in_car 7@ driverseat
0223: set_actor 9@ health_to  3000
04E4: unknown_refresh_game_renderer_at  -1333.5  -408.1
03CB: set_camera  -1333.5  -408.1  14.1
029B: 23@ = init_object 1655 at -1576.02  -202.34  13.76
0177: set_object 23@ z_angle_to  270.0
01C7: remove_object_from_mission_cleanup_list 23@
0382: set_object 23@ collision_detection  1
029B: 24@ = init_object 1655 at -1597.9  -506.5  21.7
0177: set_object 24@ z_angle_to  270.0
01C7: remove_object_from_mission_cleanup_list 24@
0382: set_object 24@ collision_detection  1
029B: 25@ = init_object 1655 at -1375.9  -581.5  13.69
0177: set_object 25@ z_angle_to  270.0
01C7: remove_object_from_mission_cleanup_list 25@
0382: set_object 25@ collision_detection  1
029B: 26@ = init_object 1655 at -1374.9  -585.5  13.69
0177: set_object 26@ z_angle_to  270.0
01C7: remove_object_from_mission_cleanup_list 26@

0382: set_object 26@ collision_detection  1
0177: set_object 23@ z_angle_to  135.0
0177: set_object 24@ z_angle_to  225.0
0177: set_object 25@ z_angle_to  280.0
0177: set_object 26@ z_angle_to  280.0
0186: 29@ = create_marker_above_car 7@
07E0: set_marker 29@ type_to 1

0249: release_model #NRG500
0249: release_model #MAFFA
04e0: car 7@ abandon_path_radius 200
00AD: set_car 7@ max_speed_to  100.0
04BA: set_car 7@ speed_instantly  30.0
00AF: set_car 7@ driver_behaviour_to  1
00AE: unknown_set_car 7@ to_ignore_traffic_lights  2
0001: wait  250 ms
036A: put_actor $PLAYER_ACTOR in_car 1@
0001: wait  250 ms
016A: fade  1 ()  1000 ms
0001: wait  1000 ms
0373: set_camera_directly_behind_player
02EB: restore_camera_with_jumpcut
01B4: set_player $PLAYER_CHAR frozen_state  1 (unfrozen)
0006: 15@ =  0  // integer values
0006: 16@ =  0  // integer values
0006: 20@ =  20000  // floating-point values
0006: 19@ =  0  // integer values
0007: 11@ =  -1320.48  // floating-point values
0007: 12@ =  -407.1  // floating-point values
0007: 13@ =  13.76  // floating-point values
00A7: car 7@ drive_to  11@ 12@ 13@
00AD: set_car 7@ max_speed_to  1.0
04e0: car 7@ abandon_path_radius 250
//08C6: set_actor 9@  stay_on_bike 1

:Drive_7
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @Drive_7

0050: gosub @Drive_sub_3

if  and
8119:   NOT   car 1@ wrecked
8119:   NOT   car 7@ wrecked
8118:   NOT   actor 9@ dead
jf @Drive_7
if
00FE:   actor $PLAYER_ACTOR  0 ()near_point -1333.5  -408.1  14.1 radius  650.5  650.5  50.5
jf @Drive_12
jump @Drive_7

:Drive_12
0164: disable_marker 29@
01C3: remove_references_to_car 1@  // Like turning a car into any random car
01C3: remove_references_to_car 7@  // Like turning a car into any random car
01C2: remove_references_to_actor 9@  // Like turning an actor into a random pedestrian
0108: destroy_object 23@
0108: destroy_object 24@
0108: destroy_object 25@
0108: destroy_object 26@
jump @Drive_3


:Drive_sub_3
if
8119:   NOT   car 7@ wrecked
jf @Drive_sub_109
if
00DB:   actor 9@ in_car 7@
jf @Drive_sub_99
if
0039:   19@ ==  1  // integer values
jf @Drive_sub_10
0006: 19@ =  0  // integer values
jump @Drive_sub_100

:Drive_sub_10
if
0039:   15@ ==  0  // integer values
jf @Drive_sub_11
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  5.2  5.2  5.0
jf @Drive_sub_11
0006: 15@ =  1  // integer values
0007: 11@ =  -1181.78  // floating-point values
0007: 12@ =  -331.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100

:Drive_sub_11
if
0039:   15@ ==  1  // integer values
jf @Drive_sub_12
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  15.2  15.2  5.0
jf @Drive_sub_12
00AD: set_car 7@ max_speed_to  10.0
0006: 15@ =  2  // integer values
0007: 11@ =  -1282.1  // floating-point values
0007: 12@ =  -159.3  // floating-point values
0007: 13@ =  13.76  // floating-point values
0175: set_car 7@ z_angle_to 340.0
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100


:Drive_sub_12
if
0039:   15@ ==  2  // integer values
jf @Drive_sub_13
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  15.2  15.2  5.0
jf @Drive_sub_13
00AD: set_car 7@ max_speed_to  25.0
0006: 15@ =  3  // integer values
0007: 11@ =  -1498.78  // floating-point values
0007: 12@ =  -138.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
0175: set_car 7@ z_angle_to 65.0
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100

:Drive_sub_13
if
0039:   15@ ==  3  // integer values
jf @Drive_sub_14
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  8.2  8.2  5.0
jf @Drive_sub_14
00AD: set_car 7@ max_speed_to  25.0
0006: 15@ =  4  // integer values
0007: 11@ =  -1576.78  // floating-point values
0007: 12@ =  -202.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
0175: set_car 7@ z_angle_to 135.0
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100



:Drive_sub_14
if
0039:   15@ ==  4  // integer values
jf @Drive_sub_15
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  5.2  5.2  5.0
jf @Drive_sub_15
0006: 15@ =  5  // integer values
0007: 11@ =  -1694.78  // floating-point values
0007: 12@ =  -352.30  // floating-point values
0007: 13@ =  13.9  // floating-point values
0175: set_car 7@ z_angle_to 135.0
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100

:Drive_sub_15
if
0039:   15@ ==  5  // integer values
jf @Drive_sub_16
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  15.2  15.2  5.0
jf @Drive_sub_16
00AD: set_car 7@ max_speed_to  10.0
0006: 15@ =  6  // integer values
0007: 11@ =  -1691.78  // floating-point values
0007: 12@ =  -409.30  // floating-point values
0007: 13@ =  13.9  // floating-point values
0175: set_car 7@ z_angle_to 180.0
000A: 16@ +=  0  // integer values
0007: 17@ =  40.0  // floating-point values
0007: 18@ =  10.0  // floating-point values
04e0: car 7@ abandon_path_radius 250
00AE: unknown_set_car 7@ to_ignore_traffic_lights  2
jump @Drive_sub_100

:Drive_sub_16
if
0039:   15@ ==  6  // integer values
jf @Drive_sub_17
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  8.2  8.2  5.0
jf @Drive_sub_17
00AD: set_car 7@ max_speed_to  0.0
0006: 15@ =  7  // integer values
0007: 11@ =  -1519.78  // floating-point values
0007: 12@ =  -580.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
0175: set_car 7@ z_angle_to 250.0
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  0.0  // floating-point values
04e0: car 7@ abandon_path_radius 250
00AE: unknown_set_car 7@ to_ignore_traffic_lights  2
jump @Drive_sub_100

:Drive_sub_17
if
0039:   15@ ==  7  // integer values
jf @Drive_sub_18
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  15.2  15.2  5.0
jf @Drive_sub_18
00AD: set_car 7@ max_speed_to  5.0
01EB: set_car_density_to  0.0
0006: 15@ =  8  // integer values
0007: 11@ =  -1299.78  // floating-point values
0007: 12@ =  -565.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
0175: set_car 7@ z_angle_to 0.0
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
04e0: car 7@ abandon_path_radius 250
jump @Drive_sub_100


:Drive_sub_18
if
0039:   15@ ==  8  // integer values
jf @Drive_sub_109
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  25.2  25.2  5.0
jf @Drive_sub_109
00AD: set_car 7@ max_speed_to  0.0
0006: 15@ =  1  // integer values
000A: 16@ +=  1  // integer values
0007: 11@ =  -1181.78  // floating-point values
0007: 12@ =  -331.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
0175: set_car 7@ z_angle_to 1.0
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
04e0: car 7@ abandon_path_radius 250
00AE: unknown_set_car 7@ to_ignore_traffic_lights  2

if
0039:   16@ ==  2  // integer values
jf @Drive_sub_100
00BC: text_highpriority 'BJ_LOSE'  5000 ms  1
jump @Drive_sub_100


:Drive_sub_99
if
0039:   19@ ==  0  // integer values
jf @Drive_sub_109
00AD: set_car 7@ max_speed_to  0.0
05CB: actor_goto_and_enter_car 9@ 7@  5000
0006: 19@ =  1  // integer values
jump @Drive_sub_109

:Drive_sub_100
00A7: car 7@ drive_to  11@ 12@ 13@
00AD: set_car 7@ max_speed_to  17@
03F0: text_draw_toggle  0
0006: 33@ =  0  // integer values
jump @Drive_sub_109



:Drive_sub_102
if
01F3:   car 7@ airborne
jf @Drive_sub_103
0007: 18@ =  0.0  // floating-point values
00A7: car 7@ drive_to  11@ 12@ 13@
04BA: set_car 7@ speed_instantly  18@
00AD: set_car 7@ max_speed_to  17@
jump @Drive_sub_103

:Drive_sub_103
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  30.2  30.2  5.0
jf @Drive_sub_104
jump @Drive_sub_105

:Drive_sub_104
02E3: 20@ = car 7@ speed
if
81F3:   NOT   car 7@ airborne
jf @Drive_sub_106
if  and
0021:   20@ >  30.0  // floating-point values
0019:   33@ >  700  // integer values
jf @Drive_sub_105
04BA: set_car 7@ speed_instantly  50.0

:Drive_sub_105
if
0019:   33@ >  2000  // integer values
jf @Drive_sub_109

:Drive_sub_106
0006: 33@ =  0  // integer values


:Drive_sub_109
0051: return


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

The SF-Airport Circle version 2

Same script as above but now opcode 07E7: AS_assign_scmpath_to_actor is used
It teleports the player to the SF airport on a motorbike and spawns an opponent driver on motorbike who drives around the airort building.
Go outside to the exterior map and press Backspace then follow the opponent driver to see what he do
To refresh the script needs to leave the aiport, you must have a distance of 700.0 units to the startpoint

CODE
{$CLEO .cs}
:scmpath_1
03A4: name_thread 'SCMP'

:scmpath_3
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @scmpath_3
077E: 0@ = active_interior
if  and
0038:   0@ ==  0  // integer values
0AB0:   key_pressed 8//----------------------------------------Backspace  
jf @scmpath_3
016A: fade  0 ()  250 ms
0001: wait 250 ms
01B4: set_player $PLAYER_CHAR frozen_state  0 (frozen)
0362: remove_actor $PLAYER_ACTOR from_car_and_place_at -1338.5  -408.1  14.1
0173: set_actor $PLAYER_ACTOR z_angle_to  90.8
0001: wait  500 ms
0247: request_model #NRG500
0247: request_model #MAFFA

:scmpath_5
0001: wait  0 ms
if  and
0248:   model #NRG500 available
0248:   model #MAFFA available
jf @scmpath_5
00A5: 1@ = create_car #NRG500 at -1333.5  -408.1  14.1
0175: set_car 1@ z_angle_to  280.0
0224: set_car 1@ health_to  2000
00A5: 7@ = create_car #NRG500 at -1354.5  -419.1  14.1
0175: set_car 7@ z_angle_to  280.0
0224: set_car 7@ health_to  2000
020A: set_car  7@ door_status_to 4
02AC: set_car 7@ immunities  1  1  1  1  1
01EC: make_car 7@ very_heavy  1
0129: 9@ = create_actor  24 #MAFFA in_car 7@ driverseat
0223: set_actor 9@ health_to  3000
04E4: unknown_refresh_game_renderer_at  -1333.5  -408.1
03CB: set_camera  -1333.5  -408.1  14.1
029B: 23@ = init_object 1655 at -1576.02  -202.34  13.76
0177: set_object 23@ z_angle_to  270.0
01C7: remove_object_from_mission_cleanup_list 23@
0382: set_object 23@ collision_detection  1
029B: 24@ = init_object 1655 at -1597.9  -506.5  21.7
0177: set_object 24@ z_angle_to  270.0
01C7: remove_object_from_mission_cleanup_list 24@
0382: set_object 24@ collision_detection  1
029B: 25@ = init_object 1655 at -1375.9  -581.5  13.69
0177: set_object 25@ z_angle_to  270.0
01C7: remove_object_from_mission_cleanup_list 25@
0382: set_object 25@ collision_detection  1
029B: 26@ = init_object 1655 at -1374.9  -585.5  13.69
0177: set_object 26@ z_angle_to  270.0
01C7: remove_object_from_mission_cleanup_list 26@

0382: set_object 26@ collision_detection  1
0177: set_object 23@ z_angle_to  135.0
0177: set_object 24@ z_angle_to  225.0
0177: set_object 25@ z_angle_to  280.0
0177: set_object 26@ z_angle_to  280.0
0186: 29@ = create_marker_above_car 7@
07E0: set_marker 29@ type_to 1

0249: release_model #NRG500
0249: release_model #MAFFA
04e0: car 7@ abandon_path_radius 200
00AD: set_car 7@ max_speed_to  100.0
04BA: set_car 7@ speed_instantly  30.0
00AF: set_car 7@ driver_behaviour_to  1
00AE: unknown_set_car 7@ to_ignore_traffic_lights  2
0001: wait  250 ms
036A: put_actor $PLAYER_ACTOR in_car 1@
0001: wait  250 ms
016A: fade  1 ()  1000 ms
0001: wait  1000 ms
0373: set_camera_directly_behind_player
02EB: restore_camera_with_jumpcut
01B4: set_player $PLAYER_CHAR frozen_state  1 (unfrozen)
0006: 15@ =  0  // integer values
0006: 16@ =  0  // integer values
0006: 20@ =  20000  // floating-point values
0006: 19@ =  0  // integer values
0007: 11@ =  -1320.48  // floating-point values
0007: 12@ =  -407.1  // floating-point values
0007: 13@ =  13.76  // floating-point values
00A7: car 7@ drive_to  11@ 12@ 13@
00AD: set_car 7@ max_speed_to  1.0
04e0: car 7@ abandon_path_radius 250
08C6: set_actor 9@  stay_on_bike 1





:scmpath_7
0001: wait 0 ms
if
0256: player $PLAYER_CHAR defined
jf @scmpath_7

0050: gosub @scmpath_sub_3

if  and
8119:   NOT   car 1@ wrecked
8119:   NOT   car 7@ wrecked
8118:   NOT   actor 9@ dead
jf @scmpath_7
if
00FE:   actor $PLAYER_ACTOR  0 ()near_point -1333.5  -408.1  14.1 radius  650.5  650.5  50.5
jf @scmpath_12
jump @scmpath_7

:scmpath_12
0164: disable_marker 29@
01C3: remove_references_to_car 1@  // Like turning a car into any random car
01C3: remove_references_to_car 7@  // Like turning a car into any random car
01C2: remove_references_to_actor 9@  // Like turning an actor into a random pedestrian
0108: destroy_object 23@
0108: destroy_object 24@
0108: destroy_object 25@
0108: destroy_object 26@
jump @scmpath_3


:scmpath_sub_3
if
8119:   NOT   car 7@ wrecked
jf @scmpath_sub_109
if
00DB:   actor 9@ in_car 7@
jf @scmpath_sub_99
if
0039:   19@ ==  1  // integer values
jf @scmpath_sub_10
0006: 19@ =  0  // integer values
jump @scmpath_sub_100

:scmpath_sub_10
if
0039:   15@ ==  0  // integer values
jf @scmpath_sub_11
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  5.2  5.2  5.0
jf @scmpath_sub_11
0006: 15@ =  1  // integer values
05D6: clear_scmpath
0007: 11@ =  -1181.78  // floating-point values
0007: 12@ =  -331.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100

:scmpath_sub_11
if
0039:   15@ ==  1  // integer values
jf @scmpath_sub_12
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  15.2  15.2  5.0
jf @scmpath_sub_12
00AD: set_car 7@ max_speed_to  10.0
0006: 15@ =  2  // integer values
05D6: clear_scmpath
0007: 11@ =  -1282.1  // floating-point values
0007: 12@ =  -159.3  // floating-point values
0007: 13@ =  13.76  // floating-point values
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100


:scmpath_sub_12
if
0039:   15@ ==  2  // integer values
jf @scmpath_sub_13
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  15.2  15.2  5.0
jf @scmpath_sub_13
00AD: set_car 7@ max_speed_to  25.0
0006: 15@ =  3  // integer values
05D6: clear_scmpath
0007: 11@ =  -1498.78  // floating-point values
0007: 12@ =  -138.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100

:scmpath_sub_13
if
0039:   15@ ==  3  // integer values
jf @scmpath_sub_14
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  8.2  8.2  5.0
jf @scmpath_sub_14
00AD: set_car 7@ max_speed_to  25.0
0006: 15@ =  4  // integer values
05D6: clear_scmpath
0007: 11@ =  -1576.78  // floating-point values
0007: 12@ =  -202.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100



:scmpath_sub_14
if
0039:   15@ ==  4  // integer values
jf @scmpath_sub_15
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  5.2  5.2  5.0
jf @scmpath_sub_15
0006: 15@ =  5  // integer values
05D6: clear_scmpath
0007: 11@ =  -1694.78  // floating-point values
0007: 12@ =  -352.30  // floating-point values
0007: 13@ =  13.9  // floating-point values
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100

:scmpath_sub_15
if
0039:   15@ ==  5  // integer values
jf @scmpath_sub_16
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  15.2  15.2  5.0
jf @scmpath_sub_16
00AD: set_car 7@ max_speed_to  10.0
0006: 15@ =  6  // integer values
05D6: clear_scmpath
0007: 11@ =  -1691.78  // floating-point values
0007: 12@ =  -409.30  // floating-point values
0007: 13@ =  13.9  // floating-point values
000A: 16@ +=  0  // integer values
0007: 17@ =  40.0  // floating-point values
0007: 18@ =  10.0  // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
00AE: unknown_set_car 7@ to_ignore_traffic_lights  2
jump @scmpath_sub_100

:scmpath_sub_16
if
0039:   15@ ==  6  // integer values
jf @scmpath_sub_17
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  8.2  8.2  5.0
jf @scmpath_sub_17
00AD: set_car 7@ max_speed_to  0.0
0006: 15@ =  7  // integer values
05D6: clear_scmpath
0007: 11@ =  -1519.78  // floating-point values
0007: 12@ =  -580.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  0.0  // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
00AE: unknown_set_car 7@ to_ignore_traffic_lights  2
jump @scmpath_sub_100

:scmpath_sub_17
if
0039:   15@ ==  7  // integer values
jf @scmpath_sub_18
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  15.2  15.2  5.0
jf @scmpath_sub_18
00AD: set_car 7@ max_speed_to  5.0
01EB: set_car_density_to  0.0
0006: 15@ =  8  // integer values
05D6: clear_scmpath
0007: 11@ =  -1299.78  // floating-point values
0007: 12@ =  -565.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
000A: 16@ +=  0  // integer values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@
jump @scmpath_sub_100


:scmpath_sub_18
if
0039:   15@ ==  8  // integer values
jf @scmpath_sub_109
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  25.2  25.2  5.0
jf @scmpath_sub_109
00AD: set_car 7@ max_speed_to  0.0
0006: 15@ =  1  // integer values
000A: 16@ +=  1  // integer values
05D6: clear_scmpath
0007: 11@ =  -1181.78  // floating-point values
0007: 12@ =  -331.30  // floating-point values
0007: 13@ =  13.76  // floating-point values
0007: 17@ =  100.0  // floating-point values
0007: 18@ =  20.0  // floating-point values
05D7: add_point_to_scmpath 11@ 12@ 13@

if
0039:   16@ ==  2  // integer values
jf @scmpath_sub_100
00BC: text_highpriority 'BJ_LOSE'  5000 ms  1
jump @scmpath_sub_100


:scmpath_sub_99
if
0039:   19@ ==  0  // integer values
jf @scmpath_sub_109
00AD: set_car 7@ max_speed_to  0.0
05CB: actor_goto_and_enter_car 9@ 7@  5000
0006: 19@ =  1  // integer values
jump @scmpath_sub_109

:scmpath_sub_100
07E7: AS_assign_scmpath_to_actor 9@ in_car 7@ speed 17@ flags 2 0 3
03F0: text_draw_toggle  0
0006: 33@ =  0  // integer values
jump @scmpath_sub_109



:scmpath_sub_102
if
01F3:   car 7@ airborne
jf @scmpath_sub_103
0007: 18@ =  0.0  // floating-point values
04BA: set_car 7@ speed_instantly  18@
07E7: AS_assign_scmpath_to_actor 9@ in_car 7@ speed 17@ flags 2 0 3
jump @scmpath_sub_103

:scmpath_sub_103
if
01AF:   car 7@  0 ()near_point 11@ 12@ 13@ radius  30.2  30.2  5.0
jf @scmpath_sub_104
jump @scmpath_sub_105

:scmpath_sub_104
02E3: 20@ = car 7@ speed
if
81F3:   NOT   car 7@ airborne
jf @scmpath_sub_106
if  and
0021:   20@ >  30.0  // floating-point values
0019:   33@ >  700  // integer values
jf @scmpath_sub_105
04BA: set_car 7@ speed_instantly  50.0

:scmpath_sub_105
if
0019:   33@ >  2000  // integer values
jf @scmpath_sub_109

:scmpath_sub_106
0006: 33@ =  0  // integer values


:scmpath_sub_109
0051: return

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#30

Posted 29 August 2009 - 01:22 PM


Use Carrec Paths to let a vehicle move along a recorded route

Record a path with Seemanns carrec.cs http://cleo.sannybuilder.com/
More informations at http://www.gtaforums...howtopic=297295

Its created then in GTASA\data\paths

Rename it to carrec899.rrr and import it into carrec.img
Then use the script below to assigne player car to the path
CODE
{$CLEO .cs}
:DrvCarrec_1
03A4: name_thread 'DRVCARC'

:DRVCARC_11
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @DRVCARC_11
00D6: if and
0AB0:   key_pressed 57
00DF:   actor $PLAYER_ACTOR driving
004D: jump_if_false @DRVCARC_11
03C0: 0@ = actor $PLAYER_ACTOR car
0A30: repair_car 0@
0224: set_car 0@ health_to 1000
0006: 8@ = 899
07C0: load_path 8@

:DRVCARC_85
0001: wait 0 ms
00D6: if
07C1:   path 8@ available
004D: jump_if_false @DRVCARC_85
00D6: if
8119:   not car 0@ wrecked
004D: jump_if_false @DRVCARC_218
0001: wait 500 ms
05EB: assign_car 0@ to_path 8@

:DRVCARC_148
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @DRVCARC_218
00D6: if or
0AB0:   key_pressed 48
0119:   car 0@ wrecked
004D: jump_if_false @DRVCARC_195
0002: jump @DRVCARC_218

:DRVCARC_195
00D6: if
00DF:   actor $PLAYER_ACTOR driving
004D: jump_if_false @DRVCARC_218
0002: jump @DRVCARC_148

:DRVCARC_218
0001: wait 0 ms
00D6: if
0256:   player $PLAYER_CHAR defined
004D: jump_if_false @DRVCARC_218
0373: set_camera_directly_behind_player
02EB: restore_camera_with_jumpcut
05EC: release_car 0@ from_path
0873: release_path 8@
01C3: remove_references_to_car 0@ // Like turning a car into any random car
0001: wait 1000 ms
0002: jump @DRVCARC_11




5 user(s) are reading this topic

0 members, 5 guests, 0 anonymous users