Искусство войны. Осваиваем скрипты

Материал из Бронетанковой Энциклопедии — armor.kiev.ua/wiki
Перейти к: навигация, поиск

Одним из главных недостатков любой военной игры из серии «Искусство войны» вполне справедливо называется малое число игровых миссий. Однако сама игра снабжена редакторами карт и миссий, которые позволяют создавать антураж и сценарии, не уступающие включённым в базовый комплект программного продукта. Как справедливо отмечено критикой, их использование требует определённого умения, но при этом абсолютно не нужно быть асом программирования как Дейкстра или создатели RT-11. Немножко логики и понимания основ заложенной в программный продукт сценарной машины — и работающие скрипты, позволяющие получить от игры удовольствие, обеспечены. Чтобы показать, что «не боги горшки обжигают», давайте вместе с автором пройдёмся по этапам создания скриптов несложной, но вполне интересной по прохождению миссии «Forza, Carristi!» для дополнения «Итальянский вариант» первой инкарнации «Искусство войны. Африка 1943».

Постановка задачи

Именно с этого всегда надо начинать. После некоторых раздумий сценарий на одной из стандартных карт для мультиплеера выкристаллизовался в следующее: танковому и берсальерскому взводам итальянской дивизии «Чентауро» надо захватить занятую британцами деревню, которые они используют как снабженческий и коммуникационный пункт. К деревне от стартовых позиций ведут два непересекающихся пути, на каждом из которых итальянцев ждут нелёгкие испытания. Один проход защищается мощной группировкой из двухфунтовых противотанковых орудий и станковых пулемётов, а другой проходит мимо малюсенького населённого пункта, где расположилось британское пехотное отделение с наличием противотанкового ружья системы Бойса и два «Крузейдера». Один вражеский танк вооружён двухфунтовой пушкой, второй — трёхдюймовой гаубицей. Сама деревня-цель атаки защищена тремя отделениями британской пехоты с наличием противотанковых ружей системы Бойса. Для некоторого усложнения задачи игроку его непосредственный начальник, майор Луиджи Ферретти, не разрешил ввести в бой все имеющиеся силы (5 танков М14/41 и 4 берсальерских отделения сразу) и оставил в резерве два танка и два отделения. Таким образом, в составе контролируемых игроком сил 3 М14/41 и 2 отделения. Распылять их, пытаясь атаковать по обоим путям сразу — верный путь к поражению, поэтому игроку предстоит либо осторожно, шаг за шагом, в тесном взаимодействии танков и пехоты продавливать оборону вражеской группировки с орудиями и пулемётами, либо решиться на танковый бой с «Крузейдерами». В этом случае эффективным против М14/41 является один 40-мм ствол, гаубица второго «Крузейдера» «близкой поддержки» и ПТР системы Бойса могут при удаче лишь обездвижить наши танки, что весьма неприятно (они нужны для штурма деревни), но в целом ещё не фатально. Но радио у британцев есть и в случае невозможности огня из этой 40-мм пушки (уничтожения «Крузейдера», повреждения его орудия или полной гибели экипажа), а следовательно и невозможности закрыть проход от проникновения туда наших танков они вызывают подкрепление — два бронеавтомобиля «Даймлер», которые появляются с тыла и постараются пройти угрожаемым проходом к деревне, чтобы усилить её защиту, по пути истребляя всех попадающихся им на глаза итальянцев. Вне зависимости от выбранного игроком пути в случае больших потерь майор Ферретти передаёт нам под командование резерв для выполнения задачи. Пусть также на основании данных разведки наш командир предупредит нас при подходе к тому или иному проходу, с чем нам предстоит иметь дело.

Таков общий план миссии. Осталось только уточнить частности — деревню считаем захваченной и задачу выполненной, если в её области находится минимум десять наших солдат, причём это число включает членов экипажей танков, как в своих машинах, так и вне их; а из вражеских сил осталось в живых не более двух Томми. Если эти условия выполнены, посчитаем выживших британских солдат крайне деморализованными и не способными оказать какое-либо сопротивление. Очевидно, что если у нас осталось менее десяти берсальеров и танкистов (вне зависимости от числа и состояния танков), то поставленная задача не может быть выполнена и это будет условием поражения. Определим также взгляды майора Ферретти на то, когда стоит вводить в бой резерв. Пусть он сочтёт это нужным, если у нас из первоначальных сил не осталось больше ни одного исправного танка (танк считается исправным, если у него не повреждены ходовая часть с основным вооружением и в нём присутствует хотя бы один член экипажа) или общее число берсальеров и танкистов стало меньше 15 человек. Поскольку в дальнейшем достаточно часто будут встречаться условия на общее число сражающихся человек с той или иной стороны, без различия на их воинские специальности (член экипажа техники, номер расчёта орудия или пулемёта, пехотинец) и текущий статус («безлошадный» танкист продолжает сражаться в пешем строю или вставший к захваченному орудию пехотинец становится номером расчёта), то для краткости их именования используем подходящий юридический термин «комбатант». Если нужно, из множества комбатантов всегда можно выделить подмножества пехотинцев, номеров расчётов и членов экипажей техники.

Программируем скрипты

Когда задача стала ясной, не стоит пугаться её кажущегося объёма — и слона можно съесть по кусочкам. Сначала приступаем к «разрезке» этого «слона» на эти самые кусочки, но перед этим следует немного сказать пару слов о принципе работы скриптовой машины «Искусства войны». Поведение и своих, и вражеских войск управляется последовательностями управляющих инструкций, которые сгруппированы в блоки — так называемые триггера. Проводя аналогию с заводским цехом, можно сказать, что триггера - это рабочие. Сколько их работает в данный момент, определяется текущей обстановкой, если нужно, то один рабочий может позвать другого на помощь или отпустить помощника отдыхать в курилку, завершить работу, передать её результаты другому рабочему и пойти в курилку сам. Точно также и триггера — в зависимости от ситуации могут запускать и останавливать другие триггера, завершать свою выполненную работу, чтобы не занимать более ресурсы процессора компьютера. Работающий в данный момент триггер называется активным, их может быть несколько и они выполняются одновременно (в рамках процессорной «многозадачности» — когда процессор быстро-быстро переключается с одного дела на другое, в итоге за большое время в успевая сделать всю порученную ему работу). Также и в цеху могут одновременно работать сразу несколько рабочих над одним или разными делами. Те триггера, которым ещё предстоит вступить в дело или уже выполнившие свою работу, называются неактивными — как отдыхающие рабочие в курилке.

Как в производстве есть промежуточные результаты — полуфабрикаты и готовые детали, так и в скриптовой машине есть их полный аналог — это ячейки для хранения чисел и текстов, называемые переменными. Там, к примеру, может храниться количество танков противника или название группы боевых единиц, нужные для определения выигрышного положения дел. Причём следует иметь в виду, что часть таких ячеек доступна абсолютно всем триггерам (их названия начинаются с двух символов @@), а часть — только одному триггеру, где в них есть необходимость (их названия начинаются с одиночного символа @). Это схоже с ящиком с запчастями, доступным для всего цеха и с бардачком с необходимым инвентарём и деталями у конкретного рабочего, нужным только ему.

В соответствии с этим производим разбиение (по-научному декомпозицию) задуманного сценария на составные части. В нашем случае они достаточно просты — необходимо контролировать следующие ситуации:

  1. Наличие более 9 наших и менее 3 вражеских комбатантов в области деревни. Если это случилось — мы победили;
  2. Наличие в нашем распоряжении менее 10 комбатантов. Если это случилось — мы проиграли;
  3. Наличие в нашем распоряжении менее 15 комбатантов или полное отсутствие исправных танков с экипажем. Если это случилось в первый раз — мы получаем подкрепления;
  4. Невозможность стрельбы из основного оружия вражеского танка «Крузейдер» с 40-мм пушкой. Если это случилось — противник получает подкрепление;
  5. Наличие хотя бы одного нашего комбатанта к началу прохода с обороняющими его противотанковыми пушками и пулемётами. Если это случилось в первый раз — мы получаем соответствующее сообщение;
  6. Наличие хотя бы одного нашего комбатанта к началу прохода с обороняющими его «Крузейдерами». Если это случилось в первый раз — мы получаем соответствующее сообщение.

Каждый пункт — это триггер, в миссии «Forza, Carristi!» они имеют следующие названия:

  1. WinCheck — проверка выигрыша (от английских слов Win - выигрыш и Check — проверка);
  2. FailCheck — проверка поражения (Fail - провал и Check — проверка);
  3. Reinforcement — подкрепление нашим силам (Reinforcement - подкрепление);
  4. Brit_Daimler — подкрепление в виде «Даймлеров» вражеским силам (British Daimlers - британские «Даймлеры»);
  5. Warning_1 — 1-е предупреждение от майора Ферретти (Warning — предупреждение);
  6. 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

Поскольку в сценарии есть управляемые игроком силы, а также управляемые искусственным интеллектом союзные и вражеские боевые единицы, то в редакторе миссий организованы четыре армии с соответствующими характеристиками враждебности друг к другу, каждой из них при создании автоматически присваивается свой номер (незадействованная в окончательной версии сценария нейтральная армия с номером 3 использовалась при отладке). Конечно, номер армии можно указывать каждый раз в нужном месте, но гораздо лучше создать для каждой армии свою переменную, в которой он хранится и используется при надобности. Да, вместо числа 1 при наборе кода надо будет печатать @@army, но, представим, что из-за каких-нибудь правок в редакторе номер армии сменится, а он уже задействован путём непосредственного задания в доброй полсотне мест в самых разных триггерах. И придётся эти триггера и места выискивать, редактировать, с высокой вероятностью при этом можно забыть что-то исправить или изменить число 1, которое к номеру армии вообще отношения не имеет. Чтобы избежать этого, везде, где требуется номер армии, используем переменные с соответствующими именами. При необходимости смены номера достаточно исправить его только в определении оператором Set и всё снова заработает. Отметим, что эти переменные должны быть доступны абсолютно всем триггерам и потому их имена начинаются с @@. Первые четыре оператора Set в триггере init как раз и устанавливают такие переменные, записывая в них числовые значения номеров армий, выданные редактором миссий.

Организация переменной @disposition (обратите внимание на один @ в имени, поскольку эта переменная нужна только в триггере init и нигде больше) нужна для указания на заранее определённую в редакторе миссий прямоугольную область Initial_Area, где игрок может расположить нужным образом его стартовые силы перед выполнением задания. Оператор ActivateDispositionMode переводит игру в режим расстановки сил и приостанавливает выполнение скрипта init. После подтверждения игроком его готовности к бою выполнение триггера будет продолжено.

Оператор ChangeFogOfWar с параметром ENABLE включает «туман войны» (без него сражение нереалистично, но его отсутствие очень удобно для отладки сценария), оператор SetWorkArmy выбирает армию, с которой будут проводиться последующие операции. В нашем случае — армию игрока, о чём свидетельствует аргумент в виде переменной @@army. Все задания командования с их описаниями, реакцией на успешное выполнение или провал определяются заранее в редакторе кампаний под своими кодовыми обозначениями, в миссии их можно соответственно выдать, отменить, пометить выполненными или проваленными. В самом начале, естественно, мы должны получить задание и это выполняется оператором QuestActivate. В нашей миссии задание (оно единственное и проходит под кодовым обозначением MainTask) выдаёт майор Луиджи Ферретти (соответственно его позывной Luigi) и его текст будет отображаться на экране 15 секунд (отсюда число 15000 - временные интервалы в скриптовой машине почти всегда задаются в миллисекундах). В дополнение к оповещению о новом приказе оператор PingShow покажет на карте и мини-карте маркер местонахождения деревни-объекта наступления (белая цифра в красном кружке). Этот маркер будет иметь кодовое обозначение Ping_01, цифра 1 — то, что будет отображаться белым цветом в красном кружке, ключевое слово POINT - указатель на заранее определённую в редакторе миссий точку с названием Ultimate_target. На обоих картах на месте этой точки и появится белая единица в красном круге с тонкой чёрной окаёмкой.

Далее нам надо запустить все ранее упомянутые триггера, ответственные за решение своих частных задач. Это делается последовательностью операторов RunTrigger с указанием имени нужного триггера, запускаемого в параллель с уже работающими триггерами (вызов рабочих-помощников из курилки, возвращаясь к нашей аналогии). Единственная тонкость — пятисекундная задержка (оператор Delay) между запуском триггера FailCheck и WinCheck. Это некоторая мера предосторожности, оставшаяся от процесса отладки. Здесь она не нужна, когда все силы заранее расставлены по местам. Однако иногда вражеские боевые единицы находятся в скрытом состоянии и с началом сценария «вбрасываются» в него. Этот процесс занимает какое-то время и если поставить вызов проверки на победу сразу же после вброса, то может получиться так, что первый опрос численности сил противника опередит их появление на карте (не забываем об одновременности работы всех активных триггеров) и игрок получит мгновенный выигрыш (или проигрыш, в зависимости от ситуации). Задержка является одним из методов борьбы с этим нежелательным явлением. Однако, повторимся, в рассматриваемом сценарии такого нет, а потому задержка не нужна, хотя ничему и не вредит.

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

FailCheck

SetWorkArmy ( ARMY , @@army )
Set @friends = GetNUnits ( ARMY , @@army , HUMAN , CREW )

If ( @friends < 10 ) Then
  DestroyTrigger ( "WinCheck" )
  QuestFail ( "MainTask" , "Luigi" , 15000  )
  Delay ( 15000 )
  MissionFail ( )
  Halt
Endif
Delay ( 1000 )

Этот триггер ответственен за обработку условия поражения. Уже обсуждавшийся выше оператор SetWorkArmy устанавливает для последующей обработки силы, подконтрольные игроку. Следующий оператор Set помещает в переменную @friends число всех комбатантов в армии игрока. Последнее получается путём вызова функции GetNUnits с указанными аргументами. А далее оператором If-Then-Endif проверяется условие того, что число наших людей меньше десяти. Если это так, то оператор DestroyTrigger останавливает триггер WinCheck, ответственный за обработку условия победы, всё, победы не видать, оператор QuestFail отмечает задание под кодовым обозначением MainTask проваленным, реплика майора Ферретти будет отображаться на экране 15 секунд (см. выше в описании триггера init обсуждение оператора QuestActivate - его аргументы те же, что и у QuestFail). Оператор задержки Delay даёт нам возможность прочитать сообщение и осознать тяжесть поражения, а оператор MissionFail окончательно завершает игру поражением. Хотя после этого все триггера будут остановлены, останов посредством Halt ничему не вредит и только подчёркивает конец работы триггера.

Если наши силы насчитывают десять или более комбатантов, то ничего не происходит. Триггер даёт секундную задержку для обеспечения работы другим триггерам (во время исполнения любых других инструкций, отличных от Delay он сильно нагружает процессор) и начинает свою работу сначала. Так уж устроена скриптовая машина «Искусства войны» — если встретился конец кода триггера, а оператора останова Halt — нет, то он вновь начинает исполняться со своей первой строки. Таким образом, при явном отсутствии останова триггер выполняется до выхода из боя или завершения битвы тем или иным образом.

WinCheck

SetWorkArmy ( ARMY , @@army )
Set @friends = GetNUnitsInArea ( ARMY , @@army , HUMAN , "Village_Area" , CREW )
SetWorkArmy ( ARMY , @@enemy_army )
Set @foes    = GetNUnitsInArea ( ARMY , @@enemy_army , HUMAN , "Village_Area" , CREW )

If ( @friends > 9 AND @foes < 3 ) Then
  DestroyTrigger ( "FailCheck" )
  QuestWin ( "MainTask" , "Luigi" , 15000  )
  PingHide ( "Ping_01" )
  MissionWinButton ( "Activate" )
  Delay ( 120000 )
  MissionWin ( )
  Halt
Endif
Delay ( 1000 )

Этот триггер ответственен за обработку условия победы. Сначала оператор SetWorkArmy устанавливает для последующей обработки силы, подконтрольные игроку. Следующий оператор Set помещает в переменную @friends число всех комбатантов в армии игрока в прямоугольной области деревни с кодовым обозначением Village_Area, определённой заранее в редакторе миссий. Это число получается путём вызова функции GetNUnitsInArea с указанными аргументами. То же самое делается и по отношению к противнику — оператор SetWorkArmy устанавливает для последующей обработки силы, подконтрольные враждебному нам ИИ, число его комбатантов в области деревни записывается в переменную @foes.

А далее оператором If-Then-Endif проверяется условие того, что число наших людей больше девяти, а вражеских — меньше трёх. Если это так, то оператор DestroyTrigger останавливает уже триггер проверки поражения FailCheck, оператор QuestWin отмечает задание под кодовым обозначением MainTask выполненным, реплика майора Ферретти будет отображаться на экране 15 секунд (аргументы те же, что и у QuestActivate или QuestFail). Также, как подтверждение выполненного задания, оператор PingHide убирает маркер на карте и мини-карте — задача выполнена! Для желающих поскорее отпраздновать победу оператор MissionWinButton отображает надпись Cражение выиграно и кнопку Завершить бой, а для тех, кто хочет жестоко добить оставшиеся силы врага оператор задержки Delay даёт ещё две минуты игрового времени. Оператор MissionWin окончательно завершает игру победой. Остальное полностью идентично триггеру FailCheck.

Reinforcement

SetWorkArmy ( ARMY , @@army )
Set @tanks   = GetNUnits ( ARMY , @@army , TANKS , OK_WEAPON , OK_ENGINE , NOT_EMPTY )
Set @friends = GetNUnits ( ARMY , @@army , HUMAN , CREW )

If ( @tanks = 0 OR @friends < 15 ) Then
  SetWorkArmy ( ARMY , @@allied_army )
  ChangeArmy ( GROUP , "Group13" , @@army )
  SendBriefingMessage ( Reinforcements , "Luigi" , 15000 )
  Halt
Endif
Delay ( 1000 )

Этот триггер ответственен за решение майора Ферретти о предоставлении нам подкрепления. Как и ранее, оператор SetWorkArmy устанавливает для последующей обработки силы, подконтрольные игроку. Следующие два оператора Set помещают в переменные @tanks и @friends соответственно число исправных танков с экипажем и количество всех комбатантов в армии игрока. И то, и другое получаются путём вызова функции GetNUnits с указанными аргументами. А далее оператором If-Then-Endif проверяется условие того, что число наших людей меньше пятнадцати или количество исправных танков с экипажем обратилось в ноль. Если это так, то оператор SetWorkArmy устанавливает для последующей обработки силы, подконтрольные союзному нам ИИ. Правда всё время жаркого боя они стояли в сторонке, но у нас на виду, для ловли в свой адрес экспрессивно-обсценной итальянской лексики. Теперь оператор ChangeArmy с указанными аргументами (заданная в редакторе мисссий группа Group13 передаётся армии, чей номер хранится в переменной @@army, т. е. игроку) меняет положение дел самым радикальным образом — курить бамбук в покое им теперь уже точно не придётся... Посредством оператора SendBriefingMessage Луиджи Ферретти уведомляет нас о своём решении (текстовая строка под кодовым обозначением Reinforcements, заданная в редакторе кампаний , те же 15 секунд на экране). После этого триггер, полностью выполнивший свою задачу, останавливается оператором Halt. Если условие не выполнено, то через секунду триггер вновь его проверит.

Brit_Daimler

SetWorkArmy ( ARMY , @@enemy_army )
Set @tanks = GetNUnits ( UNIT , 156 , TANKS , OK_WEAPON , NOT_EMPTY )

If ( @tanks = 0 ) Then
  ReinforcementLand ( GROUP , "Group12" )
  RunCommand ( GROUP , "Group12" , STORM , RECT , "Village_Area" )
  Halt
Endif
Delay ( 1000 )

Этот триггер ответственен за предоставление подкрепления противнику. Ставший привычным оператор SetWorkArmy устанавливает для последующей обработки силы, подконтрольные враждебному нам ИИ. Последующий оператор Set помещает в переменную @tanks число танков с исправным орудием и с экипажем, уникальный идентификатор которых равен 156 (такое значение было выдано «Крузейдеру» с 40-мм пушкой редактором миссий, с точки зрения методологии и его было бы лучше записать в переменную, но используется оно только в одном месте)... Естественно, что результатом будет 0 (танк уничтожен или его орудие повреждено или весь экипаж убит) или 1 (танк может вести огонь). Как и в других случаях, получается это путём вызова функции GetNUnits с указанными аргументами. А далее оператором If-Then-Endif проверяется равенство нулю переменной @tanks. Если это так, то оператор ReinforcementLand вбросит заданную в редакторе миссий «спящую» (т. е. неактивную и невидимую) группу Group12 сил противника — два бронеавтомобиля «Даймлер». Оператор RunCommand даст этой группе приказ двигаться в прямоугольную область Village_Area (т. е. в деревню-цель атаки), атакуя любого врага (т. е. наши силы) на своём пути. Если они сумеют добраться до деревни, то там и останутся, усилив её гарнизон. После этого триггер, полностью выполнивший свою задачу, останавливается оператором Halt. Если условие не выполнено, то через секунду триггер вновь его проверит.

Warning_1

SetWorkArmy ( ARMY , @@army )
Set @men = GetNUnitsInArea ( ARMY , @@army , HUMAN , "Warning_Area_1" , CREW )

If ( @men > 0 ) Then
  SendBriefingMessage ( Warning_1 , "Luigi" , 15000 )
  Halt
Endif
Delay ( 1000 )

Этот триггер ответственен за выдачу предупреждения от майора Ферретти о противостоящих нам силах противника на выбранном пути. Оператор SetWorkArmy устанавливает для последующей обработки силы, подконтрольные игроку. Следующий оператор Set помещает в переменную @men количество всех комбатантов в армии игрока, находящихся в прямоугольной области Warning_Area_1 путём вызова функции GetNUnitsInArea с указанными аргументами. А далее оператором If-Then-Endif проверяется условие того, что число наших людей в этой области отлично от нуля. Если это так, то посредством оператора SendBriefingMessage Луиджи Ферретти уведомляет нас о данных разведки ( текстовая строка под кодовым обозначением Warning_1, заданная в редакторе кампаний , 15 секунд на экране ). После этого триггер, полностью выполнивший свою задачу, останавливается оператором Halt. Если условие не выполнено, то через секунду триггер вновь его проверит.

Warning_2

SetWorkArmy ( ARMY , @@army )
Set @men = GetNUnitsInArea ( ARMY , @@army , HUMAN , "Warning_Area_2" , CREW )

If ( @men > 0 ) Then
  SendBriefingMessage ( Warning_2 , "Luigi" , 15000 )
  Halt
Endif
Delay ( 1000 )

То же самое, что и Warning_1, только другие текст и область действия.

Заключение

Вот так слон и съедается по кусочку, из простых операций собираются сложные, чтобы воплотиться в жизнь в том или ином сценарии. Естественно, что рассмотренный нами пример охватывает далеко не все возможности скриптовой машины игры, однако, как автор надеется, он будет хорошей стартовой точкой в дальнейшем совершенствовании своих умений создателя сценариев. Поскольку код поставляемых в стандартном комплекте игры миссий полностью открыт для изучения, можно его фрагменты совершенно спокойно посмотреть на предмет, как на практике реализуются те или иные элементы игрового процесса. И в них они иллюстрируются даже лучше, чем в прилагаемом к игре руководстве. Но есть одно важное обстоятельство — перед написанием скриптов обязательно следует выполнить все предыдущие этапы создания сценария — разработку карты (если не подходят уже имеющиеся в поставке игры), идею битвы, распределение сил и средств сторон, разметку важных для миссии точек и областей на карте. Когда задача ясна, известны все определения областей, боевых единиц и их групп, можно сказать, что скрипты накладываются на них сами.