Script-Aufbau und das Prinzip der Abfrage-Technik

  1. Der Thread ist das Basis-Script in der Main.scm wie in Cleo-Scripten
  2. Er wird in "create_thread", in Missionen oder Externscripten definiert
    oder vom Cleo-Programm gestartet, wenn Cleo eine Scriptdatei mit Endung .CS erkennt
  3. Mit Abfragen werden unterschiedliche Script-Teile für den Leseprozess freigeschaltet

  4. Script-Aufbau/kurz

  5. Unser Thread-Script bekommt einen Kopf (Header) und beginnt mit dem Eintrag der Cleo-Directive
  6. {$CLEO .cs}
  7. dann geben wir ihm sein erstes Label (Adresse).
  8. :Akt
  9. Dannach folgt die Namensgebung für den Thread mit:
  10. 03A4: name_thread 'AKT'
  11. und dann gehts los, einen code rein, der was bewirkt und end_thread und fertig
    probierts aus:
  12. {$CLEO .cs}
    :Akt
    03A4: name_thread 'AKT'
    08B2: toggle_thermal_vision 1
    0A93: end_custom_thread
  13. 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
  14. Jetzt möchten wir natürlich in die Normalansicht schalten können

    Dazu bauen wir eine Schleife(Loop) ein, mit Abfrage

  15. Eine Abfrage besteht aus mindestens 3 opcodes:
  16. 1. die IF-Variation Näheres zur IF-Variation, weiter unten
  17. 2. die eigentliche Frage
  18. 3. Die Sprunganweisung bei Verneinung

    1. if

    2. 0AB0: key_pressed 8

    3. 004D: jump_if_false @akt_01

  19. Abfragen nennen wir im script english CHECK
  20. 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.
  21. so setzen wir unser nächstes Script folgendermaßen zusammen:
  22. -Scriptkopf
  23. -1.LoopAdresse
  24. -wait code
  25. -Abfrage
  26. -Ereignis
  27. -Ende
  28. Unsere Abfrage soll bei einem bestimmten Tastendruck passiert werden, bei der "Backspace"-Taste
    sieht dann aus:
  29. {$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
  30. Der Leseprozess der Game-Engine "loopt" nun in einer Schleife, solange Backspace nicht gedrückt wird
  31. 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

  32. Im nächsten Kapitel werden wir die Bedeutung des Loops vertiefen und ihn zu Nutze machen, um das Script dauerhaft laufen zu lassen
  33. 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

  34. Es ist:
  35. if
    0256:   player $PLAYER_CHAR defined
    004D: jump_if_false @Akt_01
  36. 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:
  37. -Scriptkopf
  38. -1.Loop-Adresse
  39. -wait code
  40. -IF player_defined-Abfrage
  41. -Abfrage
  42. -Ereignis
  43. -Einfache Sprunganweisung zur 1.LoopAdresse
  44. {$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
  45. Immer wenn Backspace gedrückt wird, schaltet das Spiel in die Infrarotansicht, wartet dann 3 Sekunden
    und schaltet dann wieder in die Normalansicht
  46. 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

  47. Diesen Scriptaufbau empfehle ich euch in nächster Zukunft beizubehalten:
  48. -Scriptkopf
  49. -1.Loop-Adresse
  50. -wait code
  51. -IF player_defined-Abfrage
  52. -Abfrage
  53. -Ereignis
  54. -2.Loop-Adresse
  55. -wait code
  56. -IF player_defined-Abfrage
  57. -Abfrage
  58. -Einfache Sprunganweisung zur 1.LoopAdresse
  59. 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
  60. Ihr müsst euch nicht auf 2 Loops beschränken und es gibt auch andere Varianten sein Script aufzubauen
  61. Aber Ihr solltet es so machen, bis ihr richtig scripten könnt
  62. Bild zur Verdeutlichung wie Loop und Abfrage funktionieren
  63. Beispiel-Scripte:
  64. Screenshot
  65. Slowmotion
  66. First Person Camera

    Die Gestaltung der Abfrage ( IF - CHECK)
  1. Hier wird die Frage-Variation angegeben
  2. 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
  3. Für die meisten Frage-codes gibts auch den dazugehörigen Gegenteil-Frage-code
  4. Beispiel:
  5. 00E1: key_pressed 0 10 
    und
    80E1: NOT key_pressed 0 11
  6. Wir betrachten nur die Opcodes:
  7. 00E1: / 80E1:
  8. und erkennen daß die erste Ziffer bei normaler Frage 0 ist,
  9. und bei Nein- Frage 8
  10. Die Abfragegestaltung ist die schwierigste Thematik beim Scripten und wird gerne falsch gemacht.
  11. Besonders, wenn man BW MB-basierte Scripte vor sich hat.
  12. Das Prinzip mit den Zahlen funktioniert folgendermaßen
  13. 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 "
    
  14. if 8 und 28 sind maximal möglich
  15. Ein paar Beispiele:
  16. Abgefragt wird:
  17. Fährt CJ NICHT, UND wird die Taste 10 gedrückt ?
  18. 00D6: if  1
    80DF:   NOT   actor $PLAYER_ACTOR driving
    00E1:   key_pressed  0  10
    004D: jump_if_false @Label
  19. Abgefragt wird:
  20. Befindet sich CJ in der Zone Verdant Madows, ODER in der Zone Las Venturas ?
  21. 00D6: if  21
    0154:   actor $PLAYER_ACTOR in_zone 'MEAD'
    0154:   actor $PLAYER_ACTOR in_zone 'VE'
    004D: jump_if_false @Label
  22. Abgefragt wird:
  23. Ist KEINE Mission aktiv UND ist das Fahrzeug NICHT geschrottet
  24. UND NICHT gesunken UND wurde auch NICHT die Taste 11 gedrückt?
  25. 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
  26. Abgefragt wird:
  27. Ist CJ an einem der folgenden Orten ?
  28. ( Im Sinne von ODER )
  29. 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
  30. Abgefragt wird:
  31. Ist CJ an keinem der folgenden Orten ?
  32. ( Im Sinne von UND )
  33. 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


  34. Es ist vielleicht aufgefallen, daß der Variable-Name für die Player-Figur
  35. einmal $PLAYER_CHAR und ein anderesmal $PLAYER_ACTOR heißt.
  36. Der Player-Status wird zu Beginn der Main ins Leben gerufen
  37. 0053: $PLAYER_CHAR = create_player #NULL at  920.22  2012.941  11.15
  38. Es gibt codes, die nur für den Player anwendbar sind
  39. z.B.
  40. 01B4: set_player $PLAYER_CHAR frozen_state 1 (unfrozen)
  41. viele andere codes dagegen können allgemein für alle actor (peds) verwendet werden.
  42. Dazu wurde der Player einem actor gleichgesetzt.
  43. 01F5: $PLAYER_ACTOR = create_emulated_actor_from_player $PLAYER_CHAR


nothing
nothing