Angepinnt [H5]Liste nützlicher Scripte

    • [H5]Liste nützlicher Scripte

      Bekanntlich ist es mit dem Editor ziemlich schwierig spezielle Missionen zu erstellen, bei denen man z.B. eine Stadt gegen mehrere Invasionsarmeen verteidigen muss, die zu genau festgelegten Zeitpunkten auftauchen sollen. Oder man will ein Szenario erstellen, bei dem sich - zunächst feindliche - Städte erst anschließen, nachdem man bestimmte Aufträge erfüllt hat.

      Gerade für Einsteiger ist es deshalb sicher nützlich, ein paar Beispiele für funktionierende Scripts zu sehen und genau dafür ist dieser Thread gedacht. Wer also schon ein paar Scripts erstellt hat, kann die hier reinstellen …

      Bitte keine Fragen hier posten!
      Wenn ihr Fragen habt dann könnt ihr sie hier stellen!
      Die kausale Unabhängigkeit der Quarks von unserer Rede ist kein Merkmal der Realität (im Sinne des Gegenteils der Welt des Scheins), sondern sie ist einfach ein unbezweifelter Bestandteil unseres Redens über Quarks.
      Richard Rorty

      Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von Der Mentat () aus folgendem Grund: Link aktualisiert

    • Ressourceneinstellungen

      Das Einstellen der Startressourcen ist eines der einfachsten Scripts. Es besteht nur aus der Zeile

      SetPlayerStartResources( PLAYER_1, 10, 10, 10, 10, 10, 10, 10000);

      Die erste Variable gibt den Spieler an, der diese Startessourcen erhalten soll. Die folgenden Zahlen beschreiben die Menge von Holz, Stein, Quecksilber, Kristall, Schwefel, Edelsteinen und schließlich Gold. Wichtig ist das Semikolon am Ende des Befehls.
      Etwas schwieriger ist es, die Rohstoffe später um einen bestimmten Betrag zu erhöhen (siehe weiter unten).



      Regionen blockieren

      Oft ist es wichtig, dass ein gegnerischer Held, der in einer Stadt stationiert ist, diese nicht verlassen kann. Dazu erstellt man direkt vor dem Stadteingang eine Region, die hier den Namen "rbarierre" besitzen soll. (Wie man Regionen erstellt, kann man im Editor-Praxis-Handbuch finden, das man hier runterladen kann.) Ist der Gegner Spieler 2, dann verwendet man das Script

      SetRegionBlocked("rbarriere",not nil, PLAYER_2);

      Setzt man

      SetRegionBlocked("rbarriere",not nil, -1);

      so ist die Region für alle Spieler unpassierbar.

      SetRegionBlocked("rbarriere", nil, PLAYER_2);

      sollte die Blockierung wieder aufheben. (Habe ich aber noch nicht ausprobiert.)



      Regionale Auslöser

      Beispiel 1: Wettrennen

      Wir wollen erreichen, dass der erste Held, der die Region "rziel" erreicht, als Belohnung 10 Erzengel erhält. Dazu muss man eine Funktion definieren, die dann durch einen Trigger ausgelöst wird:

      function Ziel(heroname)
      AddHeroCreatures( heroname, CREATURE_ARCHANGEL, 10 );
      Trigger( REGION_ENTER_AND_STOP_TRIGGER, "rziel", nil);
      end;

      Trigger( REGION_ENTER_AND_STOP_TRIGGER, "rziel", "Ziel" );


      Erklärung

      In die erste Zeile schreibt man also "function" und dahinter einen beliebigen Namen (hier: Ziel, der Name sollte aber kein ö, ü oder so enthalten). Die Funkton hängt von der Variable "heroname" ab, in die das Script automatisch den Namen des Helden einsetzt, der die Region gerade betritt. In der zweiten Zeile formuliert man den gewünschten Befehl, der dem Held die Kreaturen gibt. Die IDs wie CREATURE_ARCHANGEL findet man über das Startmenü unter

      Ubisoft > Tribes of the East > Andere Handbücher > Handbuch zum Karteneditor > IDs für Scripte

      Der letzte Parameter (hier: 10) gibt die Anzahl der Kreaturen an. Die dritte Zeile bewirkt, dass die Funktion nur einmal ausgelöst wird, d.h. der Held kann nicht unbegrenzt Erzengel sammeln, indem er immer wieder die Region betritt. Der Befehl in der fünften Zeile bewirkt schließlich, dass beim Betreten der Region "rziel" die Funktion "Ziel" ausgeführt wird.


      Beispiel 2: Festgelegter Held

      Soll nur ein bestimmter Held die Erzengel erhalten können, so ersetzt man obiges Script durch

      function Ziel( heroname )
      if heroname == "Wulfstan" then
      AddHeroCreatures( heroname, CREATURE_ARCHANGEL, 10 );
      Trigger( REGION_ENTER_AND_STOP_TRIGGER, "rziel", nil );
      end;
      end;

      Trigger( REGION_ENTER_AND_STOP_TRIGGER, "rziel", "Ziel" );

      Um die IDs für Helden wie hier Wulfstan, (die nicht immer mit den Heldennamen im Spiel übereinstimmen) zu bekommen, wählt man den Held im Editor mit der Leertaste an; dort findet man den Namen unter "Settings".



      Temporäre Auslöser

      Mit der Funktion "GetDate(DAY)" kann man Ereignisse zu festgelegten Zeitpunkten eintreten lassen.

      function Zeit()
      if GetDate(DAY) == 3 then
      Invasion()
      end;
      end;

      Trigger( NEW_DAY_TRIGGER, "Zeit" );

      startet z.B. die (getrennt zu definierende) Funktion "Invasion()" am Tag 3.


      Beispiel: Steuereinnahmen

      Wir wollen erreichen, dass der Spieler 1 nach einem Monat durch Steuereinnahmen zusätzlich 10000 Gold bekommt. Da es keinen Befehl der Form AddResource gibt, muss man eine Variable "Res" einfügen, die die Menge das gerade vorhandenen Goldbestands angibt und zu dieser 10000 hinzufügen:

      Res = 0;

      function Steuer()
      if GetDate(DAY) == 29 then
      Res = GetPlayerResource( PLAYER_1, GOLD )+10000;
      sleep(2);
      SetPlayerResource( PLAYER_1, GOLD, Res);
      Trigger( NEW_DAY_TRIGGER, nil );
      end;
      end;

      Trigger( NEW_DAY_TRIGGER, "Steuer" );


      Erklärung

      In der ersten Zeile wird die Variable "Res" definiert und gleich 0 gesetzt. Mit der
      Funktion "GetPlayerResource( PLAYER_1, GOLD )" wird am Tag 29 bestimmt, wie viel Gold Spieler 1 besitzt und "Res" wird um 10000 höher festgesetzt. Der "sleep(2)"- Befehl soll sicherstellen, dass dieser Wert erst berechnet wird, bevor die nächsten Schritte im Script ausgeführt werden. Zeile 6 setzt den Goldbestand dann auf den berechneten Wert. Mit "Trigger( NEW_DAY_TRIGGER, nil );" wird die Möglichkeit von Zeitauslösern abgeschaltet; diese Funktion darf also erst in den "spätesten" Zeitauslöser eingebaut werden.



      Nachrichten-Boxen

      Um in einem Szenario Pläne, Aufträge oder allgemein die Handlung voranzutreiben, braucht man meistens Textboxen, die zu bestimmten Zeiten oder nach bestimmten Ereignissen auftauchen. Dazu verwendet man folgendes Script:

      function Warnung()
      if GetDate(DAY) == 2 then
      MessageBox("Maps/SingleMissions/Gantrithor/Warnung.txt" );
      Trigger( NEW_DAY_TRIGGER, nil );
      end;
      end;

      Trigger( NEW_DAY_TRIGGER, "Warnung" );

      Es wird dann am Tag 2 die Textnachricht, die unter "Warnung.text" im Ordner

      HeroesV\Editor\H5MMods\<Kartenname>\Maps\SingleMissions\<Kartenname>\

      abgespeichert ist, angezeigt. Den Pfad ab "Maps" schreibt man in die Klammer hinter "MessageBox". Die Nachricht muss mit Unicode-Codierung abgespeichert werden, damit das Ganze funktioniert. Eine noch genauere Beschreibung, wie diese Textdateien erstellt werden können, gibt euch makrise.


      So, das reicht für heute. Beim nächsten mal erklär ich euch, wie man Gebäude umfunktionieren kann und Invasionen programmiert. :D
      Die kausale Unabhängigkeit der Quarks von unserer Rede ist kein Merkmal der Realität (im Sinne des Gegenteils der Welt des Scheins), sondern sie ist einfach ein unbezweifelter Bestandteil unseres Redens über Quarks.
      Richard Rorty

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von Der Mentat ()

    • Gebäude umfunktionieren

      Beispiel 1: Magischer Schrein für Level 5-Zauber

      Ziel ist es, ein Gebäude zu erstellen, das jedem vorbeikommenden Held einen Level 5-Zauber, genauer den Zauber "Phönix beschwören" lehrt. Wir modifizieren dafür eine "School of Magic", also das Gebäude, in dem die Helden normalerweise entweder Zauberkraft oder Wissen steigern können.
      Wenn man die "School of Magic" anwählt, sieht man auf der linken Seite des Bildschirms eine Liste mit den "Properties" (ich glaube beim ersten Öffnen des Editors wir diese Liste nicht automatisch angezeigt; man muss dann evtl. erst auf den Menüpunkt View > Map Properties Tree gehen). Wir fügen unter Name den Text Magierturm ein; auf die Bezeichnung kann man sich dann im Script beziehen. Letzteres sieht dann so aus:

      function Turm(heroname)
      if GetHeroSkillMastery( heroname, 12) ==3 then
      TeachHeroSpell( heroname, 235);
      MessageBox("Maps/SingleMissions/Test/Phoenix.txt" );
      else
      MessageBox("Maps/SingleMissions/Test/Skill.txt" );
      end;
      end;

      SetObjectEnabled('Magierturm',false);
      Trigger(OBJECT_TOUCH_TRIGGER, 'Magierturm', 'Turm');


      Erklärung

      Zuerst definieren wir die Funktion, die ausgeführt werden soll, wenn ein Held das Gebäude betritt. Dabei wird in der zweiten Zeile überprüft, ob der Held meisteliche Beschwörungsmagie beherrscht: Die 12 ist die ID für beschwörende Magie und 3 steht für meisterliche Stufe. Mit dem Befehl TeachHeroSpell erhält der Held einen Zauber, in diesem Fall "Phönix beschwören" mit der ID 235. Die parallel erscheinende Messagebox enthält die Nachricht, dass der Held den Zauber gelernt hat. Hat der Held keine meisterliche Beschwörungsmagie, dann greift der "else"- Absschnitt mit der Textbox-Information, dass dem Held der erforderliche Skill fehlt.

      Mit "SetObjectEnabled('Magierturm',false);" erreicht man, dass die übliche Funktion einer "School of Magic" - also die Wahl zwischen Zauberkraft und Wissen - abgeschaltet wird, so dass man sie mit Hilfe des nachfolgenden Triggers durch die Funktion "Turm" ersetzen kann.


      Beispiel 2: Dunkelmagie bei einer Hexe lernen

      Wir wollen, dass jeder Held bei einer bestimmten Hexenhütte die Fähigkeit Dunkelmagie lernen kann. Da Hexenhütten auf das Anwählen mit der Leertaste nicht reagieren, muss man dies über ein Script steuern. Der Fall ist allerdings schwieriger als dass obige Beispiel, denn man muss sicherstellen, dass ein Held die Hexe nicht mehrmals besuchen kann und so nacheinender den Skill von einfach auf geübt und dann auf meisterlich steigert.
      Zuerst muss man der Hexe wieder einen Namen geben. In diesem Fall nennen wir das Gebäude einfach Huette. Im Script schreibt man

      visitedHeroes={}

      function Hekate(heroname)
      if not visitedHeroes[heroname]==1 then
      GiveHeroSkill( heroname, 10)
      visitedHeroes[heroname]=1;
      sleep(2);
      if HasHeroSkill( heroname, 10) == true then
      MessageBox("Maps/SingleMissions/Test/HDunkel.txt" );
      else
      MessageBox("Maps/SingleMissions/Test/HSkill.txt" );
      end;
      else
      MessageBox("Maps/SingleMissions/Test/HBesucht.txt" );
      end;
      end;

      SetObjectEnabled('Huette',false);
      Trigger(OBJECT_TOUCH_TRIGGER, 'Huette', 'Hekate');


      Erklärung

      Mit "visitedHeroes" definiert man eine Variable, in die dann die Heldennamen eingetragen werden, die die Hexe Hekate schon besucht haben. Ist das der Fall, wird in Zeile 3 eine 1 ausgegeben, falls nicht, erhält der Held in Zeile 4 über "GiveHeroSkill" die Fähigkeit Dunkelmagie mit der ID 10. Anschließend wird der Held in die visitedHeroes-Liste eingetragen.

      Eine Veränderung tritt natürlich nur dann ein, wenn der Held noch Dunkelmagie lernen kann und nicht schon sechs andere Primärskills besitzt. Deshalb soll mit "HasHeroSkill" geprüft werden, ob das Erlernen auch erfolgreich war. Der sleep(2)-Befehl davor hat den Zweck, dass der Held sozusagen genug Zeit hat den Skill zu lernen, bevor er abgefragt wird. Besitzt der Held nun Dunkelmagie, wird die Erfolgsmeldung "HDunkel.txt" angezeigt, wenn er dagegen schon zu viele andere Fähigkeiten hat, erhält er die negative Meldung "HSkill.txt".

      Der zweite else-Teil bezieht sich schließlich auf den Fall, dass der Held schon zum zweiten Mal bei Hekate auftaucht; er bekommt dann nur die Nachricht "HBesucht.txt".
      (Nicht abgedeckt wird die Situation, das deshalb nichts gelernt werden kann, weil der Held schon den meisterhaften Grad in Dunkelmagie beherrscht. Über GetHeroSkillMastery kann man dazu ggf. noch einen weiteren if-Abschnitt einfügen.)

      Die Grundideen für dieses Script stammen übrigens wieder von makrise, genauer von seinem library-Script.
      Die kausale Unabhängigkeit der Quarks von unserer Rede ist kein Merkmal der Realität (im Sinne des Gegenteils der Welt des Scheins), sondern sie ist einfach ein unbezweifelter Bestandteil unseres Redens über Quarks.
      Richard Rorty

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Der Mentat ()

    • Manuelle Zieleinstellungen

      Bei Szenarios möchte man normalerweise komplexere Ziele erstellen als die Standardeinstellung "Alle Gegner besiegen". Mit Hilfe des Map-Properties-Tree hat man unter Objectives die Auswahl zwischen einer ganzen Menge anderer Ziele, die man auch ohne zusätzliche Scripts verwenden kann. Wie das ganau geht, wird ausführlich im Theorie-Handbuch des Editors beschrieben. (Das befindet sich im Startmenü unter Ubisoft > Tribes of the East > Andere Handbücher > Handbuch zum Karteneditor > Editor-Theorie.) Ein gutes Beispiel dazu mit Graphiken gibt's auch in diesem Thread von Lya.

      Bei der Bearbeitung eines Ziels im Properties-Tree kann man unter "Kind" auch "OBJECTIVE_KIND_MANUAL" wählen. Wir verwenden diese Einstellung, um folgendes Ziel zu erstellen: Der Spieler soll innerhalb von zwei Wochen die Stadt "Minas Morgul" einnehmen, sonst ist das Ziel verfehlt.

      Dafür wählen wir zuerst die gewünschte Stadt an und geben ihr (im Properties-Tree der Stadt) den Namen MinasMorgul. Wir gehen wieder zurück zum Map-Properties-Tree (z.B. über View in der Menüleiste) und geben dem Ziel den Namen Prim1. Für die Punkte "Caption" und "Description" kann man einen passenden Text formulieren.
      Nun bearbeiten wir das Script:

      function Morgul( oldowner, newowner )
      if newowner == PLAYER_1 then
      SetObjectiveState( 'Prim1', OBJECTIVE_COMPLETED );
      end;
      end;

      function NewDay()
      if ( GetDate(DAY) == 15 ) and ( GetObjectiveState( 'Prim1' ) == OBJECTIVE_ACTIVE ) then
      SetObjectiveState( 'Prim1', OBJECTIVE_FAILED );
      end;
      end;

      Trigger( OBJECT_CAPTURE_TRIGGER, "MinasMorgul", "Morgul" );
      Trigger( NEW_DAY_TRIGGER, "NewDay" );


      Erklärung

      Um zu überprüfen, wann die Stadt Minas Morgul erobert wird, benutzt man den
      OBJECT_CAPTURE_TRIGGER. Dieser gibt immer auch den alten und neuen Besitzer aus, so dass man diese Werte als Variablen in der zugehörigen Funktion verwenden kann (so wie z.B. der REGION_ENTER_AND_STOP_TRIGGER immer den Heldennamen ausgibt, der gerade die Region betritt).

      In der zweiten Zeile wird getestet, ob der neue Besitzer der Spieler 1 (also der menschliche Spieler) ist, dann wird mit "SetObjectiveState" das Ziel Prim1 auf "erfüllt" gesetzt. Diesen Teil der Zieleinstellungen hätte man auch ohne Script über den Properties-Tree erreichen können, indem man unter Kind OBJECTIVE_KIND_CAPTURE_OBJECT wählt. Wir fordern allerdings noch die zusätzliche Bedingung, dass der Spieler für diesen Auftrag nur zwei Wochen Zeit hat. Dafür braucht man die zweite Funktion.

      NewDay() untersucht, ob das Ziel Prim1 am Tag 15 noch aktiv, also noch nicht abgeschlossen ist. In disem Fall wertet es das Ziel als verfehlt. In den letzten beiden Zeilen stehen noch die Trigger. Der OBJECT_CAPTURE_TRIGGER ordnet dem "Objekt" MinasMorgul die Funktion Morgul zu.



      Objektbesitzer ändern

      Mit "SetObjectOwner" kann man einem Objekt, z.B.einer Stadt einen neuen Besitzer zuteilen. In diesem Beispiel geben wir der Stadt in ihrem Properties-Tree (siehe oben) den Namen MinasTirith. Bei einem Zeitauslöser sieht das Ganze so aus:

      function NewDay()
      if GetDate(DAY) == 9 then
      SetObjectOwner( 'MinasTirith', 0 );
      SetObjectOwner( 'MinasTirith', 5 );
      end;
      end;

      Trigger( NEW_DAY_TRIGGER, "NewDay" );

      Die Stadt wird dann am Tag 9 an Spieler 5 übergeben. In Zeile 3 wird dabei die Stadt zuerst neutral gemacht. Manchmal funktioniert so ein Script auch ohne diese Zeile, manchmal braucht man diesen Zwischenschritt selstamerweise aber auch.

      Statt dem Zeitauslöser kann man den Befehl auch in eine manuelle Zieleinstellung schreiben, so dass sich die Stadt anschließt, nachdem der Spieler dieses Ziel erreicht hat. Das Script aus dem obigen Abschnitt könnte man z.B. erweitern zu

      function Morgul( oldowner, newowner )
      if newowner == PLAYER_1 then
      SetObjectiveState( 'Prim1', OBJECTIVE_COMPLETED );
      SetObjectOwner( 'MinasTirith', 0 );
      SetObjectOwner( 'MinasTirith', 1 );
      end;
      end;

      Trigger( OBJECT_CAPTURE_TRIGGER, "MinasMorgul", "Morgul");



      Neuen Helden einfügen

      Man kann für jeden Spieler einzelne Helden in eine Reserveliste eintragen und die dann zu einem bestimmten Zeitpunkt im Spiel auftauchen lassen. Die Liste findet man in den Map Properties unter Player Properties. Dort wählt man einen Spieler aus und klickt dann bei der „Reserve Heroes List“ auf „Add“. Auch Armee, Fähigkeiten des Helden usw. können hier eingestellt werden.

      Um den Held im Spiel auftauchen zu lassen, verwendet man die Funktion „DeployReserveHero”:

      function NewDay()
      if GetDate(DAY) == 2 then
      DeployReserveHero( "Deleb", 85,80, GROUND);
      end;
      end;

      Trigger( NEW_DAY_TRIGGER, "NewDay" );

      "DeployReserveHero" hängt von vier Variablen ab: Die erste ist der Scriptname des Helden aus der Reserveliste, der auftauchen soll (hier: Deleb); die beiden folgenden Zahlen stehen für die Eintrittskoordinaten und im letzten Feld wählt man je nach Ebene GROUND oder UNDERGROUND.

      Soll der eingetroffene Held eine bestimmte Stadt angreifen, so sollte man das eigentlich über den Befehl

      SetAIHeroAttractor("MinasTirith", "Deleb", 2)

      steuern können. Bei mir hat das leider nicht funktioniert, was entweder an einem Fehler in meinem Script liegt oder daran, dass diese Priorisierung zu schwach ist. Eine sicherere Möglichkeit, den Helden zu einem Angriff zu veranlassen, ist es den Held einem Spieler zuzuordnen, der genau eine Stadt und keine weiteren Helden hat, wenn das von der Karte her möglich ist. Sobald der neue Held auftaucht, nimmt man ihm mit „SetObjectOwner“ die Stadt weg. Der Held hat dann nur sieben Tage Zeit, eine neue Stadt zu erobern und wird praktisch sofort – wie gewünscht – die nächstgelegene Stadt angreifen, auch wenn seine Armee eigentlich unterlegen ist.
      Die kausale Unabhängigkeit der Quarks von unserer Rede ist kein Merkmal der Realität (im Sinne des Gegenteils der Welt des Scheins), sondern sie ist einfach ein unbezweifelter Bestandteil unseres Redens über Quarks.
      Richard Rorty

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von Der Mentat ()

    • Invasionen starten

      Nachdem die obige Idee für die Programmierung eines Angriffs auf eine Stadt doch nicht so gut funktioniert, habe ich noch eine zuverlässigere Alternative gefunden: Mit dem Befehl "MoveHero( "Jazaz", 21, 163 )" kann man einen Helden (hier:Jazaz) an bestimmte Koordinaten auf der Karte schicken. Das Ziel muss nicht innerhalb eines Tagesmarsches erreichbar sein, das Script funktioniert auch über mehrere Züge:

      function NewDay()
      if GetDate(DAY) == 2 then
      DeployReserveHero( "Jazaz", 5,122, GROUND);
      sleep(2);
      EnableHeroAI( "Jazaz", nil );
      sleep(2);
      MoveHero( "Jazaz", 21, 163 );
      end;
      if GetDate(DAY) == 4 then
      if IsHeroAlive("Jazaz") == true then
      EnableHeroAI( "Jazaz", not nil );
      end;
      end;
      end;

      Trigger( NEW_DAY_TRIGGER, "NewDay" );


      Erklärung

      Die Invasion wird über einen Zeitauslöser initiiert. In der dritten Zeile wird der Held auf der Karte eingefügt (vgl. den letzten Abschnitt). Die darauffolgende sleep-Zeile sollte ausreichend Zeit geben, um diese Aktion auszuführen. Bevor man "MoveHero" verwenden kann, muss die KI-Kontrolle über den Held mit "EnableHeroAI( "Jazaz", nil )" ausgeschaltet werden.

      Als Zielkoordinaten, hier (21,163), kann man den Eingang einer Stadt wählen; das ist dann gleichbedeutend mit einem Angriff auf die Stadt. Auf meiner Karte brauchte der Held zwei Tagesreisen bis zum Ziel. Deshalb wird am Tag 4 überprüft, ob er noch am Leben ist, er also die Stadt erobert hat. Wenn das zutrifft, gibt "IsHeroAlive("Jazaz")" den Wert "true" aus und man kann in der nächsten Zeile die KI-Steuerung wieder aktivieren.

      Ein Held, der mit MoveHero gesteuert wird greift auch neutrale Kreaturen (und vermutlich feindliche Helden), die den Weg versperren, an. Nach der offiziellen Beschreibung des Scripts kann er aber keine Portale durchqueren oder Schiffe benutzen.
      Die kausale Unabhängigkeit der Quarks von unserer Rede ist kein Merkmal der Realität (im Sinne des Gegenteils der Welt des Scheins), sondern sie ist einfach ein unbezweifelter Bestandteil unseres Redens über Quarks.
      Richard Rorty

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Der Mentat ()

    • Effekte erstellen


      Beispiel 1: Ortsgebundenener Effekt

      Die Effekte von Zaubersprüchen aus den Kämpfen können auch auf der Abenteuerkarte eingesetzt werden. In diesem Beispiel nützt ein mächtiger Dämonenheld den Armageddonzauber, um seine Ankunft anzukündigen; d.h. zuerst wird der Effekt abgespielt und dann der Held über DeployReserveHero eingefügt. Daneben werden noch ein paar Kamerafunktionen eingebaut, damit der Spieler den Effekt auch sieht: ;)

      function NewDay()
      if GetDate(DAY) == 2 then
      OpenCircleFog(52, 25, 0, 7 , PLAYER_1);
      MoveCamera( 52, 25 , 0, 25, 0, 5.24, 0, 1, 1 );
      sleep (10);
      PlayVisualEffect( "/Effects/_(Effect)/Spells/Armageddon.xdb#xpointer(/Effect)", "", "stop1", 52, 25, 0, 0, 0 );
      sleep(30);
      DeployReserveHero("Deleb",51, 24,0);
      end;
      end;

      Trigger( NEW_DAY_TRIGGER, "NewDay" );


      Erklärung

      In Zeile 3 lösen wir den Nebel in der Region auf, in der der neue Held auftauchen soll. Die ersten beiden Zahlen geben die Ortskoordinaten an, 0 steht für GROUND und die vierte Zahl ist der Radius des Kreises, der sichtbar wird. In der nächsten Zeile wird die Kamera an die gleiche Position bewegt; im Unterschied zu oben steht hier die vierte Zahl für den Zoom und die beiden folgenden für die Rotation (genauer kann man das in der PDF-Datei für Scripts nachlesen).
      Die Wartefunktion sleep(10) stellt sicher, dass der Effekt erst beginnt, wenn die Kamera die entsprechende Position erreicht hat.
      Mit PlayVisualEffect starten wir dann logischerweise den Effekt. Der Pfad ist immer der gleiche, man braucht nur die Spells zu variieren. Zauberspruchnamen, die aus mehreren Wörtern bestehen werden zusammengeschrieben, also z.B. AnimateDead bzw. der gesamte Pfad:

      "/Effects/_(Effect)/Spells/AnimateDead.xdb#xpointer(/Effect)"

      Die folgende Variable wird bei ortsgebundenen Effekten leergelassen (""), die dritte ("stop1") ist normalerweise auch überflüssig, und dient nur dazu, dass man den Effekt einen Namen gibt, durch den man ihn zwischendurch abbrechen könnte (mit StopVisualEffects ("stop1"); ). (52,25) sind wieder die Ortskoordinaten.
      Mit DeployReserveHero fügen wir schließlich den Held ein.


      Beispiel 2: Objektgebundener Effekt

      Das gleiche Prinzip umgekehrt: Wir lassen einen Held mit CelestialShield explodieren: :devil:

      function NewDay()
      if GetDate(DAY) == 2 then
      O_x,O_y,O_z = GetObjectPosition("Deleb");
      MoveCamera(O_x,O_y,O_z,50,1,0,0,0);
      sleep(10);
      PlayVisualEffect( "/Effects/_(Effect)/Spells/CelestialShield.xdb#xpointer(/Effect)", "Deleb", "stop2", 0, 0, 0, 0, 0 );
      sleep(25);
      RemoveObject("Deleb");
      end;
      end;

      Trigger( NEW_DAY_TRIGGER, "NewDay" );


      Erklärung

      Wir müssen zuerst bestimmen, an welchem Ort sich der Held "Deleb" befindet. GetObjectPosition gibt diese Koordinaten aus und wir bezeichnen sie mit O_x, O_y und O_z. MoveCamera funktioniert wie oben.
      Bei PlayVisualEffect kann man entweder wie im ersten Beispiel die Koordinaten einsetzen (also O_x, O_y, O_z) oder wie hier in der zweiten Variable den Heldennamen eingeben; der Effekt wird dann direkt über ihm ausgelöst.
      RemoveObject entfernt den Held. Leider scheint die Remove-Funktion aber nicht bei festen Kartenobjekten, z.B. Gebäuden zu wirken.



      Question Box

      Die QuestionBox funktioniert eigentlich genauso wie die MessageBox, nur hat man hier zwei Auswahlmöglichkeiten, nämlich OK oder Abbrechen und je nach Wahl können verschiedene Funktionen ausgelöst werden. In diesem Beispiel bietet der Held "Aberrar" an, sich dem Spieler anzuschließen. Lehnt man ab, d.h. drückt man Abbrechen, dann greift er stattdessen an:

      function Solveig(heroname)
      QuestionBox("Maps/SingleMissions/Test/SolveigQ.txt", "OK", "Abbrechen");
      Trigger( REGION_ENTER_AND_STOP_TRIGGER, "rsolveig", nil );
      end;

      function OK()
      SetObjectOwner("Aberrar", PLAYER_1);
      end;

      function Abbrechen()
      MoveHeroRealTime("Aberrar",167,66);
      end;

      Trigger( REGION_ENTER_AND_STOP_TRIGGER, "rsolveig", "Solveig" );


      Erklärung

      Die QuestionBox enthält natürlich einen Text, den man genauso eingibt wie bei der MessageBox (siehe oben unter Nachrichten-Boxen). Nach dem Pfad kann man zwei Funktionsnamen eingeben, hier habe ich sie einfach "OK" und "Abbrechen" genannt.
      Wird die Funktion "OK" ausgelöst, so wechselt der Held zu Spieler 1 durch SetObjectOwner. Bei "Abbrechen" wird das Spiel kurz geblockt, während sich der feindliche Held zu den Koordinaten (167,66) bewegt. Diese sind exakt neben der (nur 1 Feld großen) Region "rsolveig", so dass automatisch der Kampfmodus gestartet wird.
      Die kausale Unabhängigkeit der Quarks von unserer Rede ist kein Merkmal der Realität (im Sinne des Gegenteils der Welt des Scheins), sondern sie ist einfach ein unbezweifelter Bestandteil unseres Redens über Quarks.
      Richard Rorty

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von Der Mentat ()