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

Материал из АвиаВики
Перейти к: навигация, поиск
(Загрузка подмиссий (автор FG28_Kodiak))
 
(не показано 12 промежуточных версии ещё одного участника)
Строка 2: Строка 2:
 
:'''Ссылка:''' [http://translate.googleusercontent.com/translate_c?hl=en&rurl=translate.google.com&sl=de&tl=en&twu=1&u=http://forum.sturmovik.de/index.php/topic,721.0.html%3FPHPSESSID%3Dac198c6ea43133020cb39e5f138fa85a&usg=ALkJrhiUPU7IvyTBPlLaOn7JmUlwfZx2pw Перейти (перевод Google)]
 
:'''Ссылка:''' [http://translate.googleusercontent.com/translate_c?hl=en&rurl=translate.google.com&sl=de&tl=en&twu=1&u=http://forum.sturmovik.de/index.php/topic,721.0.html%3FPHPSESSID%3Dac198c6ea43133020cb39e5f138fa85a&usg=ALkJrhiUPU7IvyTBPlLaOn7JmUlwfZx2pw Перейти (перевод Google)]
  
 +
Скачать оригиналы миссий:
 +
:[http://forum.sturmovik.de/index.php?action=dlattach;topic=721.0;attach=218 Samples.zip]
 +
Скачать примеры с Sukhoi.ru:
 +
:[http://www.sukhoi.ru/forum/attachment.php?attachmentid=142554&d=1318334365 Samples.zip]
  
  
 +
В предыдущих двух миссиях мы загружали под-миссии после начала миссии-хоста. В этой части мы научимся контролировать загрузку миссиий при помощи метода '''public virtual void OnTickGame ()'''
  
 +
'''public override void OnTickGame()'''
  
 +
Метод '''OnTickGame()''' направляет вызовы с частотой 34 ''тика'' в секунду, в зависимости от компьютера может быть больше или меньше времени.
  
 +
Например:
 +
 +
using System;
 +
using maddox.game;
 +
using maddox.game.world;
 +
public class Mission : AMission
 +
{
 +
    public override void OnTickGame()
 +
    {
 +
        double WievielSekunden = 0;
 +
       
 +
        if (Time.tickCounter() == 334)
 +
        {
 +
            WievielSekunden = Time.TicksToSecs(Time.tickCounter());
 +
            GamePlay.gpLogServer (null, "Meldung nach: {0} Ticks das sind {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
 +
        }
 +
        if (Time.tickCounter() == 667)
 +
        {
 +
            WievielSekunden = Time.TicksToSecs(Time.tickCounter());
 +
            GamePlay.gpLogServer (null, "Meldung nach: {0} Ticks das sind {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
 +
        }
 +
        if (Time.tickCounter() == 1000)
 +
        {
 +
            WievielSekunden = Time.TicksToSecs(Time.tickCounter());
 +
            GamePlay.gpLogServer (null, "Meldung nach: {0} Ticks das sind {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
 +
        }
 +
  }
 +
}
 +
 +
Данный пример ничего не делает, кроме как отправляет сообщение в чат сервера каждые 10, 20, 30 секунд.
 +
 +
'''Time.tickCounter()''' - содержит количество тиков, прошедших с момента начала мисиии
 +
'''Time.TicksToSecs''' - переводит такты в секунды
 +
 +
Далее выводим сообщение на экран:
 +
GamePlay.gpLogServer (null, "Meldung nach: {0} Ticks das sind {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
 +
 +
В игре это будет выглядеть так:
 +
 +
 +
[[Файл:Sfdp3-1.jpg|800px]]
 +
 +
 +
Также вы можете использовать '''OnTickGame()''' для задания циклов, зависящих от времени, например:
 +
 +
 +
using System;
 +
using maddox.game;
 +
using maddox.game.world;
 +
public class Mission : AMission
 +
{
 +
    public override void OnTickGame()
 +
    {
 +
        double WievielSekunden = 0;
 +
       
 +
        if (Time.tickCounter() % 334 == 0)
 +
        {
 +
            WievielSekunden = Time.TicksToSecs(Time.tickCounter());
 +
            GamePlay.gpLogServer (null, "Erste Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
 +
        }
 +
        if (Time.tickCounter() % 509 == 0)
 +
        {
 +
            WievielSekunden = Time.TicksToSecs(Time.tickCounter());
 +
            GamePlay.gpLogServer (null, "Zweite Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
 +
        }
 +
    }
 +
}
 +
 +
Для вычисления остатка при целочисленном делении в языке С# используется оператор деления по модулю %. Он применяется таким же образом, что и оператор деления, но в результате вычисляется не частное, а остаток.
 +
 +
3%3  результат: 0
 +
3%2  результат: 1
 +
5%3  результат: 2
 +
 +
:Подробнее можно прочитать здесь: [http://en.wikipedia.org/wiki/Modulo_operation Деление с остатком] )
 +
 +
Условие '''Time.tickCounter() % 334 == 0''' всегда выполняется когда значение'''tickCounter()''' равно 334 тика (то есть остаток  от деления 334%334 равен нулю и отправляет сообщения в чат через каждые 10 секунд.
 +
 +
Условие '''Time.tickCounter() % 509 == 0''' всегда выполняется когда значение'''tickCounter()''' равно 509 тиков (то есть остаток  от деления 509%509 равен нулю и отправляет сообщения в чат через каждые 15 секунд.
 +
 +
 +
[[Файл:Sfdp3-2.jpg|800px]]
 +
 +
 +
Если вы не хотите выводить сообщение в начале миссии, можете использовать задержку изменив ноль в предыдущем примере на значение '''меньше''', чем делитель. Вот примеры неправильных условий:
 +
 +
if (Time.tickCounter() % 334 == '''334''')
 +
if (Time.tickCounter() % 334 == '''335''')
 +
Эти условия никогда не будут выполнены и сообщение не появится на экране.
 +
 +
Зададим конкретное время вывода сообщения:
 +
 +
using System;
 +
using maddox.game;
 +
using maddox.game.world;
 +
public class Mission : AMission
 +
{
 +
    public override void OnTickGame()
 +
    {
 +
        double WievielSekunden = 0;
 +
       
 +
        if (Time.tickCounter() % 334 == 333)
 +
        {
 +
            WievielSekunden = Time.TicksToSecs(Time.tickCounter());
 +
            GamePlay.gpLogServer (null, "Erste Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
 +
        }
 +
        if (Time.tickCounter() % 509 == 508)
 +
        {
 +
            WievielSekunden = Time.TicksToSecs(Time.tickCounter());
 +
            GamePlay.gpLogServer (null, "Zweite Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
 +
        }
 +
    }
 +
}
 +
 +
Результат:
 +
 +
[[Файл:Sfdp3-3.jpg|800px]]
 +
 +
 +
В основную миссию два добавим камуфляжную палатку, она появится перед исчезновением и скроет технику.
 +
 +
 +
[[Файл:Sfdp3-4.jpg|800px]]
 +
 +
 +
Далее нам необходима подмиссия. В ней будет один автомобиль, который проедет от одного конца ВПП до другого.
 +
 +
 +
[[Файл:Sfdp3-5.jpg|800px]]
 +
 +
 +
Подмиссия будет загружаться скажем каждые 30 секунд, так мы создадим колонну грузовиков, которые будут курсировать по ВПП и станут для нас отличной мишенью. Транспортные средства будут двигаться на некотором расстоянии друг от друга. В нашей миссии автомобили буду исчезать через 75 секунд - это время, которое понадобится им, чтобы достичь конечной точки пути. Игрок должен уничтожить как можно больше автомобилей. Количество машин (точнее под-миссий) будет равно 10. В этот раз мы не будем использовать триггеры, зачет результатов атаки и сведения о поврежденной технике будут содержаться в коде скрипта.
 +
 +
Код с тестовыми сообщениями:
 +
 +
 +
using System;
 +
using maddox.game;
 +
using maddox.game.world;
 +
using System.Collections.Generic;
 +
public class Mission : AMission
 +
{   
 +
    AiAircraft PlayerPlane;
 +
    const int MaxAnzahlWellen = 10;
 +
    int AnzahlWellen = 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 (Time.tickCounter() % 1000 == 0 && (AnzahlWellen < MaxAnzahlWellen))  //ca. alle 30sek die Karte laden
 +
        {
 +
            GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen5Sub1.mis");
 +
            AnzahlWellen++;
 +
            GamePlay.gpLogServer (null, "{0} nach {1} sek.\n", new object [] {AnzahlWellen, Time.TicksToSecs(Time.tickCounter())});//Testmeldung
 +
        }       
 +
        if (Time.tickCounter() % 11500 == 0)   
 +
        {
 +
                    GamePlay.gpLogServer (null, "{0} nach {1} sek.\n", new object [] {AnzahlWellen, Time.TicksToSecs(Time.tickCounter())});//Testmeldung
 +
                    GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlWellen.ToString() + " Fahrzeugen zerstört" );
 +
        }
 +
    }   
 +
    public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
 +
    {
 +
        base.OnActorCreated(missionNumber, shortName, actor);
 +
        if (actor is AiGroundActor)
 +
        {
 +
            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()))
 +
    {
 +
        ZerstoerteZiele++;
 +
        serverMessage(ZerstoerteZiele.ToString());
 +
      }
 +
    }
 +
}
 +
 +
 +
Разберем код нашего скрипта. Во-первых мы используем новый метод:
 +
'''using System.Collections.Generic;'''
 +
 +
В скрипте нам понадобятся следующие переменные:
 +
 +
'''AiAircraft PlayerPlane;''' - '''AiAircraft''' класс, в котором содержатся все доступные самолеты в игре, все самолеты за пределами этой группы являются статическими.
 +
 +
'''const int MaxAnzahlWellen = 10;''' - количество запусков под-миссий, в нашем случае равно кол-ву грузовиков (целей)
 +
'''int AnzahlWellen = 0;''' - кол-во уже запущенных под-миссий
 +
'''int ZerstoerteZiele;''' - количество уничтоженных целей
 +
 +
public override void OnBattleStarted()
 +
{
 +
    base.OnBattleStarted();
 +
    MissionNumberListener = -1;
 +
    PlayerPlane = (AiAircraft)GamePlay.gpPlayer().Place();
 +
}
 +
 +
В методе '''OnBattleStarted ''' установим '''MissionNumberListener = -1''', чтобы иметь доступ к объектам под-миссий.
 +
 +
'''PlayerPlane = (AiAircraft)GamePlay.gpPlayer().Place();'''  - определяем самолет игрока.
 +
Используем для этого класс IGamePlay, в котором есть метод '''gpPlayer()'''. Указываем нужный нам класс '''(AiAircraft)''' куда входит игрок (так же он присутствует в классах '''AiActor, AiCart, AiAircraft..)'''. '''Place()''' определяет текущее положение игрока. Метод '''gpPlayer''' используется только в одиночных миссиях, для мультиплеера нужно использовать метод '''gpRemotePlayers'''.
 +
 +
 +
public override void OnTickGame()
 +
{
 +
    if (Time.tickCounter() % 1000 == 0 && (AnzahlWellen < MaxAnzahlWellen))  //ca. alle 30sek die Karte laden
 +
    {
 +
        GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen5Sub1.mis");
 +
        AnzahlWellen++;
 +
        GamePlay.gpLogServer (null, "{0} nach {1} sek.\n", new object [] {AnzahlWellen, Time.TicksToSecs(Time.tickCounter())});//Testmeldung
 +
    }
 +
       
 +
    if (Time.tickCounter() == 11500)   
 +
    {
 +
        GamePlay.gpLogServer (null, "{0} nach {1} sek.\n", new object [] {AnzahlWellen, Time.TicksToSecs(Time.tickCounter())});//Testmeldung
 +
        GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlWellen.ToString() + " Fahrzeugen zerstört" );
 +
        MissionAbgeschlossen = true;
 +
    }
 +
}
 +
 +
 +
'''OnTickGame ()'''
 +
 +
'''if (Time.tickCounter() % 1000 == 0 && (AnzahlWellen < MaxAnzahlWellen))''' - условие, которое загружает под-миссию, если прошло 30 секунд ''И'' (оператор '''''&&''''') и номер текущей подмиссии меньше переменной ''const int MaxAnzahlWellen''.
 +
 +
'''if (Time.tickCounter() == 11500)''' - если прошло 11500 тиков (то есть время, выделенное на выполнение задания - выводится итоговый результат по количеству уничтоженных целей)
 +
 +
[[Файл:Sfdp3-6.jpg|800px]]
 +
 +
 +
public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
 +
{
 +
    base.OnActorCreated(missionNumber, shortName, actor);
 +
 +
    if (actor is AiGroundActor)
 +
    {
 +
        Timeout(75, () => {
 +
            if (actor != null)
 +
            {
 +
                (actor as AiGroundActor).Destroy();
 +
            }
 +
        });
 +
    }
 +
}
 +
 +
 +
'''OnActorCreated(int missionNumber, string shortName, AiActor actor)''' - метод вызывается каждый раз, когда создается новый '''Actor'''.
 +
 +
'''if (actor is AiGroundActor)''' -  проверяем, принадлежит ли '''Actor''' к классу '''AiGroundActor'''
 +
в котором содержатся все "живые" наземные объекты: автомобили, танки, корабли, артиллерия. Если условие равно TRUE выполняется соответствующий код.
 +
 +
 +
'''Timeout(75, () => { Anweisungen });''' - "отсчитываем" 75 секунд после создания '''Actor''', далее проверяем существует ли он еще - '''if (actor != null)'''. Если условия выполняются - указываем, что объект должен рассматриваться как '''AiGroundActor''' и уничтожаем объект командой '''.Destroy();'''.
 +
 +
 +
'''.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()))
 +
    {
 +
        ZerstoerteZiele++;
 +
        serverMessage(ZerstoerteZiele.ToString()); //Testmeldung
 +
    }
 +
}
 +
 +
 +
Чтобы зарегистрировать уничтоженный объект в статистике переопределим метод '''OnActorDead(..)'''.
 +
 +
'''public override void OnActorDead(int missionNumber, string shortName, AiActor actor, System.Collections.Generic.List<DamagerScore> damages)'''
 +
 +
Этот метод вызывается при нанесении объекту повреждений, причем два раза - первый раз для техники, второй - для экипажа. Так как мы будем считать только уничтоженные грузовики введем переменную '''KilledName'''. Переменная будет состоять из номера миссии и имени уничтоженного объекта. Имя объекта можно найти в файле мисиии '''.mis''':
 +
 +
[Chiefs]
 +
0_Chief Vehicle.Austin_10_Tilly gb
 +
 +
 +
'''if ((damages.Count != 0) && (PlayerPlane.Name().Equals(damages[0].initiator.Actor.Name())) && KilledName.Equals(actor.Name()))'''
 +
 +
- условие в котором определяется, что игрок уничтожил объект. Если выполняется - прибавляем к счетчику уничтоженных грузовиков еще один и выводим сообщение сервреа об этом.
 +
 +
 +
: ''Для установки миссий-примеров скопируйте их в папку:
 +
..\Documents\1C SoftClub\il-2 sturmovik cliffs of dover\missions\Single
 +
 +
----
 +
=== Загрузка подмиссий (автор FG28_Kodiak) ===
 +
Оригинальные темы см. на форуме [http://translate.google.com/translate?hl=en&sl=de&tl=en&u=http%3A%2F%2Fforum.sturmovik.de%2Findex.php%2Fboard%2C17.0.html sturmovik.de](перевод от Google):
 +
 +
*[[Ил-2 Штурмовик: Битва за Британию. Скрипты. Скрипты для чайников. Часть 1 - Загрузка подмиссий|Часть 1 - Загрузка подмиссий]]
 +
*[[Ил-2 Штурмовик: Битва за Британию. Скрипты. Скрипты для чайников. Часть 2 - Загрузка подмиссий|Часть 2 - Загрузка подмиссий]]
 +
*[[Ил-2 Штурмовик: Битва за Британию. Скрипты. Скрипты для чайников. Часть 4 - Загрузка подмиссий|Часть 4 - Загрузка подмиссий]]
 +
 +
[[Ил-2 Штурмовик: Битва за Британию. Скрипты|Вернуться на страницу "Скрипты"]]
  
 
[[Категория:Ил-2 Штурмовик: Битва за Британию. Скрипты]]
 
[[Категория:Ил-2 Штурмовик: Битва за Британию. Скрипты]]

Текущая версия на 18:30, 6 ноября 2011

Автор: FG28_Kodiak
Ссылка: Перейти (перевод Google)

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

Samples.zip

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

Samples.zip


В предыдущих двух миссиях мы загружали под-миссии после начала миссии-хоста. В этой части мы научимся контролировать загрузку миссиий при помощи метода public virtual void OnTickGame ()

public override void OnTickGame()

Метод OnTickGame() направляет вызовы с частотой 34 тика в секунду, в зависимости от компьютера может быть больше или меньше времени.

Например:

using System;
using maddox.game;
using maddox.game.world;
public class Mission : AMission
{
   public override void OnTickGame()
   {
       double WievielSekunden = 0;
       
       if (Time.tickCounter() == 334) 
       {
           WievielSekunden = Time.TicksToSecs(Time.tickCounter());
           GamePlay.gpLogServer (null, "Meldung nach: {0} Ticks das sind {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
       }
       if (Time.tickCounter() == 667) 
       {
           WievielSekunden = Time.TicksToSecs(Time.tickCounter());
           GamePlay.gpLogServer (null, "Meldung nach: {0} Ticks das sind {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
       }
       if (Time.tickCounter() == 1000) 
       {
           WievielSekunden = Time.TicksToSecs(Time.tickCounter());
           GamePlay.gpLogServer (null, "Meldung nach: {0} Ticks das sind {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
       }
  }
} 

Данный пример ничего не делает, кроме как отправляет сообщение в чат сервера каждые 10, 20, 30 секунд.

Time.tickCounter() - содержит количество тиков, прошедших с момента начала мисиии Time.TicksToSecs - переводит такты в секунды

Далее выводим сообщение на экран:

GamePlay.gpLogServer (null, "Meldung nach: {0} Ticks das sind {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});

В игре это будет выглядеть так:


Sfdp3-1.jpg


Также вы можете использовать OnTickGame() для задания циклов, зависящих от времени, например:


using System;
using maddox.game;
using maddox.game.world;
public class Mission : AMission
{
   public override void OnTickGame()
   {
       double WievielSekunden = 0;
       
       if (Time.tickCounter() % 334 == 0) 
       {
           WievielSekunden = Time.TicksToSecs(Time.tickCounter());
           GamePlay.gpLogServer (null, "Erste Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
       }
       if (Time.tickCounter() % 509 == 0) 
       {
           WievielSekunden = Time.TicksToSecs(Time.tickCounter());
           GamePlay.gpLogServer (null, "Zweite Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
       }
   }
}

Для вычисления остатка при целочисленном делении в языке С# используется оператор деления по модулю %. Он применяется таким же образом, что и оператор деления, но в результате вычисляется не частное, а остаток.

3%3   результат: 0
3%2   результат: 1
5%3   результат: 2
Подробнее можно прочитать здесь: Деление с остатком )

Условие Time.tickCounter() % 334 == 0 всегда выполняется когда значениеtickCounter() равно 334 тика (то есть остаток от деления 334%334 равен нулю и отправляет сообщения в чат через каждые 10 секунд.

Условие Time.tickCounter() % 509 == 0 всегда выполняется когда значениеtickCounter() равно 509 тиков (то есть остаток от деления 509%509 равен нулю и отправляет сообщения в чат через каждые 15 секунд.


Sfdp3-2.jpg


Если вы не хотите выводить сообщение в начале миссии, можете использовать задержку изменив ноль в предыдущем примере на значение меньше, чем делитель. Вот примеры неправильных условий:

if (Time.tickCounter() % 334 == 334)
if (Time.tickCounter() % 334 == 335)
Эти условия никогда не будут выполнены и сообщение не появится на экране.

Зададим конкретное время вывода сообщения:

using System;
using maddox.game;
using maddox.game.world;
public class Mission : AMission
{
   public override void OnTickGame()
   {
       double WievielSekunden = 0;
       
       if (Time.tickCounter() % 334 == 333) 
       {
           WievielSekunden = Time.TicksToSecs(Time.tickCounter());
           GamePlay.gpLogServer (null, "Erste Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
       }
       if (Time.tickCounter() % 509 == 508) 
       {
           WievielSekunden = Time.TicksToSecs(Time.tickCounter());
           GamePlay.gpLogServer (null, "Zweite Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden});
       }
   }
} 

Результат:

Sfdp3-3.jpg


В основную миссию два добавим камуфляжную палатку, она появится перед исчезновением и скроет технику.


Sfdp3-4.jpg


Далее нам необходима подмиссия. В ней будет один автомобиль, который проедет от одного конца ВПП до другого.


Sfdp3-5.jpg


Подмиссия будет загружаться скажем каждые 30 секунд, так мы создадим колонну грузовиков, которые будут курсировать по ВПП и станут для нас отличной мишенью. Транспортные средства будут двигаться на некотором расстоянии друг от друга. В нашей миссии автомобили буду исчезать через 75 секунд - это время, которое понадобится им, чтобы достичь конечной точки пути. Игрок должен уничтожить как можно больше автомобилей. Количество машин (точнее под-миссий) будет равно 10. В этот раз мы не будем использовать триггеры, зачет результатов атаки и сведения о поврежденной технике будут содержаться в коде скрипта.

Код с тестовыми сообщениями:


using System;
using maddox.game;
using maddox.game.world;
using System.Collections.Generic;
public class Mission : AMission
{    
   AiAircraft PlayerPlane;
   const int MaxAnzahlWellen = 10;
   int AnzahlWellen = 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 (Time.tickCounter() % 1000 == 0 && (AnzahlWellen < MaxAnzahlWellen))  //ca. alle 30sek die Karte laden
       {
           GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen5Sub1.mis");
           AnzahlWellen++;
           GamePlay.gpLogServer (null, "{0} nach {1} sek.\n", new object [] {AnzahlWellen, Time.TicksToSecs(Time.tickCounter())});//Testmeldung
       }        
       if (Time.tickCounter() % 11500 == 0)     
       {
                   GamePlay.gpLogServer (null, "{0} nach {1} sek.\n", new object [] {AnzahlWellen, Time.TicksToSecs(Time.tickCounter())});//Testmeldung
                   GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlWellen.ToString() + " Fahrzeugen zerstört" );
       }
   }    
   public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
   {
       base.OnActorCreated(missionNumber, shortName, actor);
       if (actor is AiGroundActor)
       {
           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()))
    		{
    		    ZerstoerteZiele++;
    		    serverMessage(ZerstoerteZiele.ToString());
    	  }
   }
}


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

using System.Collections.Generic;

В скрипте нам понадобятся следующие переменные:

AiAircraft PlayerPlane; - AiAircraft класс, в котором содержатся все доступные самолеты в игре, все самолеты за пределами этой группы являются статическими.

const int MaxAnzahlWellen = 10; - количество запусков под-миссий, в нашем случае равно кол-ву грузовиков (целей) int AnzahlWellen = 0; - кол-во уже запущенных под-миссий int ZerstoerteZiele; - количество уничтоженных целей

public override void OnBattleStarted()
{
   base.OnBattleStarted();
   MissionNumberListener = -1;
   PlayerPlane = (AiAircraft)GamePlay.gpPlayer().Place();
}

В методе OnBattleStarted установим MissionNumberListener = -1, чтобы иметь доступ к объектам под-миссий.

PlayerPlane = (AiAircraft)GamePlay.gpPlayer().Place(); - определяем самолет игрока. Используем для этого класс IGamePlay, в котором есть метод gpPlayer(). Указываем нужный нам класс (AiAircraft) куда входит игрок (так же он присутствует в классах AiActor, AiCart, AiAircraft..). Place() определяет текущее положение игрока. Метод gpPlayer используется только в одиночных миссиях, для мультиплеера нужно использовать метод gpRemotePlayers.


public override void OnTickGame()
{
   if (Time.tickCounter() % 1000 == 0 && (AnzahlWellen < MaxAnzahlWellen))  //ca. alle 30sek die Karte laden
   {
       GamePlay.gpPostMissionLoad("missions\\Single\\Samples\\TestSubmissions\\MissionNachladen5Sub1.mis");
       AnzahlWellen++;
       GamePlay.gpLogServer (null, "{0} nach {1} sek.\n", new object [] {AnzahlWellen, Time.TicksToSecs(Time.tickCounter())});//Testmeldung
   }
       
   if (Time.tickCounter() == 11500)     
   {
       GamePlay.gpLogServer (null, "{0} nach {1} sek.\n", new object [] {AnzahlWellen, Time.TicksToSecs(Time.tickCounter())});//Testmeldung
       GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlWellen.ToString() + " Fahrzeugen zerstört" );
       MissionAbgeschlossen = true;
   }
}


OnTickGame ()

if (Time.tickCounter() % 1000 == 0 && (AnzahlWellen < MaxAnzahlWellen)) - условие, которое загружает под-миссию, если прошло 30 секунд И (оператор &&) и номер текущей подмиссии меньше переменной const int MaxAnzahlWellen.

if (Time.tickCounter() == 11500) - если прошло 11500 тиков (то есть время, выделенное на выполнение задания - выводится итоговый результат по количеству уничтоженных целей)

Sfdp3-6.jpg


public override void OnActorCreated(int missionNumber, string shortName, AiActor actor)
{
   base.OnActorCreated(missionNumber, shortName, actor);
   if (actor is AiGroundActor)
   {
       Timeout(75, () => {
           if (actor != null)
           { 
               (actor as AiGroundActor).Destroy(); 
           }
       });
   }
}


OnActorCreated(int missionNumber, string shortName, AiActor actor) - метод вызывается каждый раз, когда создается новый Actor.

if (actor is AiGroundActor) - проверяем, принадлежит ли Actor к классу AiGroundActor в котором содержатся все "живые" наземные объекты: автомобили, танки, корабли, артиллерия. Если условие равно TRUE выполняется соответствующий код.


Timeout(75, () => { Anweisungen }); - "отсчитываем" 75 секунд после создания Actor, далее проверяем существует ли он еще - if (actor != null). Если условия выполняются - указываем, что объект должен рассматриваться как AiGroundActor и уничтожаем объект командой .Destroy();.


.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()))
   {
       ZerstoerteZiele++;
       serverMessage(ZerstoerteZiele.ToString()); //Testmeldung
   }
}


Чтобы зарегистрировать уничтоженный объект в статистике переопределим метод OnActorDead(..).

public override void OnActorDead(int missionNumber, string shortName, AiActor actor, System.Collections.Generic.List<DamagerScore> damages)

Этот метод вызывается при нанесении объекту повреждений, причем два раза - первый раз для техники, второй - для экипажа. Так как мы будем считать только уничтоженные грузовики введем переменную KilledName. Переменная будет состоять из номера миссии и имени уничтоженного объекта. Имя объекта можно найти в файле мисиии .mis:

[Chiefs]
0_Chief Vehicle.Austin_10_Tilly gb


if ((damages.Count != 0) && (PlayerPlane.Name().Equals(damages[0].initiator.Actor.Name())) && KilledName.Equals(actor.Name())) 

- условие в котором определяется, что игрок уничтожил объект. Если выполняется - прибавляем к счетчику уничтоженных грузовиков еще один и выводим сообщение сервреа об этом.


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

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

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

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