Bei der letzten Lektion haben wir uns ja damit beschäftigt, eine einzelne SubMission laufend alle 30sek zu laden und die zerstörten Fahrzeuge mit Hilfe der Methode OnActorDestroyed() zu zählen.
Mit dieser Lektion werden wir jeweils eine von mehreren SubMissionen zufallsgesteuert auswählen und laden. Außerdem bauen wir eine kleine Falle für den Spieler ein, nämlich befreundete Fahrzeuge. Wird eines von diesen vom Spieler zerstört, gilt die Mission als Fehlschlag. Der Spieler wird lernen genauer hinzusehen und wir werden lernen wie man die Armeezugehörigkeit eines Actors feststellt, so haben beide was davon

. Außerdem zählen wir nicht mehr die Gesamtanzahl der Fahrzeuge sondern nur die der Feindlichen.
Also erstmal die Submissionen vorbereiten, die Hauptmission bleibt unverändert. Man öffnet einfach die SubMission vom letzten Mal, ändert das Fahrzeug und speichert die Mission dann unter anderem Namen. Hier mal als Beispiel unser befreundetes Fahrzeug:

Insgesamt habe ich neben der vom letzten Mal, 3 weitere Submissionen erstellt, davon eine mit einem befreundeten Fahrzeug.
Der Code zu dieser Beispielmission
using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;
public class Mission : AMission
{
enum MissionCondition {Neutral, Success, Failure}
MissionCondition AktuelleMissionCondition = MissionCondition.Neutral;
AiAircraft PlayerPlane;
const int MaxAnzahlFeindlicheFahrzeuge = 10;
int Zeitspanne = 4000;
int AnzahlFeindlicheFahrzeuge = 0;
int ZerstoerteZiele = 0;
public override void OnBattleStarted()
{
base.OnBattleStarted();
MissionNumberListener = -1;
PlayerPlane = (AiAircraft)GamePlay.gpPlayer().Place();
}
private void serverMessage(string msg)
{
GamePlay.gpLogServer (null, msg, new object [] {msg});
}
public override void OnTickGame()
{
if (AktuelleMissionCondition == MissionCondition.Neutral)
{
if (Time.tickCounter() % 1000 == 0 && (AnzahlFeindlicheFahrzeuge < MaxAnzahlFeindlicheFahrzeuge)) //ca. alle 30sek die Karte laden
{
Zeitspanne += 1000; // Bei jedem neuen Fahrzeug 30 sekunden zur GesamtZeit hinzu
Random ZufaelligesFahrzeug = new Random();
switch (ZufaelligesFahrzeug.Next(1,5))
{
case 1:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub1.mis");
break;
case 2:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub2.mis");
break;
case 3:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub3.mis");
break;
case 4:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub4.mis");
break;
default:
serverMessage("Mission nicht gefunden");
break;
}
}
if (Time.tickCounter() > Zeitspanne && AktuelleMissionCondition != MissionCondition.Success)
{
GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlFeindlicheFahrzeuge.ToString() + " Fahrzeugen zerstört" );
AktuelleMissionCondition = MissionCondition.Success;
}
}
}
public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
{
base.OnActorCreated(missionNumber, shortName, actor);
if (actor is AiGroundActor)
{
GamePlay.gpLogServer (null, "Fahrzeug: {0}\n", new object [] {(actor as AiGroundActor).InternalTypeName()});//Testmeldung
if (actor != null && actor.Army() == 1) // 1 steht für Rote Seite 2 würde für Blaue Seite stehen
{
AnzahlFeindlicheFahrzeuge++; // Wird nur gezählt wenn gegnerische Seite
}
Timeout(75, () => {
if (actor != null)
{
(actor as AiGroundActor).Destroy();
}
});
}
}
public override void OnActorDead(int missionNumber, string shortName, AiActor actor, System.Collections.Generic.List<DamagerScore> damages)
{
base.OnActorDead(missionNumber, shortName, actor, damages);
string KilledName;
KilledName = missionNumber.ToString()+ ":0_Chief";
if ((damages.Count != 0) && (PlayerPlane.Name().Equals(damages[0].initiator.Actor.Name())) && KilledName.Equals(actor.Name()))
{
if (actor != null && actor.Army() == 2) // 2 steht für Rote Seite 1 würde für Blaue Seite stehen
{
GamePlay.gpHUDLogCenter("Sie haben eines ihrer eigenen Fahrzeuge zerstört - <<<Mission fehlgeschlagen>>>" );
AktuelleMissionCondition = MissionCondition.Failure;
}
ZerstoerteZiele++;
}
}
}
Zuerst wieder die in der Mission global gütligen Variablen:
enum MissionCondition {Neutral, Success, Failure}
MissionCondition AktuelleMissionCondition = MissionCondition.Neutral;Da wir diesmal wieder eine Abbruchbedingung haben, benutzen wir die bereits aus einer früheren Lektion bekannte
Enumerationconst int MaxAnzahlFeindlicheFahrzeuge = 10; Da wir diesmal nur die Gesamtzahl der feindlichen Fahrzeuge berücksichtigen möchten, wurde ein aussagekräftigerer Variablenname gewählt.
int Zeitspanne = 4000; Mit dieser Variable berücksichtigen wir das das letzte Fahrzeug auch noch eine gewisse Zeit benötigt um den Weg zurückzulegen. Diese Variable wird später im Code für jede neu hinzugekommene SubMission um 1000 erhöht, da wir nicht wissen können, wieviele befreundete Fahrzeuge sich am Ende auf den Weg gemacht haben.
int AnzahlFeindlicheFahrzeuge = 0; Hier wird die aktuelle Zahl der gegnerischen Fahrzeuge gespeichert.
Der Rest ändert sich zur vorigen Lektion nicht.
OnBattleStarted() und
serverMessage(string msg) bleiben ebenfalls unverändert.
public override void OnTickGame()
{
if (AktuelleMissionCondition == MissionCondition.Neutral)
{
if (Time.tickCounter() % 1000 == 0 && (AnzahlFeindlicheFahrzeuge < MaxAnzahlFeindlicheFahrzeuge)) //ca. alle 30sek die Karte laden
{
Zeitspanne += 1000; // Bei jedem neuen Fahrzeug 30 sekunden zur GesamtZeit hinzu
Random ZufaelligesFahrzeug = new Random();
switch (ZufaelligesFahrzeug.Next(1,5))
{
case 1:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub1.mis");
break;
case 2:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub2.mis");
break;
case 3:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub3.mis");
break;
case 4:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub4.mis");
break;
default:
serverMessage("Mission nicht gefunden");
break;
}
}
if (Time.tickCounter() > Zeitspanne)
{
GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlFeindlicheFahrzeuge.ToString() + " Fahrzeugen zerstört" );
AktuelleMissionCondition = MissionCondition.Success;
}
}
}
Verändert wurde hingegen die Methode OnTickGame().
if (AktuelleMissionCondition == MissionCondition.Neutral) zuerst wird erst einmal abgefragt ob der Missionsstatus noch Neutral ist. Sollte also die Mission bereits ein Fehlschlag durch das zerstören eines befreundeten Ziels sein, werden keine neuen SubMissionen mehr geladen.
if (Time.tickCounter() % 1000 == 0 && (AnzahlFeindlicheFahrzeuge < MaxAnzahlFeindlicheFahrzeuge)) Die Abfrage wird ausgeführt wenn ca 30sek vergangen sind und die Anzahl der bereits gespawnten gegnerischen Fahrzeuge noch nicht die Maximale Anzahl erreicht hat.
Ist die If Abfrage also Wahr
wird zuerst die Zeitspanne um 1000 erhöht das
Zeitspanne += 1000 kann man auch als Zeitspanne = Zeitspanne + 1000 schreiben. Das += (genauso gibt es -=, *= und /=) ist eine Abkürzung für Schreibfaule (Ok nicht ganz

).
Random ZufaelligesFahrzeug = new Random() hiermit erzeugen wir ein neues Objekt mit dem Namen ZufaelligesFahrzeug aus der Klasse Random, diese Klasse wird uns durch .Net zu Verfügung gestellt und liefert uns Pseudo-Zufallszahlen. Pseudo heißt unter gleichen Bedingungen werden auch immer die gleichen Zahlen erzeugt. Aber für unseren Zweck reicht diese Art der Zufallszahlen aus (Hier findet sich
Näheres dazu.).
switch (ZufaelligesFahrzeug.Next(1,5))
{
case 1:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub1.mis");
break;
case 2:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub2.mis");
break;
case 3:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub3.mis");
break;
case 4:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub4.mis");
break;
default:
serverMessage("Mission nicht gefunden");
break;
}
Zum festlegen welche SubMission geladen wird verwenden wir eine switch .. case Anweisung. Dabei wird überprüft, ob der hinter switch aufgeführte Ausdruck, der entweder eine Ganzzahl oder eine Zeichenfolge sein muss, mit einer der hinter case angegebenen Konstanten übereinstimmt. Dabei wird der Reihe nach vorgegangen also zuerst wird überprüft ob der erste case zutrifft, dann ob der zweite etc. Man kann in C# keinen Bereich hinter dem case angeben, Dinge wie case 1..5: sind in C# nicht möglich. Trifft eine case zu, werden alle Anweisungen bis zum break; ausgeführt. Mit default kann man einen Zweig definieren der auf jeden Fall ausgeführt wird, wenn keine case zutrifft. So aber schauen wir uns die Switch - Anweisung unseres Scripts näher an.
switch (ZufaelligesFahrzeug.Next(1,5)) Mit ZufaelligesFahrzeug.Next(..,..) erzeugen wir mit Hilfe des Random Objektes eine ganzzahlige Zufallszahl. Der erste Wert in Klammern gibt den Minimal Wert an, dieser ist einschließlich, der zweite Wert gibt den Maximal Wert an, dieser ist ausschließlich, das bedeutet der Maximalwert wird durch den Zufallszahlengenerator nicht erzeugt, der Minimalwert hingegen schon. Möchte man zum Beispiel Zufallszahlen von 1 bis 10 müsste man .Next(1,11) angeben. In unserem Beispiel haben wir momentan 4 Missionen deswegen benötigen wir Zahlen von 1 bis 4, daher müssen wir bei .Next(1,5) festlegen. Wurde die Zufallszahl erzeugt, vergleicht die Switch-Anweisung alle Case-Fälle bis der Richtige gefunden wurde und lädt dann die dort angegebene SubMission. Hätten wir aus Versehen .Next(1,6) als Zufallszahlbereich angegeben, würde auch ab und zu die Zahl 5 erzeugt, dafür existiert aber kein Case-Fall, somit würde dann hier der default-Bereich aktiv und dieser gibt uns eine kurze Meldung in der Chatleiste aus.
Mit
if (Time.tickCounter() > Zeitspanne) überprüfen wir ob die Zeit bereits abgelaufen ist, wenn Ja geben wir eine "Gewinnmeldung" aus und werten mit
AktuelleMissionCondition = MissionCondition.Success; die Mission als Erfolg.
public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
{
base.OnActorCreated(missionNumber, shortName, actor);
if (actor is AiGroundActor)
{
GamePlay.gpLogServer (null, "Fahrzeug: {0}\n", new object [] {(actor as AiGroundActor).InternalTypeName()});//Testmeldung
if (actor != null && actor.Army() == 1) // 1 steht für Rote Seite 2 würde für Blaue Seite stehen
{
AnzahlFeindlicheFahrzeuge++; // Wird nur gezählt wenn gegnerische Seite
}
Timeout(75, () => {
if (actor != null)
{
(actor as AiGroundActor).Destroy();
}
});
}
}
Zur Methode OnActorCreated kamen folgende Anweisungen hinzu:
GamePlay.gpLogServer (null, "Fahrzeug: {0}\n", new object [] {(actor as AiGroundActor).InternalTypeName()});Mit Hilfe von .InternalTypeName() kann man den internen Spielnamen eines AiGroundActors abfragen bzw. ausgeben. Die Ausgabe sieht dann folgendermaßen aus:
if (actor != null && actor.Army() == 1) Mit der If-Anweisung wird abgefragt ob der Actor vorhanden ist und ob er der gegnerischen Armee angehört. Army() gibt einen Integer-Wert für die Armee zurück, hierbei steht 1 in Cliffs of Dover für die Rote Seite und 2 für die Blaue Seite. Gehört der Actor also zur Roten Seite wird AnzahlFeindlicheFahrzeuge um eins erhöht.
public override void OnActorDead(int missionNumber, string shortName, AiActor actor, System.Collections.Generic.List<DamagerScore> damages)
{
base.OnActorDead(missionNumber, shortName, actor, damages);
string KilledName;
KilledName = missionNumber.ToString()+ ":0_Chief";
if ((damages.Count != 0) && (PlayerPlane.Name().Equals(damages[0].initiator.Actor.Name())) && KilledName.Equals(actor.Name()))
{
if (actor != null && actor.Army() == 2) // 2 steht für Blaue Seite
{
GamePlay.gpHUDLogCenter("Sie haben eines ihrer eigenen Fahrzeuge zerstört - <<<Mission fehlgeschlagen>>>" );
AktuelleMissionCondition = MissionCondition.Failure;
}
ZerstoerteZiele++;
}
}
Im Vergleich zur Mission aus der letzten Lektion wurde diese If-Anweisung eingefügt:
if (actor != null && actor.Army() == 2) // 2 steht für Blaue Seite
{
GamePlay.gpHUDLogCenter("Sie haben eines ihrer eigenen Fahrzeuge zerstört - <<<Mission fehlgeschlagen>>>" );
AktuelleMissionCondition = MissionCondition.Failure;
}Sie fragt ab ob der Actor vorhanden ist und durch actor.Army() == 2 ob er zur blauen (also unserer) Seite gehört, ist dies der Fall wird eine Meldung ausgegeben und AktuelleMissionCondition auf Failure gesetzt, die Mission war also ein Fehlschlag.

Beim Testen der obigen Mission, wird einem relativ schnell auffallen das manche Fahrzeuge gar nicht zum zweiten Tarnnetz kommen, bevor sie verschwinden. Diese Fahrzeuge sind zu langsam und brauchen daher mehr Zeit bis sie ihr Ziel erreichen. Man könnte jetzt natürlich einfach die Zeit erhöhen, nach der die Fahrzeuge mit Destroy() entfernt werden. Aber dann gäbe es eventuell Staus am Ziel, die für den Spieler ein einfaches Ziel wären.
Um dies zu vermeiden, kann man auch eine Methode schreiben die Überprüft wo sich ein Actor gerade befindet und wenn dieser eine bestimmte Stelle erreicht wird er einfach aus dem Spiel entfernt. So eine Methode kann folgendermassen aussehen:
private void DestroyGroundActorAtPosition(double x, double y, double destroyRadius)
{
Point3d DestroyPos;
DestroyPos.x = x;
DestroyPos.y = y;
DestroyPos.z = 1;
for (int i = 0; i < MissionsCount; i++)
{
AiGroundActor curActor;
for (int j = 0; j < 10; j++)
{
string nameActor = i.ToString() + ":0_Chief" + j.ToString();
curActor = GamePlay.gpActorByName(nameActor) as AiGroundActor;
if (curActor != null)
{
if (curActor.Pos().distance(ref DestroyPos) < destroyRadius)
{
curActor.Destroy();
}
}
}
}
}
Schauen wir sie uns genauer an.
private void DestroyGroundActorAtPosition(double x, double y, double destroyRadius)Als Übergabewerte verlangt diese selbstgeschriebene Methode die X und Y Koordinate des Zielpunkts, sowie einen Radius um den Punkt, so das man die Entfernung zum Punkt angeben kann ab dem ein GroundActor entfernt werden kann.
Point3d DestroyPos; DestroyPos wird als Point3d deklariert, Point3d ist eine Interne Datenstruktur von Cliffs of Dover. Zugriff auf diese Struktur erhalten wir dadurch das wir das Namespace maddox.GP durch
using maddox.GP; am Beginn unseres Scripts laden.
Point3d enthält 3 double Werte, jeweils einen für x, y und z, also alle Angaben die eine Lokalisierung in einem 3Dimensionalen Raum nötig sind. DestroyPos wird mit .x = x und .y = y durch die Übergabewerte der Methode und durch .z =1 von uns festgelegt, den Z-Wert legen wir mit 1 fest da wir nur Bodenziele verschwinden lassen wollen.
Um sicherzustellen das auch alle Aktoren aus allen Missionen berücksichtigt werden kann man diese mit der Methode OnMissionLoaded() zählen, diese wird vom Spiel immer aufgerufen, wenn eine Mission neu geladen wurde. Zuerst müssen wir allerdings noch eine zusätzliche globale Variable einführen
int MissionsCount = 1; dieses MissionsCount wird dann in OnMissionLoaded jeweils um eins erhöht.
public override void OnMissionLoaded(int missionNumber)
{
base.OnMissionLoaded(missionNumber);
MissionsCount++;
}
So zurück zu DestroyGroundActorAtPosition dort wird mit Hilfe einer for - Schleife
for (int i = 0; i < MissionsCount; i++)die Missionsnummer hochgezählt, innerhalb der Schleife dann ein neuer AiGroundActor mit Namen curActor deklariert.
Anschliessend benötigen wir noch eine zweite Schleife
for (int j = 0; j < 10; j++), mit Hilfe der beiden Schleifen setzten wir dann alle momentan möglichen Actornamen durch string nameActor = i.ToString() + ":0_Chief" + j.ToString(); zusammen, dies ist nötig damit auch immer der richtige Actor "erwischt" wird. Mit
curActor = GamePlay.gpActorByName(nameActor) as AiGroundActor; weisen wir dann der Variablen curActor mit Hilfe von gpActorByName zu. Mit
if (curActor != null) überprüfem wir dann noch ob dieser Actor auch existiert und mit
if (curActor.Pos().distance(ref DestroyPos) < destroyRadius) stellen wir fest ob der Actor schon in der Nähe unseres Punktes ist. Mit curActor.Pos() bekommen wir die aktuelle Position unseres Actors als Point3d geliefert, von dieser Position können wir mit distance(ref DestroyPos) den Abstand zu unserem vorher angegebenen Punkt bestimmen lassen. distance ist eine Methode von Point3d und erwartet als Übergabe Wert eine Referenz auf den Zielpunkt. Ist der Actor nah genug am Zielpunkt wird der Actor mit Destroy() entfernt.
DestroyGroundActorAtPosition bringen wir am Ende der OnTick-Methode unter
DestroyGroundActorAtPosition(16761.94, 14817.99, 10.0); Die XY-Werte habe ich aus dem SubMission-File entnommen, der Wert 10.0 für die Entfernung vom Zielpunkt ist ausreichend.
DestroyGroundActorAtPosition werden wir in einer späteren Lektion erweitern, so dass wir mit dieser Methode später einen ganzen Bereich von Actors "säubern" können.
Hier noch das gesamte Script:
using System;
using System.Collections;
using maddox.game;
using maddox.game.world;
using maddox.GP;
using System.Collections.Generic;
public class Mission : AMission
{
enum MissionCondition {Neutral, Success, Failure}
MissionCondition AktuelleMissionCondition = MissionCondition.Neutral;
AiAircraft PlayerPlane;
const int MaxAnzahlFeindlicheFahrzeuge = 10;
int Zeitspanne = 4000; // Zeitspanne bis letztes Fahrzeug sicher verschwunden ist.
int AnzahlFeindlicheFahrzeuge = 0;
int ZerstoerteZiele = 0;
int MissionsCount = 1;
public override void OnMissionLoaded(int missionNumber)
{
base.OnMissionLoaded(missionNumber);
MissionsCount++;
}
public override void OnBattleStarted()
{
base.OnBattleStarted();
MissionNumberListener = -1;
PlayerPlane = (AiAircraft)GamePlay.gpPlayer().Place();
}
private void serverMessage(string msg)
{
GamePlay.gpLogServer (null, msg, new object [] {msg});
}
private void DestroyGroundActorAtPosition(double x, double y, double destroyRadius)
{
Point3d DestroyPos;
DestroyPos.x = x;
DestroyPos.y = y;
DestroyPos.z = 1;
for (int i = 0; i < MissionsCount; i++)
{
AiGroundActor curActor;
for (int j = 0; j < 10; j++)
{
string nameActor = i.ToString() + ":0_Chief" + j.ToString();
curActor = GamePlay.gpActorByName(nameActor) as AiGroundActor;
if (curActor != null)
{
if (curActor.Pos().distance(ref DestroyPos) < destroyRadius)
{
curActor.Destroy();
}
}
}
}
}
public override void OnTickGame()
{
if (AktuelleMissionCondition != MissionCondition.Failure && AktuelleMissionCondition != MissionCondition.Success)
{
if (Time.tickCounter() % 1000 == 0 && (AnzahlFeindlicheFahrzeuge < MaxAnzahlFeindlicheFahrzeuge)) //ca. alle 30sek die Karte laden
{
Zeitspanne += 1000; // Bei jedem neuen Fahrzeug 30 sekunden zur GesamtZeit hinzu
Random ZufaelligesFahrzeug = new Random();
switch (ZufaelligesFahrzeug.Next(1,5))
{
case 1:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub1.mis");
break;
case 2:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub2.mis");
break;
case 3:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub3.mis");
break;
case 4:
GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen6Sub4.mis");
break;
default:
serverMessage("Mission nicht gefunden");
break;
}
}
if (Time.tickCounter() > Zeitspanne && AktuelleMissionCondition != MissionCondition.Success)
{
GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlFeindlicheFahrzeuge.ToString() + " Fahrzeugen zerstört" );
AktuelleMissionCondition = MissionCondition.Success;
}
}
DestroyGroundActorAtPosition(16761.94, 14817.99, 10.0);
}
public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
{
base.OnActorCreated(missionNumber, shortName, actor);
if (actor is AiGroundActor)
{
GamePlay.gpLogServer (null, "Fahrzeug: {0}\n", new object [] {(actor as AiGroundActor).InternalTypeName()});//Testmeldung
if (actor != null && actor.Army() == 1) // 1 steht für Rote Seite 2 würde für Blaue Seite stehen
{
AnzahlFeindlicheFahrzeuge++; // Wird nur gezählt wenn gegnerische Seite
}
}
}
public override void OnActorDead(int missionNumber, string shortName, AiActor actor, System.Collections.Generic.List<DamagerScore> damages)
{
base.OnActorDead(missionNumber, shortName, actor, damages);
string KilledName;
KilledName = missionNumber.ToString()+ ":0_Chief";
if ((damages.Count != 0) && (PlayerPlane.Name().Equals(damages[0].initiator.Actor.Name())) && KilledName.Equals(actor.Name()))
{
if (actor != null && actor.Army() == 2) // 2 steht für Blaue Seite
{
GamePlay.gpHUDLogCenter("Sie haben eines ihrer eigenen Fahrzeuge zerstört - <<<Mission fehlgeschlagen>>>" );
AktuelleMissionCondition = MissionCondition.Failure;
}
ZerstoerteZiele++;
}
}
}
Für Fragen, Kritik und Anregungen bin ich wie immer offen.
Im Anhang finden sich die beiden Beispielmissionen.
[gelöscht durch Administrator]