Missions-Scripte (EM4)

Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Dienste bereitzustellen und die Zugriffe auf unsere Website zu analysieren. Außerdem werden durch unsere Partner Informationen zu Ihrer Nutzung für soziale Medien, Werbung und Analysen erfasst. Weitere Informationen

  • Informationen zum Thema "Missions-Scripte" für EMERGENCY 4.
    Missionsscripte sind die „Drehbücher“ der Missionen. In diesen Scripten können neben Missionsbedingungen auch Ereignisse bestimmt werden, sowie Soundtracks abgespielt, CutScenes erstellt und komplexe Logiken (wenn Haus A brennt, stürzt in Haus A ein Balken ab, der Auto B zerstört usw.) angewendet werden.

    Basis-Klasse

    Am Anfang stand das Rad - und genau so muss man sich die erste wichtige Klasse eines Scripts vorstellen. Diese Basisklasse heißt „MissionScript“ und umschließt das gesamte Script. Zu beachten hierbei ist die genaue Rechtschreibung, denn C++ ist eine Sprache die CaseSensitive, also fallabhängig ist. Wenn ein Buchstabe nicht groß geschrieben wird, obwohl es so verlangt wird, dann führt dies zu Komplikationen und im schlimmsten (und wahrscheinlichsten) Fall zu einer Fehlermeldung und dem Absturz des Spiels.

    Quellcode

    1. object Mission01 : MissionScript
    2. {
    3. };
    • Mission01 ist der Name des Missionsscripts. Dieser kann frei gewählt werden, sollte aber sinnvoll und möglichst gleich dem Namen der Script-Datei sein.
    • MissionScript ist die schon erwähnte Basisklasse.
    Innerhalb dieses object (eine weitere Klasse von C++) können nun wichtige Funktionen und Methoden definiert werden. Bei allem was sich außerhalb dieses object befindet, spricht man von „Script-globalen Variablen“. Das sind zum Beispiel spezielle #Strings.
    Besonders sollte man auf geschweifte Klammern achten. Jede öffnende Klammer braucht auch eine schließende Klammer - das ist eine der wichtigsten Syntax-Regeln von C++. Mit den Code-Zeilen oben haben wir bereits ein erstes Script, welches uns für den Moment aber noch nicht weiter hilft.

    Konstruktor / Destruktor

    Wie der Name schon sagt, gibt es in Scripts einen aufbauenden und einen abbauenden Part

    Quellcode

    1. object Mission01 : MissionScript
    2. {
    3. Mission01()
    4. {}
    5. ~Mission01()
    6. {}
    7. };

    Missionsbedingungen

    Prinzipiell muss man zwischen den im Übersichtsfenster angezeigten Missionszielen und dem Status der Mission (laufend, abgeschlossen oder verloren) unterscheiden. Der Status der Mission wird durch die Funktion „GetMissionState()“ überprüft, die einen Wert aus der Aufzählung „MissionState“ zurückgeben muss. Mögliche „MissionState“-Werte sind „MISSION_RUNNING“ für eine laufende, „MISSION_SUCCEEDED“ für eine erfolgreich abgeschlossene und „MISSION_FAILED“ für eine fehlgeschlagene Mission. Sobald ein anderer Wert als „MISSION_RUNNING“ zurückgegeben wurde, wird die Mission sofort beendet.

    Missionsbedingungen werden mit der Funktion „Mission::AddObjective()“ hinzugefügt und gegebenenfalls mit „Mission::RemoveObjective()“ oder sogar „Mission::RemoveAllObjectives()“ wieder entfernt. Üblicherweise werden Missionsbedingungen in „void Start()“ hinzugefügt, dies kann aber auch an jeder anderen Stelle geschehen (etwa wenn sich die Einsatzlage während der Mission verändert). Mit „Mission::SetObjectiveAccomplished()“ wird festgelegt, ob eine Missionsbedingung erfüllt ist oder nicht. Es ist möglich, eine bereits erfüllte Bedingung wieder auf nicht erfüllt zu setzen, etwa wenn neue Brände ausbrechen. Eine sowohl für Missionsstatus als auch Missionsbedingungen nützliche Funktion ist „Mission::GetCounter()“, mit der sich vordefinierte Zähler, wie zum Beispiel die Zahl der Brennenden Häuser, abfragen lassen. Der Einfachheit halber kann man die Strings (OBJECTIVE_A z.B.) sofort mit dem späteren Text übersetzen, diese Methode wird auch im Beispiel angewandt.

    Quellcode

    1. const char OBJECTIVE_A[] = "Löschen Sie alle Brände!";
    2. const char OBJECTIVE_B[] = "Bringen Sie alle verletzten und toten Personen ins Krankenhaus";
    3. object Mission01 : MissionScript
    4. {
    5. Mission01()
    6. {}
    7. ~Mission01()
    8. {}
    9. void Start()
    10. {
    11. Mission::AddObjective(OBJECTIVE_A);
    12. Mission::SetObjectiveAccomplished(OBJECTIVE_A, false);
    13. Mission::AddObjective(OBJECTIVE_B);
    14. Mission::SetObjectiveAccomplished(OBJECTIVE_B, false);
    15. }
    16. MissionState GetMissionState()
    17. {
    18. if (Mission::GetCounter("Burning Objects") + Mission::GetCounter("Burning Houses") == 0)
    19. {
    20. if (!Mission::IsObjectiveAccomplished(OBJECTIVE_A))
    21. Mission::SetObjectiveAccomplished(OBJECTIVE_A, true);
    22. }
    23. else
    24. {
    25. if (Mission::IsObjectiveAccomplished(OBJECTIVE_A))
    26. Mission::SetObjectiveAccomplished(OBJECTIVE_A, false);
    27. }
    28. if (Mission::GetCounter("Injured Persons") + Mission::GetCounter("Dead Persons") == 0)
    29. {
    30. if (!Mission::IsObjectiveAccomplished(OBJECTIVE_B))
    31. Mission::SetObjectiveAccomplished(OBJECTIVE_B, true);
    32. }
    33. else
    34. {
    35. if (Mission::IsObjectiveAccomplished(OBJECTIVE_B))
    36. Mission::SetObjectiveAccomplished(OBJECTIVE_B, false);
    37. }
    38. return MISSION_RUNNING;
    39. }
    40. };
    Alles anzeigen
    • void Mission::AddObjective(const char *Name_); fügt eine neue Missionsbedingung hinzu.
    • void Mission::RemoveObjective(const char *Name_); löscht eine bestehende Missionsbedingung aus der Liste.
    • void Mission::RemoveAllObjectives(); löscht alle Missionsbedingungen.
    • bool Mission::HasObjective(const char *Name_); fragt ab, ob eine Missionsbedingung vorhanden ist.
    • void Mission::SetObjectiveAccomplished(const char *Name_, bool State_); lässt eine Missionsbedingung bei einem „true“ als grün, bei einem „false“ als rot darstellen.
    • bool Mission::IsObjectiveAccomplished(const char *Name_); ist als Test gedacht und „fragt nach“ ob die Bedingung erfüllt wurde.
    • int Mission::GetCounter(const char *Counter_); fragt den Wert eines Zählers ab.
    Um nachzufragen ob die Bedingung nicht erfüllt wurde, setzt man ein „!“ (Ausrufezeichen) an den Anfang.

    if (!Mission::IsObjectiveAccomplished(OBJECTIVE_A));

    Strings

    Strings sind Texte oder Namen die meist zusammengefügt in einer XML-Datei gespeichert werden. Diese Namen sind Sammlungen von vielen verschiedenen Dingen. Hier im Scriptbereich sind sie oft Namen von Objekten, Personen, Häusern, Triggern, virtuellen Objekten usw. Die Sammlung der Strings mit den oben genannten „const char*“ ermöglicht ein schnelles Ändern bestimmter Namen oder Werte und vereinfacht das Scripting. Außerdem behebt eine gute „const char*“-Sortierung einen unschönen Fehler im EMERGENCY 3, sowie EMERGENCY 4-Scriptinterpreter, der auftritt wenn das Script geschlossen wird und ein Name doppelt vorkommt. Siehe hier den Artikel Fehlermeldungen (EM4).

    Da alle „const char*“ global für ein Script gültig sind, müssen sie über die eben erstellte Basisklasse gesetzt werden. Strings werden in „const char STRING_NAME[] = „objektname“;“ angegeben. Wichtig hierbei ist wie immer der genaue Syntax!

    Quellcode

    1. const char NAME_CRASHCARS[] = "unfallfahrzeug";
    2. object Mission01 : MissionScript
    3. {
    4. Mission01()
    5. {}
    6. ~Mission01()
    7. {}
    8. };
    In diesem Beispiel heißt das Objekt auf der Missions-Map „unfallfahrzeug“.
    • NAME_CRASHCARS ist der Name, der im Script verwendet wird.
    • unfallfahrzeug ist der Name des Objekts auf der Map.


    Vordefinierte Methoden

    In Missions-Scripts gibt es vordefinierte Methoden, mit denen bestimmte Dinge direkt abgefragt werden können. Nachfolgend werden diese aufgezählt:

    void Start()

    Quellcode

    1. void Start()
    2. {
    3. }
    void Start()“ wird am Start der Mission einmalig aufgerufen. Perfekt für Definierung von Arrays am Anfang, die man über das gesamte Missions-Script benötigt.

    void Update()

    Quellcode

    1. void Update()
    2. {
    3. }
    void Update()“ wird jeden Tick einmal ausgeführt. Hier sollte man vorsichtig sein, welche Funkionen ausgeführt werden - unter Umständen verschlechtert sich die Performance massiv. Alternativ kann auch ein geloopter Intervall-Timer genutzt werden.

    void OnTrigger()

    Quellcode

    1. void OnTrigger(const char *Trigger, Actor *Collider)
    2. {
    3. }
    Wenn ein Trigger aktiviert wird, wird er hier aufgerufen. Mit „*Trigger“ kann man erfragen, welcher Trigger ausgeführt wurde und „*Collider“ ist der Actor, der mit dem Trigger kollidiert.

    Beispiel:

    Quellcode

    1. void OnTrigger(const char *Trigger, Actor *Collider)
    2. {
    3. if (Trigger->HasName("Trigger_01"))
    4. {
    5. if (Collider->GetType() == ACTOR_PERSON)
    6. {
    7. Person p(Collider);
    8. p.Kill();
    9. }
    10. }
    11. }
    Alles anzeigen
    void OnTimer()

    Quellcode

    1. <strong>void OnTimer(const char *TimerName, float TimeInSec)</strong>
    2. <strong>{</strong>
    3. <strong> switch(TimerName)</strong>
    4. <strong> {</strong>
    5. <strong> case "nameDesTimers":</strong>
    6. <strong> {</strong>
    7. <strong> // Anweisungen</strong>
    8. <strong> }</strong>
    9. <strong> break;</strong>
    10. <strong> }</strong>
    11. <strong>}</strong>
    Alles anzeigen
    Die Funktion „OnTimer()“ wird aufgerufen, wenn ein Timer geendet hat oder ein Intervalltimer an seine Intervallgrenze gekommen ist.„void OnTimer()“ geht einher mit „Mission::StartSingleTimer(„nameDesTimers“, 5.f);“ und „Mission::StartIntervalTimer(„nameDesTimers“, 5.f);“. Die Floats (5.f, Abkürzung von 5.0f) geben Sekunden an. Im SingleTimer geben die 5.f an, wie lange der Timer läuft bevor er terminiert wird und im IntervalTimer wird der Timer alle fünf Sekunden ausgeführt.

    MissionState GetMissionState()

    Quellcode

    1. MissionState GetMissionState()
    2. {
    3. return MISSION_RUNNING;
    4. }
    Im MissionState laufen normalerweise Counter, die z.B. überprüfen, ob noch Verletzte auf der Einsatzkarte sind oder noch Gebäude brennen. „GetMissionState()“ ist eine ähnliche Funktion wie „void Update()“ und wird ständig aufgerufen.

    Mögliche Rückgaben für diese Funktion sind:

    return MISSION_RUNNING;
    Gibt dem Spiel die Information aus, dass es keine Veränderung hinsichtlich Erfolg oder Misserfolg der Mission gibt.

    return MISSION_SUCCEEDED;
    Gibt dem Spiel die Information, dass wenn dieser Counter oder Bool zutrifft, dass Spiel erfolgreich war.

    return MISSION_FAILED;
    Gibt dem Spiel die Information, dass die Mission fehlgeschlagen ist, wenn dieser Counter oder Bool zutrifft.

    ActionCallbackResult OnPostAction()

    Quellcode

    1. ActionCallbackResult OnPostAction(const char *Action, ActionCallback* Data)
    2. {
    3. switch(Action)
    4. {
    5. case "EActionUse" :
    6. {
    7. }
    8. break;
    9. }
    10. return ACTION_CONTINUE;
    11. }
    Alles anzeigen
    Mit dieser recht komplexen Funktion kann in Erfahrung gebracht werden, welche Aktionen die Einsatzkräfte ausgeführt haben.Im Beispiel oben wird die Aktion „Benutzen“ ausgeführt. Eine genaue Liste aller möglichen Aktionsnamen sind unter EActions (EM4) zu finden. Hier werden auch die „ActionCallbackResults“ kurz erklärt. Es gibt verschiedene Möglichkeiten der CallbackResults.

    ActionCallbackResult OnPostAction()
    Wird aufgerufen, wenn eine Aktion ausgeführt und beendet wurde (z.B. ein Feuerwehrmann der den Stromkasten benutzt hat).

    ActionCallbackResult OnPreAction()
    Wird aufgerufen kurz bevor eine EAction ausgeführt wird (z.B. wenn der Feuerwehrmann erst zum Stromkasten laufen muss, dann wird PreAction in Bezug auf „EActionUse“ ausgeführt, nachdem der Feuerwehrmann sich zum Stromkasten dreht und bevor er den Stromkasten anfängt zu benutzen).

    ActionCallbackResult OnAbortAction()
    Wird nur ausgeführt, wenn der Spieler seine Einheiten während einer Aktion unterbricht.

    590 mal gelesen