Ил-2 Штурмовик: Битва за Британию. Скрипты. Скрипты для чайников. Часть 4 - Загрузка подмиссий

Материал из АвиаВики
Перейти к: навигация, поиск
Автор: FG28_Kodiak
Ссылка: Перейти (перевод Google)

Скачать оригиналы миссий:

Samples.zip

Скачать примеры с Sukhoi.ru:

Samples.zip

В последнем уроке мы научились загружать подмиссии с заданным интервалом времени и учитывать уничтоженные объекты с помощью метода OnActorDestroyed().

В этом уроке мы научимся случайным образом выбирать и загружать подмиссии, а также подготовим небольшую ловушку для игрока в виде дружественной техники при уничтожении которой засчитывается поражение. Игроку предстоит быть более внимательным, а мы узнаем как задать принадлежность к армии для Actor . Кроме того в зачет уничтоженных целей будет идти только вражеская техника, в отличие от предыдущего урока.

Основную миссию оставляем без изменений, возьмем под-миссию из прошлого урока, поменяем в ней технику и сохраним под другим именем. Сделайте несколько таких подмиссий:

Sfdp4-1.jpg


Одну из подмиссий сделаем с дружественным транспортным средством (та самая ловушка).

Код скрипта:

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++;
        }
   }
}


В нашей миссии будет несколько глобальных переменных:

enum MissionCondition {Neutral, Success, Failure}
MissionCondition AktuelleMissionCondition = MissionCondition.Neutral;

Здесь мы задаем статус миссии, подробней можно посмотреть в одном из предыдцщих уроков.

const int MaxAnzahlFeindlicheFahrzeuge = 10; - общее количество вражеской техники.

int Zeitspanne = 4000; - эта переменная нужна для задания интервалов между появлением техники (загрузкой подмиссий).

int AnzahlFeindlicheFahrzeuge = 0; - переменная для хранения текущего количества вражеской техники.

OnBattleStarted() и serverMessage(string 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)     
       {
           GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlFeindlicheFahrzeuge.ToString() + " Fahrzeugen zerstört" );
           AktuelleMissionCondition = MissionCondition.Success;
       }
   }
}

Метод OnTickGame().

if (AktuelleMissionCondition == MissionCondition.Neutral) - проверяем статус миссии.

if (Time.tickCounter() % 1000 == 0 && (AnzahlFeindlicheFahrzeuge < MaxAnzahlFeindlicheFahrzeuge)) - проверяем, прошло ли заданное время и не исчерпан ли лимит загружаемых подмиссий (целей).

Если эти два условия выполняются выбираем случайным образом одну из подмиссий при помощи класса 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;
}
ZufaelligesFahrzeug.Next(1,5) - где 1 - минимальное значение, 5 - максимальное, которое никогда не выбирается генератором случ. чисел. default - все остальные варианты.

if (Time.tickCounter() > Zeitspanne) - проверяем, истекло ли время. Если да - выводим сообщение о победе и устанавливаем статус миссии "Выполнено" - 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(); 
           }
       });
   }
}

В метод OnActorCreated добавляем следующее:

GamePlay.gpLogServer (null, "Fahrzeug: {0}\n", new object [] {(actor as AiGroundActor).InternalTypeName()});

Используя метод .InternalTypeName() мы можем вывести на экран имена объектов AiGroundActorsиз игры:

Sfdp4-2.jpg


if (actor != null && actor.Army() == 1) - проверяем дружественный ли объект был уничтожен. Если условие верно статус миссии меняется "Провал". Если уничтожен враг - к счету уничтоженных целей прибавляется 1.

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++;
   }
}

Sfdp4-3.jpg


Тестируя миссию вы могли заметить, что некоторые машины едут медленнее и неукладываются в установленное время (то есть либо исчезнут по пути, либо будут скапливаться у тента). Чтобы избежать этого мы заставим их уничтожать по достижении определенной точки:

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();
               }
           }                             
       }
   }       
}


private void DestroyGroundActorAtPosition(double x, double y, double destroyRadius) - задаем координаты и радиус точки уничтожения.

Point3d DestroyPos; - DestroyPos is declared as a Point3D, Point3D is an internal data structure of Cliffs of Dover. Access to this structure, we get the result we maddox.GP the namespace by using maddox.GP; load at the beginning of our script. Point3d contains 3 double values, one each for x, y and z are, therefore, all the information a localization in a 3rd dimensional space is required. DestroyPos is with. X = x and. Y = y by the method of transfer values ​​and through. Z = 1 determined by us, the Z-value we define by 1 because we want to disappear leaving only ground targets. To ensure that all actors can be considered from all these missions you will be using the method OnMissionLoaded (), these count from the game called whenever a mission is reloaded. First, we still need to introduce an additional global variable int count = 1 mission, this mission will be increased in OnMissionLoaded count by one.

public override void OnMissionLoaded(int missionNumber)
{
   base.OnMissionLoaded(missionNumber);
   MissionsCount++;           
}   

So back to DestroyGroundActorAtPosition is there with the help of a for - loop

for (int i = 0; i < MissionsCount; i++) The mission number incremented inside the loop then declares a new name with AiGroundActor curActor. Then we need a second loop for (int j = 0; j <10; j + +), with the help of two loops, we set then all currently possible Actress name by string name actor = i.ToString () + ": 0_Chief" + j. ToString (); together, it is necessary to always "caught" the Actor is correct. With curActor GamePlay.gpActorByName = (name actor) as AiGroundActor, we then assign the variables with the help of curActor gpActorByName. With if (curActor! = Null) then we check whether this exists and if Actor (curActor.Pos (). Distance (ref DestroyPos) <destroy radius), we note whether the actor is already close to our point. With curActor.Pos () we get the current location of our Actors supplied as Point3D, from this position we can determine distance (ref DestroyPos) the distance to our previously specified point. distance is a method of Point3D and expected as the transfer value is a reference to the target point. Is the actor close enough to the target point with the Actor Destroy () will be removed.

DestroyGroundActorAtPosition we bring the end of the method under OnTick DestroyGroundActorAtPosition (16761.94, 14817.99, 10.0), the XY values ​​I've taken from the submission file, the value of 10.0 for the distance from the target point is sufficient. DestroyGroundActorAtPosition we will be expanding in a later lesson, so that we "clean up" after using this method for a whole range of Actors can.

Here's the whole 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++;
       }
   }
}


Для установки миссий-примеров скопируйте их в папку:
..\Documents\1C SoftClub\il-2 sturmovik cliffs of dover\missions\Single

Загрузка подмиссий (автор FG28_Kodiak)

Оригинальные темы см. на форуме sturmovik.de(перевод от Google):

Вернуться на страницу "Скрипты"