Ил-2 Штурмовик: Битва за Британию. Скрипты. Скрипты для чайников. Часть 3 - Загрузка подмиссий — различия между версиями
Podvoxx (обсуждение | вклад) |
Andric (обсуждение | вклад) (→Загрузка подмиссий (автор FG28_Kodiak)) |
||
(не показано 11 промежуточных версии ещё одного участника) | |||
Строка 1: | Строка 1: | ||
:'''Автор:''' FG28_Kodiak | :'''Автор:''' FG28_Kodiak | ||
:'''Ссылка:''' [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] | :[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 | + | |
− | + | ||
− | + | ||
− | + | '''public override void OnTickGame()''' | |
− | + | ||
− | + | ||
− | + | Метод '''OnTickGame()''' направляет вызовы с частотой 34 ''тика'' в секунду, в зависимости от компьютера может быть больше или меньше времени. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | Например: | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | using System; | |
− | Time.tickCounter () | + | using maddox.game; |
− | GamePlay.gpLogServer (null, " | + | 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}); | ||
+ | |||
+ | В игре это будет выглядеть так: | ||
Строка 47: | Строка 57: | ||
− | + | Также вы можете использовать '''OnTickGame()''' для задания циклов, зависящих от времени, например: | |
− | + | ||
− | using System; | + | using System; |
− | using maddox.game; | + | using maddox.game; |
− | using maddox.game.world; | + | 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''') | |
− | + | Эти условия никогда не будут выполнены и сообщение не появится на экране. | |
− | + | ||
− | + | Зададим конкретное время вывода сообщения: | |
− | if (Time.tickCounter() % 334 == 333) | + | using System; |
− | { | + | using maddox.game; |
− | WievielSekunden = Time.TicksToSecs(Time.tickCounter()); | + | using maddox.game.world; |
− | GamePlay.gpLogServer (null, "Erste Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden}); | + | public class Mission : AMission |
− | } | + | { |
− | if (Time.tickCounter() % 509 == 508) | + | public override void OnTickGame() |
− | { | + | { |
− | WievielSekunden = Time.TicksToSecs(Time.tickCounter()); | + | double WievielSekunden = 0; |
− | GamePlay.gpLogServer (null, "Zweite Meldung: {0} Ticks = {1} sek.\n", new object [] {Time.tickCounter(), WievielSekunden}); | + | |
− | } | + | 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-3.jpg|800px]] | ||
− | + | В основную миссию два добавим камуфляжную палатку, она появится перед исчезновением и скроет технику. | |
− | + | ||
[[Файл:Sfdp3-4.jpg|800px]] | [[Файл:Sfdp3-4.jpg|800px]] | ||
− | + | Далее нам необходима подмиссия. В ней будет один автомобиль, который проедет от одного конца ВПП до другого. | |
+ | |||
[[Файл:Sfdp3-5.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() | |
− | { | + | { |
− | GamePlay. | + | 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'''. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | if (Time.tickCounter() % | + | public override void OnTickGame() |
− | { | + | { |
− | GamePlay.gpLogServer (null, "{0} nach {1} sek.\n", new object [] {AnzahlWellen, Time.TicksToSecs(Time.tickCounter())});//Testmeldung | + | if (Time.tickCounter() % 1000 == 0 && (AnzahlWellen < MaxAnzahlWellen)) //ca. alle 30sek die Karte laden |
− | GamePlay.gpHUDLogCenter("Sie haben "+ ZerstoerteZiele.ToString() + " von " + AnzahlWellen.ToString() + " Fahrzeugen zerstört" ); | + | { |
− | } | + | 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 | + | public override void OnActorCreated(int missionNumber, string shortName, AiActor actor) |
− | { | + | { |
− | base. | + | 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 ( | + | |
− | + | '''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 | + | '''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)
Скачать оригиналы миссий:
Скачать примеры с Sukhoi.ru:
В предыдущих двух миссиях мы загружали под-миссии после начала миссии-хоста. В этой части мы научимся контролировать загрузку миссиий при помощи метода 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});
В игре это будет выглядеть так:
Также вы можете использовать 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 секунд.
Если вы не хотите выводить сообщение в начале миссии, можете использовать задержку изменив ноль в предыдущем примере на значение меньше, чем делитель. Вот примеры неправильных условий:
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}); } } }
Результат:
В основную миссию два добавим камуфляжную палатку, она появится перед исчезновением и скроет технику.
Далее нам необходима подмиссия. В ней будет один автомобиль, который проедет от одного конца ВПП до другого.
Подмиссия будет загружаться скажем каждые 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 тиков (то есть время, выделенное на выполнение задания - выводится итоговый результат по количеству уничтоженных целей)
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):