GTA SAN ANDREAS
MODS for


Script-Aufbau und das Prinzip der Abfrage-Technik
- Der Thread ist das Basis-Script in der Main.scm wie in Cleo-Scripten
- Er wird in "create_thread", in Missionen oder Externscripten definiert
oder vom Cleo-Programm gestartet, wenn Cleo eine Scriptdatei mit Endung .CS erkennt - Mit Abfragen werden unterschiedliche Script-Teile für den Leseprozess freigeschaltet
-
Script-Aufbau/kurz
- Unser Thread-Script bekommt einen Kopf (Header) und beginnt mit dem Eintrag der Cleo-Directive
- dann geben wir ihm sein erstes Label (Adresse).
- Dannach folgt die Namensgebung für den Thread mit:
- und dann gehts los, einen code rein, der was bewirkt und end_thread
und fertig
probierts aus: - Das Game schaltet in die Infrarot-Ansicht außer in Cutscenes
Das Script wird dann beendet, deaktiviert, weil es mit dem opcode 0A93: end_custom_thread endet
Es wird bei jedem Speicherstand-Laden und Neuem Spiel-Start neu gestartet - Jetzt möchten wir natürlich in die Normalansicht schalten können
Dazu bauen wir eine Schleife(Loop) ein, mit Abfrage
- Eine Abfrage besteht aus mindestens 3 opcodes:
- 1. die IF-Variation Näheres zur IF-Variation, weiter unten
- 2. die eigentliche Frage
- 3. Die Sprunganweisung bei Verneinung
1. if
2. 0AB0: key_pressed 8
3. 004D: jump_if_false @akt_01
- Abfragen nennen wir im script english CHECK
- LOOP-Adresse bedeutet, daß die Game-Engine beim Durchlesen des Scripts,
wieder zu dieser Adresse zurückspringt. Sie vollzieht eine Schleife.
Der Loop-Adresse muß unbedingt ein WAIT-code folgen.wait 0 ms bedeuted daß die Game-Engine 1/1000 Sekunde wartet. - so setzen wir unser nächstes Script folgendermaßen zusammen:
- -Scriptkopf
- -1.LoopAdresse
- -wait code
- -Abfrage
- -Ereignis
- -Ende
- Unsere Abfrage soll bei einem bestimmten Tastendruck passiert werden,
bei der "Backspace"-Taste
sieht dann aus: - Der Leseprozess der Game-Engine "loopt" nun in einer Schleife, solange Backspace nicht gedrückt wird
- Die Sprunganweisung bei Verneinung jump_if_false
@Akt_01
schickt ihn immer wieder zur Loop-Adresse Akt_01,
1000 mal pro Sekunde
Das Script wird dann beendet, deaktiviert, weil es mit dem opcode 0A93: end_custom_thread endet - Im nächsten Kapitel werden wir die Bedeutung des Loops vertiefen und ihn zu Nutze machen, um das Script dauerhaft laufen zu lassen
- Es ist:
- Er soll crashes verhindern, wenn der Player tot, verhaftet oder
sonstwas ist.
Der "IF Player- Defined-check" soll immer die erste Abfrage nach einer Loop-Adresse sein
Aufbau einfach, mit 1 Loop: - -Scriptkopf
- -1.Loop-Adresse
- -wait code
- -IF player_defined-Abfrage
- -Abfrage
- -Ereignis
- -Einfache Sprunganweisung zur 1.LoopAdresse
- Immer wenn Backspace gedrückt wird, schaltet das Spiel in die Infrarotansicht,
wartet dann 3 Sekunden
und schaltet dann wieder in die Normalansicht - Diesen Scriptaufbau empfehle ich euch in nächster Zukunft beizubehalten:
- -Scriptkopf
- -1.Loop-Adresse
- -wait code
- -IF player_defined-Abfrage
- -Abfrage
- -Ereignis
- -2.Loop-Adresse
- -wait code
- -IF player_defined-Abfrage
- -Abfrage
- -Einfache Sprunganweisung zur 1.LoopAdresse
- Ihr müsst euch nicht auf 2 Loops beschränken und es gibt auch andere Varianten sein Script aufzubauen
- Aber Ihr solltet es so machen, bis ihr richtig scripten könnt
- Bild zur Verdeutlichung wie Loop und Abfrage funktionieren
- Beispiel-Scripte:
- Screenshot
- Slowmotion
- First Person Camera
{$CLEO .cs}
:Akt
03A4: name_thread 'AKT'
{$CLEO .cs}
:Akt
03A4: name_thread 'AKT'
08B2: toggle_thermal_vision 1
0A93: end_custom_thread
{$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//--------Sprunganweisung bei Verneinung
08B2: toggle_thermal_vision 0
0A93: end_custom_thread
Script-Aufbau/einfach
Anstatt das Script enden zu lassen setzen wir eine einfach Sprunganweisung zur 1. Loop-Adresse ans Scriptende
0002: jump @Akt_01
Und diesmal bauen wir eine weitere Abfrage in unseren Loop mit ein, die wir immer bei jeder Loop-Adresse einbauen sollten
if
0256: player $PLAYER_CHAR defined
004D: jump_if_false @Akt_01
{$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
004D: jump_if_false @Akt_01
08B2: toggle_thermal_vision 1
0001: wait 3000 ms
08B2: toggle_thermal_vision 0
0002: jump @Akt_01//--------einfache Sprunganweisung zur 1.Loop Adresse
Script-Aufbau/modual (verläuft relativ zu veränderte Zustände)
Das Starten einer Aktion über unser Script verändert den Zustand
im Game aber dem Leseprozess ist das egal
Das Script muss nun den Leseprozess umleiten, um nicht die Aktion
zu wiederholen oder beendet werden zu müssen
Dafür integrieren wir einen 2. Loop im Script
Loop 1 - vor der Aktion
Loop 2 - nach der Aktion
Im folgendem Beispielscript wird das Player-Fahrzeug unzerstörbar
gemacht, sobald der Player in ein Fahrzeug eingestiegen ist.
Dazu muß die Instanz des Fahrzeugs registriert werden
Das erledigt der code: 03C0: 1@ = actor $PLAYER_ACTOR
car und verpasst dem car eine Locale
Variable über die es im weiteren verlauf des Script benutzt
werden kann
Hat der Player das Fahrzeug verlassen, springt der Leseprozess wieder
in den 1.Loop
{$CLEO .cs}
:akt
03A4: name_thread 'AKT'
:akt01//----------------------------1.Loop Adresse
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 Adresse
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//--------einfache Sprunganweisung zur 1.Loop Adresse
-
Die Gestaltung der Abfrage (
IF - CHECK)
- Hier wird die Frage-Variation angegeben
- Für die meisten Frage-codes gibts auch den dazugehörigen Gegenteil-Frage-code
- Beispiel:
- Wir betrachten nur die Opcodes:
- 00E1: / 80E1:
- und erkennen daß die erste Ziffer bei normaler Frage 0 ist,
- und bei Nein- Frage 8
- Die Abfragegestaltung ist die schwierigste Thematik beim Scripten und wird gerne falsch gemacht.
- Besonders, wenn man BW MB-basierte Scripte vor sich hat.
- Das Prinzip mit den Zahlen funktioniert folgendermaßen
- if 8 und 28 sind maximal möglich
- Ein paar Beispiele:
- Abgefragt wird:
- Fährt CJ NICHT, UND wird die Taste 10 gedrückt ?
- Abgefragt wird:
- Befindet sich CJ in der Zone Verdant Madows, ODER in der Zone Las Venturas ?
- Abgefragt wird:
- Ist KEINE Mission aktiv UND ist das Fahrzeug NICHT geschrottet
- UND NICHT gesunken UND wurde auch NICHT die Taste 11 gedrückt?
- Abgefragt wird:
- Ist CJ an einem der folgenden Orten ?
- ( Im Sinne von ODER )
- Abgefragt wird:
- Ist CJ an keinem der folgenden Orten ?
- ( Im Sinne von UND )
- Es ist vielleicht aufgefallen, daß der Variable-Name für die Player-Figur
- einmal $PLAYER_CHAR und ein anderesmal $PLAYER_ACTOR heißt.
- Der Player-Status wird zu Beginn der Main ins Leben gerufen
- Es gibt codes, die nur für den Player anwendbar sind
- z.B.
- 01B4: set_player $PLAYER_CHAR frozen_state 1 (unfrozen)
- viele andere codes dagegen können allgemein für alle actor (peds) verwendet werden.
- Dazu wurde der Player einem actor gleichgesetzt.
if
00D6: if
00D6: if 0
IF oder IF 0 , wenn nur eine Frage vorhanden ist
Alle 3 Schreibweisen sind gültig. Die Angabe einer Zahl ist die Klassische
Variante und stammt aus der Verwendung des BW Missionbuilder
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
Bei mehr als einer Frage muss angegeben werden,
ob sie im Sinne von UND oder ODER
gestellt werden sollen
"if and" und "if or" sind Keywords;
maximal 9 Fragen in einer Abfrage sind möglich
if and
00DF: actor $PLAYER_ACTOR driving
8119: NOT car 0@ wrecked
004D: jump_if_false @AD_5
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
if or
8118: NOT actor 7@ dead
8118: NOT actor 8@ dead
004D: jump_if_false @AD_25
0002: jump @AD_12
00E1: key_pressed 0 10
und
80E1: NOT key_pressed 0 11
00D6: if 0 = wenn nur eine Bedingung gestellt wird
00D6: if 1 = wenn 2 Bedingungen zutreffen müssen im Sinne von " UND "
00D6: if 2 = wenn 3 Bedingungen zutreffen müssen im Sinne von " UND "
00D6: if 21 = wenn 2 Bedingungen gestellt werden im Sinne von " ODER "
00D6: if 28 = wenn 9 Bedingungen gestellt werden im Sinne von " ODER "
00D6: if 1
80DF: NOT actor $PLAYER_ACTOR driving
00E1: key_pressed 0 10
004D: jump_if_false @Label
00D6: if 21
0154: actor $PLAYER_ACTOR in_zone 'MEAD'
0154: actor $PLAYER_ACTOR in_zone 'VE'
004D: jump_if_false @Label
00D6: if 3
0038: $$ONMISSION == 0 ;; integer values
8119: NOT car 1@ wrecked
82BF: NOT car 1@ sunk
80E1: NOT key_pressed 0 11
004D: jump_if_false @Label
00D6: if 25
00FE: actor $PLAYER_ACTOR 0 ()near_point 2402.664 -1712.32 14.20 radius 5.0 5.0 3.0
00FE: actor $PLAYER_ACTOR 0 ()near_point -1799.58 1202.5 24.10 radius 5.0 5.0 3.0
00FE: actor $PLAYER_ACTOR 0 ()near_point -368.3978 -1428.692 25.72 radius 5.0 5.0 3.0
00FE: actor $PLAYER_ACTOR 0 ()near_point 1579.101 -1635.873 13.56 radius 5.0 5.0 3.0
00FE: actor $PLAYER_ACTOR 0 ()near_point -2574.808 1151.744 55.70 radius 5.0 5.0 3.0
00FE: actor $PLAYER_ACTOR 0 ()near_point 2037.362 2724.411 10.82 radius 5.0 5.0 3.0
004D: jump_if_false @Label
00D6: if 5
80EC: NOT actor $PLAYER_ACTOR 0 ()near_point 2402.664 -1712.32 radius 10.5 10.5
80EC: NOT actor $PLAYER_ACTOR 0 ()near_point -1799.5 1202.5 radius 10.5 10.5
80EC: NOT actor $PLAYER_ACTOR 0 ()near_point -368.3978 -1428.692 radius 10.5 10.5
80EC: NOT actor $PLAYER_ACTOR 0 ()near_point 1579.101 -1635.873 radius 10.5 10.5
80EC: NOT actor $PLAYER_ACTOR 0 ()near_point -2574.808 1151.744 radius 10.5 10.5
80EC: NOT actor $PLAYER_ACTOR 0 ()near_point 2037.362 2724.411 radius 10.5 10.5
004D: jump_if_false @Label
0053: $PLAYER_CHAR = create_player #NULL at 920.22 2012.941 11.15
01F5: $PLAYER_ACTOR = create_emulated_actor_from_player $PLAYER_CHAR

