Искусство войны. Осваиваем скрипты — различия между версиями
(Новая страница: «Одним из главных недостатков любой военной игры из серии «Искусство войны» вполне справе…») |
(нет различий)
|
Версия 08:07, 20 января 2010
Одним из главных недостатков любой военной игры из серии «Искусство войны» вполне справедливо называется малое число игровых миссий. Однако сама игра снабжена редакторами карт и миссий, которые позволяют создавать антураж и сценарии, не уступающие включённым в базовый комплект программного продукта. Как справедливо отмечено критикой, их использование требует определённого умения, но при этом абсолютно не нужно быть асом программирования как Дейкстра или создатели RT-11. Немножко логики и понимания основ заложенной в программный продукт сценарной машины — и работающие скрипты, позволяющие получить от игры удовольствие, обеспечены. Чтобы показать, что «не боги горшки обжигают», давайте вместе с автором пройдёмся по этапам создания скриптов несложной, но вполне интересной по прохождению миссии «Forza, Carristi!» для дополнения «Итальянский вариант» первой инкарнации «Искусство войны. Африка 1943».
Постановка задачи
Именно с этого всегда надо начинать. После некоторых раздумий сценарий на одной из стандартных карт для мультиплеера выкристаллизовался в следующее: танковому и берсальерскому взводам итальянской дивизии «Чентауро» надо захватить занятую британцами деревню, которые они используют как снабженческий и коммуникационный пункт. К деревне от стартовых позиций ведут два непересекающихся пути, на каждом из которых итальянцев ждут нелёгкие испытания. Один проход защищается мощной группировкой из двухфунтовых противотанковых орудий и станковых пулемётов, а другой проходит мимо малюсенького населённого пункта, где расположилось британское пехотное отделение с наличием противотанкового ружья системы Бойса и два «Крузейдера». Один вражеский танк вооружён двухфунтовой пушкой, второй — трёхдюймовой гаубицей. Сама деревня-цель атаки защищена тремя отделениями британской пехоты с наличием противотанковых ружей системы Бойса. Для некоторого усложнения задачи игроку его непосредственный начальник, майор Луиджи Ферретти, не разрешил ввести в бой все имеющиеся силы (5 танков М14/41 и 4 берсальерских отделения сразу) и оставил в резерве два танка и два отделения. Таким образом, в составе контролируемых игроком сил 3 М14/41 и 2 отделения. Распылять их, пытаясь атаковать по обоим путям сразу — верный путь к поражению, поэтому игроку предстоит либо осторожно, шаг за шагом, в тесном взаимодействии танков и пехоты продавливать оборону вражеской группировки с орудиями и пулемётами, либо решиться на танковый бой с «Крузейдерами». В этом случае эффективным против М14/41 является один 40-мм ствол, гаубица второго «Крузейдера» «близкой поддержки» и ПТР системы Бойса могут при удаче лишь обездвижить наши танки, что весьма неприятно (они нужны для штурма деревни), но в целом ещё не фатально. Но радио у британцев есть и в случае невозможности огня из этой 40-мм пушки (уничтожения «Крузейдера», повреждения его орудия или полной гибели экипажа), а следовательно и защитить проход от наших танков они вызывают подкрепление — два бронеавтомобиля «Даймлер», которые появляются с тыла и постараются пройти угрожаемым проходом к деревне, чтобы усилить её защиту, по пути истребляя всех попадающихся им на глаза итальянцев. Вне зависимости от выбранного игроком пути в случае больших потерь майор Ферретти передаёт нам под командование резерв для выполнения задачи. Пусть также на основании данных разведки наш командир предупредит нас при подходе к тому или иному проходу, с чем нам предстоит иметь дело.
Таков общий план миссии. Осталось только уточнить частности — деревню считаем захваченной и задачу выполненной, если в её области находится минимум десять наших солдат, причём это число включает членов экипажей танков, как в своих машинах, так и вне их; а из вражеских сил осталось в живых не более двух Томми. Если эти условия выполнены, посчитаем выживших британских солдат крайне деморализованными, бросившими оружие, сдавшимися в плен. Очевидно, что если у нас осталось менее десяти берсальеров и танкистов (вне зависимости от числа и состояния танков), то поставленная задача не может быть выполнена и это будет условием поражения. Определим также взгляды майора Ферретти на то, когда стоит вводить в бой резерв. Пусть он сочтёт это нужным, если у нас из первоначальных сил не осталось больше ни одного исправного танка (танк считается исправным, если у него не повреждены ходовая часть, основное вооружение и в нём присутствует хотя бы один член экипажа) или общее число берсальеров и танкистов стало меньше 15 человек.
Программируем скрипты
Когда задача стала ясной, не стоит пугаться её кажущегося объёма — и слона можно съесть по кусочкам. Сначала приступаем к «разрезке» этого «слона» на эти самые кусочки, но перед этим следует немного сказать пару слов о принципе работы скриптовой машины «Искусства войны». Поведение и своих, и вражеских войск управляется последовательностями управляющих инструкций, которые сгруппированы в блоки — так называемые триггера. Проводя аналогию с заводским цехом, можно сказать, что триггера - это рабочие. Сколько их работает в данный момент, определяется текущей обстановкой, если нужно, то один рабочий может позвать другого на помощь или отпустить помощника отдыхать в курилку, завершить работу, передать её результаты другому рабочему и пойти в курилку сам. Точно также и триггера — в зависимости от ситуации могут запускать и останавливать другие триггера, завершать свою выполненную работу, чтобы не занимать более ресурсы процессора компьютера. Работающий в данный момент триггер называется активным, их может быть несколько и они выполняются одновременно (в рамках процессорной «многозадачности» — когда процессор быстро-быстро переключается с одного дела на другое, в итоге за большое время в успевая сделать всю порученную ему работу). Также и в цеху могут одновременно работать сразу несколько рабочих над одним или разными делами. Те триггера, которым ещё предстоит вступить в дело или уже выполнившие свою работу, называются неактивными — как отдыхающие рабочие в курилке.
Как в производстве есть промежуточные результаты — полуфабрикаты и готовые детали, так и в скриптовой машине есть их полный аналог — это ячейки для хранения чисел и текстов, называемые переменными. Там, к примеру, может храниться количество танков противника или название группы боевых единиц, нужные для определения выигрышного положения дел. Причём следует иметь в виду, что часть таких ячеек доступна абсолютно всем триггерам (их названия начинаются с двух символов @@), а часть — только одному триггеру, где в них есть необходимость (их названия начинаются с одиночного символа @). Это схоже с ящиком с запчастями, доступным для всего цеха и с бардачком с необходимым инвентарём и деталями у конкретного рабочего, нужным только ему.
В соответствии с этим производим разбиение (по-научному декомпозицию) задуманного сценария на составные части. В нашем случае они достаточно просты — необходимо контролировать следующие ситуации:
- Наличие более 9 наших и менее 3 вражеских комбатантов в области деревни. Если это случилось — мы победили;
- Наличие в нашем распоряжении менее 10 комбатантов. Если это случилось — мы проиграли;
- Наличие в нашем распоряжении менее 15 комбатантов и ни одного исправного танка с экипажем. Если это случилось — мы получаем подкрепления;
- Невозможность стрельбы из основного оружия вражеского танка «Крузейдер» с 40-мм пушкой. Если это случилось — противник получает подкрепление.
- Наличие хотя бы одного нашего комбатанта к началу прохода с обороняющими его противотанковыми пушками и пулемётами. Если это случилось — мы получаем соответствующее сообщение;
- Наличие хотя бы одного нашего комбатанта к началу прохода с обороняющими его «Крузейдерами». Если это случилось — мы получаем соответствующее сообщение;
Каждый пункт — это триггер, в миссии «Forza, Carristi!» они имеют следующие названия:
- WinCheck — проверка выигрыша (от английских слов Win - выигрыш и Check — проверка);
- FailCheck — проверка поражения (Fail - провал и Check — проверка);
- Reinforcement — подкрепление нашим силам (Reinforcement - подкрепление);
- Brit_Daimler — подкрепление в виде «Даймлеров» вражеским силам (British Daimlers - британские «Даймлеры»);
- Warning_1 — 1-е предупреждение от майора Ферретти (Warning — предупреждение);
- Warning_2 — 2-е предупреждение от майора Ферретти.
И в единое целое их связывает триггер init, который автоматически выполняется скриптовой машиной игры сразу после загрузки сценария. Рассмотрим их теперь по отдельности. Однако за подробным описанием синтаксиса и возможностей того или иного оператора всё равно следует обратиться к соответствующему руководству, прилагаемому в электронном виде к игре.
init
// 1. Армия ИГРОКА Set @@army = 1 // 2. Армия КОМПЬЮТЕРА Set @@enemy_army = 2 // 3. НЕЙТРАЛЬНАЯ армия Set @@neutral_army = 3 // 4. Армия СОЮЗНИКА Set @@allied_army = 4 Set @disposition = "Initial_Area" ActivateDispositionMode ( @disposition ) ChangeFogOfWar ( ENABLE ) SetWorkArmy ( ARMY , @@army ) // Сообщаем игроку о задании QuestActivate ( "MainTask" , "Luigi" , 15000 ) PingShow ( "Ping_01" , 1 , POINT , "Ultimate_target" ) RunTrigger ( "FailCheck" ) Delay ( 5000 ) RunTrigger ( "WinCheck" ) RunTrigger ( "Reinforcement" ) RunTrigger ( "Warning_1" ) RunTrigger ( "Warning_2" ) RunTrigger ( "Brit_Daimler" ) Halt
Поскольку в сценарии есть управляемые игроком силы, а также управляемые искусственным интеллектом союзные, вражеские и нейтральные (взятые в плен британские солдаты), то в редакторе миссий организованы четыре армии с соответствующими характеристиками враждебности друг к другу, каждой из них при создании автоматически присваивается свой номер. Конечно, его можно указывать каждый раз в нужном месте, но гораздо лучше создать для каждой армии свою переменную, в которой он хранится и используется при надобности. Да, вместо числа 1 при наборе кода надо будет печатать @@army, но, представим, что из-за каких-нибудь правок в редакторе номер армии сменится, а задействован он в доброй полсотне мест в самых разных триггерах. И придётся их выискивать, править, с высокой вероятностью при этом можно забыть что-то исправить или изменить число 1, которое к номеру армии вообще отношения не имеет. Чтобы избежать этого, везде, где требуется номер армии, используем соответствующие имена переменных, при необходимости его изменения достаточно исправить его только в определении оператором Set и всё снова заработает. Отметим, что эти переменные должны быть доступны абсолютно всем триггерам и потому их имена начинаются с @@. Первые четыре оператора Set здесь задают соответствующие переменные и устанавливают для них числовые значения номеров армий, выданные редактором миссий.