Проблема скриптования стоит ещё более остро, чем рисование новых карт, так что эта тема призвана подтянуть общее понимание того, как писать качественные и работоспособные скрипты.
Можно подумать, что чтобы написать качественный сценарий - нужно иметь высшее образование в области программирования, но спешу порадовать вас - это не так
Однако, здесь я не буду досконально разжёвывать как написать ф-цию и вообще запустить скрипт - на форуме такая информация уже имеется и причём очень хорошо изложенная, здесь я лишь дам ссылки и, может быть некоторые комментарии к тому, что было написано ранее.
Итак, начнём.
А с чего вообще начинается написание скрипта? Конечно же, с самого файла. По сути, скрипт - текстовый файл расширения lua с прописанным внутри кодом. Для написания своего сценарий сгодится даже обычный блокнот, но лучше использовать специальную программу, которая будет в этом архиве. Кроме того, там вы сможете найти "библию" любого картодела по скриптам, где описаны все применяемые команды/операторы(их так же можно именовать функциями) и справочник по редактору карт.
Товарищ Reks, ныне ушедший от нас, уже давно создал тему, в которой очень доступно и понятно объяснил самые основы, поэтому привожу ссылки на самые нужные нам сообщения: 1, 2, 3
Для начала внимательно прочитайте и переварите написанное. В принципе, это всё довольно легко и просто.
От себя лишь добавлю теоретическую часть для понимания, как вообще происходит работа скрипта, и зачем нужен оператор Suicide()
Язык lua таков, что он выполняется циклически, то есть весь файл работает сразу от начала и до конца, и так происходит много-много раз. В большинстве языков программирования выполнение идёт построчно, то есть есть одна главная программа, которая построчно выполняется. В нашем случае такого нет, у нас всё работает по функциям. "В чём разница?", - спросите вы. А в том, что мы имеем инициализирющую функцию под названием Init, из которой начинают запускаться другие функции. Init запускается вместе с миссией и его не надо вызывать самостоятельно. Если мы запускаем свою какую-нибудь функцию(слишком много функций, но вы терпите ), например, RunScript("Attack1", 3000), то эта самая Attack1 будет запускаться каждые 3000 миллисекунд, при условии, если внутри не будет прописан Suicide(), то есть:
function Init()
RunScript("Attack1",3000);
RunScript("Attack2",3000);
end;function Attack1()
DisplayTrace("Началась атака 1");
end;function Attack2()
DisplayTrace("Началась атака 2");
Suicide();
end;
В данном примере, при запуске карты, на экране сообщение "Началась атака 1" будет появляться каждые 3 секунды, а сообщение "Началась атака 2" будет выведено лишь единожды.
Suicide() - это такая замечательная штука, которая не даёт функциям зацикливаться, но с ней есть несколько тонкостей, которые важно понимать для построения правильного алгоритма.
Когда выполняется этот оператор, ф-ция моментально выключается, однако, её можно будет вновь использовать для вызова. Вызов функции двумя RunScript подряд будет приводить к зацикливанию даже при наличии в ней Суицидов. Например, если в Init записать RunScript("Attack2",3000); дважды.
Если вам нужно вызвать функцию определённое кол-во раз, то стоит дописать параметр после время вызова, который будет означать кол-ва срабатываний нужной функции RunScript("Attack2",3000,3);
А вот если нужен постоянный запуск, например для проверки какого-то условия через if, то в такой функции Suicide() не нужен, а вернее, нужен, но в другом месте.
function Init()
RunScript("Proverka1",3000);
end;function Proverka1()
if (GetNUnitsInArea(0,"zona") > 0) then
DisplayTrace("В зоне");
Suicide();
end;
end;
В данном случае Proverka1 будет запускаться каждые 3 секунды, пока не выполнится условие, то есть хотя бы один юнит стороны 0 не окажется в зоне "zona". Без Суицида проверка будет работать дальше и выдавать сообщение "В зоне" каждые 3 секунды, пока хотя бы один юнит находится в зоне. А вот если Суицид поместить между двумя end;, то проверка отработает лишь один раз после первого запуска и больше работать не будет, по сути своей это будет одноразовая проверка условия(не циклическая). На этом принципе строится выполнение простейших заданий, то есть пока врага сколько-то или он где-то, то происходит проверка на наличие юнитов в скриптовой группе или зоне(зависит от задания).
Это самые базовые знания для создания простеньких сценариев плана захватить то, уничтожить это, удержать вот здесь, доставить туда. На простеньком примере опишу каждое из таких заданий (открывайте руководство по луа и разбирайте все ключевые слова по ходу):
function Init()
RunScript("Obj0", 3000);
end;function Obj0()
ObjectiveChanged(0,0) -- Выдача первого(нумерация начинается с нуля) задания, у нас это будет, допустим, захват деревни
RunScript("Obj0end", 3000); -- Запуск проверки выполнения первого задания
Suicide();
end;function Obj0end()
if GetNUnitsInArea(1,"Village") < 2 then -- Если в зоне Village, которую мы рисуем в редакторе карт, юнитов врага меньше 2, то выполняется задание и выдаётся следующее. Желательно не писать в одной функции два и более ObjectiveChanged, иначе не будет появлятся окошко с заданием(не влияет на геймплей)
ObjectiveChanged(0,1); -- Отображение завершения первого
RunScript("Obj1", 3000); -- Запуск второго задания
Suicide();
end;
end;function Obj1()
ObjectiveChanged(1,0); -- Выдача второго задания, допустим, уничтожить стоящую на месте немецкую колонну
RunScript("Obj1end", 3000); -- Запуск проверки второго задания
Suicide();
end;function Obj1end()
if GetNUnitsInScriptGroup(100) < 1 then --Если юнитов(грузовиков, например) с номером 100 меньше 1(можно так же писать "== 0", но если случайно потерять одно из двух "=", то скрипт не запустится вообще), то задание выполняется
ObjectiveChanged(1,1);
LandReinforcement(1); --Подкрепление для врага, задаётся в редакторе карт(см. свиток Reinforcement Groups в редакторе карт)
RunScript("Attack", 10000); --Команды для юнитов подкрепления нужно задавать не сразу, а через некоторое время, потому что юниты развёртываются не мгновенно, а постепенно, и если команда будет задана пока юнита нет на карте, то он её не получит вообще.
RunScript("Obj2", 3000);
Suicide();
end;
end;function Obj2()
ObjectiveChanged(2,0); -- Выдача третьего задания, допустим, удерживать деревню в течении 5 минут
RunScript("Obj2end", 300000); -- Запуск проверки третьего задания(по факту там нет проверки, а сразу выполение через 5 минут)
RunScript("Proval", 10000); -- Запуск проверки провала задания
Suicide();
end;function Attack()
Cmd(19,10000,1,GetScriptAreaParams("Village")); -- Вызов бомбардировщиков, второй параметр для команд с авиацией всегда равен 10000, GetScriptAreaParams можно применять вместо координат
Cmd(3,20,GetScriptAreaParams("AttackPos")); -- Предположим, что все юниты в подкреплении имели номер 20, все атакующие будут идти в одну точку. Как сделать атаку более реалистичной будет расказано в следующем посте.
Suicide();
end;function Proval()
if GetNUnitsInArea(0,"Village") < 2 then -- Если юнитов игрока в деревне будет меньше 2-х, то поражение
ObjectiveChanged(2,2); -- Невыполнение задачи
Loose(); -- Вызов окошка поражения
Suicide();
end;
end;function Obj2end()
ObjectiveChanged(2,1); -- Выполнение третьего задания
KillScript("Proval"); -- Принудительная остановка проверки на невыполнение
RunScript("Obj3", 3000); -- Запуск четвёртого задания
Suicide();
end;function Obj3()
ObjectiveChanged(3,0); -- Выдача четвёртого задания, допустим, доставить прибывшего офицера к штабу
LandReinforcement(2); -- Прибытие офицера
RunScript("Obj3end", 3000); -- Запуск проверки четвёртого задания
Suicide();
end;function Obj3end()
if GetNScriptUnitsInArea(80,"Shtab") > 0 then -- Если офицер с сриптовым номером 80 прибудет в зону "Shtab", то победа
ObjectiveChanged(3,1); -- Выполнение четвёртого задания
Win(0); -- Вывод окошка победы
Suicide();
end;
end;
Такой скрипт пишется за полчаса. Как видим, не используя чего-то сверхсложного можно получить вполне интересную миссию
В следующих сообщениях постараюсь осветить такую тему, как переменные и использование готовых кусков скрипта, которые я буду приводить далее.
Здесь можете задавать любые вопросы касательно скриптов, идей для каких-либо алгоритмов, работы каких-то конкретных функций и т.д.