Скриптование карт. LUA

  Модератор: Yaguar

 
Аватара пользователя
Yaguar Не в сети
Генерал-полковник
Генерал-полковник
 
Сообщений: 78
Зарегистрирован: 03 ноя 2011, 22:40
Cпасибо сказано: 19
Спасибо получено: 59 раз в 42 сообщениях

Медали: 10
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС II ст. (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1) 50-лет Карибскому Кризису-1962 (1)
3 года форуму (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 20
 
Добавить очки репутации Уменьшить очки репутации

Скриптование карт. LUA

Сообщение Yaguar » 13 фев 2012, 14:12

Уроки от DarthVader:

Урок первый.
"Написание функций и их запуск".
На карте имеется автомобиль которому мы присвоили скриптовый номер 100 (как присваивать надеюсь не надо объяснять). Наша задача - заставить его перемещаться в определенную точку в определенное время. Простейший скрипт данного перемещения (да и вообще просто простейший скрипт):

function Init()
RunScript("MoveCar", 3000);
end;

function MoveCar()
Cmd(0, 100, 916, 1516);
Suicide();
end;

Начнем по порядку. Функция - это небольшой блок/подпрограмма выполняющая определенное действие. В данном скрипте изображено две функции: Init и MoveCar. Функция всегда начинается с ее объявления словом function, и заканчивается оператором End. Все что между ними - является телом функции. Правописание как вы уже догадались следующее:
function <имя ф-ции>() - после function обязательный пробел, перед () пробела нет, после () точка с запятой не ставится. Точка с запятой ставится после End, при чем обязательно.
Точка с запятой обычно обозначает окончание чего то, будь то функция, или оператор, или команда. Так же для удобства (хотя это не обязательно) функции еще отделяют друг от друга пустой строкой, что бы при проверке было легче читать и текст не слипался в бесконечный непрерывный поток строк.
Рассмотрим теперь обе функции поочередно. Функция Init - это функция запуска. Она неотемлемая часть любого скрипта, так как все остальные функции скрипта необходимо вызывать. Для этого и служит Init. Она запускается автоматически в самом начале, и приводит в действие (вызывает) остальные функции скрипта. Без Инита скрипт работать не будет. Ф-ция Init срабатывает только один раз. Она как стартер в автомобиле.
Как мы видим, тело функции содержит только одну команду/оператор (в данном примере):

RunScript("MoveCar", 3000);

Операторы, в отличии от функций заканчиваются точкой с запятой, без End-а; функция может содержать в себе любое кол-во операторов.
В ворд-файле 18_Lua есть подробное описание всех команд/операторов, используемых при написании скриптов к блицу. Как видим:
RunScript (“Name”, iPeriodicity , [iNumberOfRepetitions])
Запускает сценарную функцию с именем Name каждые iPeriodicity миллисекунд. Необязательным параметром iNumberOfRepetitions можно указать число повторений вызовов.
То есть, применительно к нашему случаю оператор RunScript должен запускать функцию MoveCar каждые 3 секунды. Однако сдесь есть нюанс. Оператор будет срабатывать каждые 3 секунды только в том случае, если функция (в которой он находится) будет постоянно активна (включена). А так как функция Init срабатывает только один раз (только в первый цикл) и сразу отключается, то следовательно оператор RunScript сработает только один раз (через 3 секунды после запуска ф-ции Init).
Сразу оговорюсь, что один цикл - это полное прочтение программой (игрой) содержания скрипта от верха до низа (программа читает скрипт построчно). Игра повторяет цикл постоянно в течении всей миссии. В зависимости от "длинны скрипта" время цикла может немного колебаться, однако это все равно будут миллисекунды.
Что то я немного ушел в сторону (хотя информация тоже нужная). Итак, мы видим, что при запуске миссии ф-ция Init по средству оператора RunScript запустила ф-цию MoveCar с задержкой 3 секунды. Все. Ф-ция Init выполнила свое предназначение, и пока ее можно больше не вспоминать.
Перейдем ко второй функции - MoveCar:

function MoveCar()
Cmd(0, 100, 916, 1516);
Suicide();
end;

Как видим, она содержит два оператора. Каждый из операторов обязательно заканчивается точкой с запятой и начинается с новой строки! Операторы выполняются в порядке очередности один за другим. Синтаксис операторов можно посмотреть в ворд-файле 18_Lua.

Оператор Cmd:

GiveCommand (iAction, iScriptID [, params ...])
Дает команду iAction юниту со сценарной группой iScriptID. Необходимые параметры params должны быть перечислены через запятую. Cmd — синоним GiveCommand. Команда отдается юниту сразу же. См. значения команд в разделе «Команды юнитов» (в ворд файле 18_Lua). Все координаты выдаются в сценарных (SCRIPT) точках.
То есть в момент срабатывания ф-ции MoveCar, а следовательно и оператора Cmd, будет дана команда 0-перемещаться юниту (или юнитам) со скриптовым номером 100 в точку с координатами х=916, у=1516.
Далее идет оператор Suicide(); Если Suicide вызывается в теле функции, вызванной через RunScript, то после её выполнения функция больше не вызовется. То есть после срабатывания этого оператора в последующих циклах функция будет уже отключена. Она останется отключенной либо до окончания миссии, либо до момента, когда эта функция вновь будет вызвана с помощью любой другой активной функции по средству оператора RunScript.
В основном Suicide нужна для того, что бы юнит получил команду только один раз, а не получал ее с каждым новым циклом. То есть что бы ф-ция сработала, и сразу же отключилась.
Ну вот собственно и все. Теперь, когда мы все надеюсь поняли, опишем вышесказанное в трех строчках:
1) При запуске миссии срабатывает Init, который запускает ф-цию MoveCar через 3 сек.
2) По истечению 3 секунд запускается ф-ция MoveCar которая отдает команду машинке "100" двигаться в точку 916-1516.
3) Машинка отправилась в путь, а функция завершила свою работу и более не активна.
Пока все. Можете самостоятельно попробовать разобраться в нескольких следующих уроках.


Урок второй.
Добавление второй функции с последовательным набором команд.
Как и в первом уроке, у нас есть авто со скриптовым номером 100. Но теперь на карту добавлен грузовик под номером 101. Авто действует по тому же принципу, что и в уроке-1. Грузовик немного иначе. Ниже приведен скрипт второго урока:

function Init()
RunScript("MoveCar", 3000);
RunScript("MoveTruck", 7000);
end;

function MoveCar()
Cmd(0, 100, 916, 1516);
Suicide();
end;

function MoveTruck()
Cmd(0, 101, 1583, 223);
QCmd(0, 101, 1890, 1570);
QCmd(0, 101, 1100, 1890);
Suicide();
end;

Как видим, это тот же скрипт, что был рассмотрен в первом уроке, но в него добавлена новая функция – MoveTruck. Эта функция, как и ф-ция MoveCar, запускается через Init. С момента старта миссии ф-ция MoveCar запускается через 3 секунды, а MoveTruck – через 7 секунд. Как видим, обе функции запускаются не зависимо друг от друга (только с разной временной задержкой), и поэтому будут работать параллельно.
Рассмотрим новую ф-цию MoveTruck. Она очень похожа на ф-цию MoveCar, но имеет больше операторов. С оператором Cmd мы уже знакомы, а вот QCmd – необходимо рассмотреть.
Из справочника 18_Lua:

GiveQCommand (iAction, iScriptID ,[ params ...])
Добавляет команду iAction в список команд юниту со сценарной группой iScriptID. Необходимые параметры params должны быть перечислены через запятую. QCmd — синоним GiveQCommand. Функция GiveQCommand может вызываться «пачкой», например, для составления промежуточных точек пути, по которому будет перемещаться юнит. В начале такой пачки должна быть функция GiveCommand, чтобы команда отдалась юниту сразу же. См. значения команд в разделе «Команды юнитов». Все координаты выдаются в сценарных (SCRIPT) точках. С помощью GiveQCommand (QCmd) можно добавлять команды в пул стартовых команд юнитов.

Говоря другими словами, с помощью оператора QCmd, юниту можно добавить любое число (любых доступных этому юниту) последовательных команд, но только после того, как был использован оператор Cmd. Эти команды будут выполняться подобно тому, как если бы вы отдавали приказы в игре, зажав клавишу Шифт. То есть – последующая команда начнет выполняться только после того, как будет полностью выполнена предыдущая.
Сдесь я сразу же оговорюсь о некоторых тонкостях выполнения последовательных команд:
1) Если предыдущая команда невыполнима в принципе, то юнит переходит к выполнению следующей команды, не нарушая таким образом правильной работы скрипта.
Например:
Cmd(7, 200); - пехоте с номером 200 выдана команда «7»-покинуть здание
QCmd(0, 200, 1890, 1570); - пехоте добавлена команда «0»-перемещаться в точку (1890, 1570).
Может возникнуть ситуация, когда здание будет разрушено раньше времени, но пехота успеет выскочить из него и выжить. В таком случае, когда сработает соответствующая ф-ция с выше указанным набором команд, возникнет ситуация, при которой пехоте 200 уже неоткуда будет выходить (пехота уже на «улице»). В подобных случаях игра просто переходит к следующей команде в списке.

2) Предыдущая команда невыполнима физически, но выполнима в принципе. Такая ситуация приводит к «подвисанию» юнита (не скрипта) и прерыванию всей последовательности команд. Сейчас поясню, что это значит.
Например:
Cmd(0,200,1000,2000);
QCmd(0, 200, 3000, 4000);
В этом кусочке скрипта юниту 200 дана стартовая команда двигаться в точку (1000,2000). При этом юнит, к примеру, обязательно пересечет реку через деревянный мост. Но мост, оказался взорванным раньше времени. Юнит, не находя пути к заданной точке следования, практически неизбежно застопорится где-нибудь на карте. И даже если мост в дальнейшем будет починен, юнит уже не будет продолжать выполнять поставленную последовательность команд. Я думаю у всех случалось подобное в игре, когда юнит (например вследствии пробки на мосту) уезжал куда то в сторону вдоль реки (пытаясь найти обходной путь), а потом просто замирал у какого то края карты. И разшевелить его можно было, только выдав новую команду. Так же и сдесь.

3) Если в процессе выполнения последовательности команд, юниту из какой либо другой ф-ции будет выдана новая команда по средству оператора Cmd, то эта старая последовательность прервется и немедленно начнется выполнение новой команды. Другими словами оператор Cmd более приоритетный чем оператор QCmd.

4) Не забывайте «отключать» ф-цию с помощью оператора Suicide по окончанию ее работы, так как это может привести к ее зацикливанию. Применительно к ф-ции MoveTruck – можно сказать, что если бы у нее в конце не стоял оператор Suicide, то эта ф-ция запускалась бы каждые 7 секунд (см. Init), и каждые 7 секунд юнит 101 получал бы одну и ту же команду: Cmd(0, 101, 1583, 223);

Итак, разобравшись с принципом работы операторов Cmd и QCmd мы теперь видим, что при запуске ф-ции MoveTruck, грузовик 101 получает последовательную команду – двигаться по трем точкам.

Теперь давайте рассмотрим немного другой вариант скрипта урока-2, в котором ф-ции MoveCar и MoveTruck остаются практически теми же, но запускаются не параллельно, а последовательно. Текст скрипта приведен ниже:

function Init()
RunScript("MoveCar", 3000);
end;

function MoveCar()
Cmd(0, 100, 916, 1516);
RunScript("MoveTruck", 4000);
Suicide();
end;

function MoveTruck()
Cmd(0, 101, 1583, 223);
QCmd(0, 101, 1890, 1570);
QCmd(0, 101, 1100, 1890);
Suicide();
end;

Как видим сдесь Init запускает только одну ф-цию – MoveCar. Ф-ция MoveTruck запускается из тела ф-ции MoveCar. То есть, пока полностью! не сработает ф-ция MoveCar (так как оператор RunScript стоит в конце), ф-ция MoveTruck не будет запущена. Как видим, MoveTruck в итоге так же запускается через 3+4=7 секунд (в действительности на пару миллисекунд позже).
Данный порядок вызова функций более удобный при составлении скриптов, так как позволяет точно согласовывать по времени запуск очередных функций с происходящим на карте. А так же знание данного порядка вызова будет необходимо при изучении следующего (и самого незаменимого!) оператора if then else, проверяющего выполнение некоего заданного условия. Но уже в следующем уроке.

Разбор полетов Basic Lua Sessions.



Урок третий.
Проверка выполнения заданного условия.
Откройте в редакторе карт учебную карту Lesson3.bzm, которая хранится в папке Basic Lua Sessions. В принципе, для полного понимания каждого из учебных скриптов, вы должны открывать в редакторе карту, соответствующую уроку. Если вы не делали этого на прошлых уроках, то советую вам это сделать.

На карте Lesson3.bzm (как и на предыдущей Lesson2) размещены - легковое авто с номером 100, грузовик с номером 101, дом (ему присвоен номер 10), и несколько мелких объектов. Как видим, на карте появилось два новых юнита – пехота с номером 103, и пехота с номеом 104. Оба этих взвода объединены в скриптовое подкрепление номер 103. Список подкреплений можно увидеть в свитке Reinforcement Group (на рабочей панели слева) в окошке Groups. Если выделить интересующее подкрепление, то в окошке Group Propertie появится список всех скриптовых групп, входящих в скриптовое подкрепление. При составлении скриптов не путайте скриптовые номера групп юнитов со скриптовыми номерами подкреплений! Так же на карте появилась скриптовая зона - Farm, обозначенная зеленой рамкой. Список скриптовых зон можно увидеть в свитке Map Tools.

Ниже мы рассмотрим скрипт урока-3. Он выполняет следующие действия:
1) Авто 100, и грузовик 101 двигаются к дому (урок 1-2);
2) Как только авто и грузовик оба окажутся возле дома, при чем внутри скриптовой зоны Farm, на карту высаживается подкрепление 103;
3) Пехота движется к дому. Один взвод размещается возле дома, а второй заходит в дом.

Текст скрипта:

function Init()
RunScript("MoveCar", 3000);
RunScript("FarmCheck", 2000);
end;

function MoveCar()
Cmd(0, 100, 916, 1516);
RunScript("MoveTruck", 4000);
Suicide();
end;

function MoveTruck()
Cmd(0, 101, 1583, 223);
QCmd(0, 101, 1890, 1570);
QCmd(0, 101, 1100, 1890);
Suicide();
end;

function FarmCheck()
if GetNUnitsInArea(0, "Farm") == 2 then
RunScript("SquadArrive", 1000);
Suicide();
end;
end;

function SquadArrive()
LandReinforcement(103);
RunScript("SquadMove", 2000);
Suicide();
end;

function SquadMove()
Cmd(0, 103, 1530, 1320);
Cmd(6, 104, 10);
Suicide();
end;

Как видим часть скрипта идентична уроку-2. Рассмотрим новые функции. Начнем по порядку. В Init у нас запускается ф-ция FarmCheck через 2 секунды. Эта функция содержит новый (и очень полезный оператор if). Для дальнейшей работы со скриптами его обязательно необходимо изучить.

Оператор IF THEN ELSE – оператор проверяющий выполнение заранее заданного условия. Он действует по следующему принципу:

IF (если выполняется) «УСЛОВИЕ»
THEN (тогда делай) «ДЕЙСТВИЕ-1»
ELSE (в противном случае делай) «ДЕЙСТВИЕ-2»

Если в операторе отсутствует часть ELSE, тогда в случае невыполнения условия, оператор IF бездействует до тех пор, пока условие не выполнится. Рассмотрим его на примере ф-ции FarmCheck.

function FarmCheck()
if GetNUnitsInArea(0, "Farm") == 2 then
RunScript("SquadArrive", 1000);
Suicide();
end;
end;

Следует читать оператор так: if (если) GetNUnitsInArea(0, "Farm") == 2 (количество юнитов игрока «0» в зоне "Farm" = 2) then (тогда) RunScript("SquadArrive", 1000) (запустить ф-цию "SquadArrive" через 1 сек.). Suicide – отвечает за то, что ф-ция FarmCheck отключится сразу же после срабатывания строки RunScript("SquadArrive", 1000);
Оператор IF THEN ELSE по сути является небольшой вспомогательной функцией внутри основной функции, поэтому его окончание, так же необходимо обозначать словом end; В ф-ции FarmCheck первый end обозначает окончание оператора IF, а второй end – окончание самой ф-ции FarmCheck.
Внимание! Если вы забудете закрыть оператор IF эндом, весь ваш скрипт будет нерабочим!
Синтаксис оператора IF THEN ELSE чем то похож на синтаксис ф-ций, за исключением отсутствия названия и наличия условия:
if (пробел) («условие», если большое то в скобках) (пробел) then (далее с новой строки)
(«действие» - набор операторов или команд, составляющие тело вспомогательной функции if) (далее с новой строки)
end; - окончание вспомогательной функции (оператора) if.

Синтаксис знаков, позволяющих задать условие:
А==B (А равно B, пишется двойной знак равенства!);
А>B, A<B, A>=B, A<=B – стандартные знаки неравенства
A~=B (A не равен В, перед равно стоит знак «тильда»)

Итак, разобравшись с оператором if, мы так же разобрались и с ф-цией FarmCheck. Мы видим, что как только в зоне Farm, количество юнитов игрока «0» будет равно 2, оператор RunScript запустит ф-цию SquadArrive. Ну а эти «два» юнита, как не сложно увидеть из скрипта, - легковой автомобиль и грузовик.

Ф-ция SquadArrive:

function SquadArrive()
LandReinforcement(103);
RunScript("SquadMove", 2000);
Suicide();
end;

Как видим она предельно проста, и содержит два оператора. Первый LandReinforcement(103) – мгновенно высаживает на карту скриптовое подкрепление под номером 103.
(Внимание! Как только вы назначите в редакторе карт скриптовое подкрепление и придатите ему определенное количество скриптовых групп, то все эти скриптовые группы будут отсутствовать на игровой карте до тех пор, пока вы не вызовите их с помощью оператора LandReinforcement в составе назначенного скриптового подкрепления! В тоже время в окне редактора карт они будут отображаться!).
Второй оператор RunScript("SquadMove", 2000) запускает ф-цию SquadMove через 2 секунды. Что делает ф-ция SquadMove, вы уже должны уметь разобраться сами.
Остановлюсь только на небольшом нюансе. Если вызываемое подкрепление достаточно велико, к примеру 50-100 юнитов, то игра может не успеть их высадить за несколько секунд. По этому, в случае, если вам необходимо сразу же после высадки выдать команды юнитам этого подкрепления, рекомендую запускать ф-цию с набором команд для этих юнитов не через 1-2 секунды, а не менее чем через 5-10 секунд. У вас просто может возникнуть ситуация, когда подкрепление еще будет «высаживаться», а ф-ция с командами уже сработает. В этом случае команду получит только та часть подкрепления, которая успела высадиться, остальная же будет бездействовать.

Добавление служебной функции для облегчения контроля за работой миссии (используется только на стадии тестирования).

function DebugView()
Password("Panzerklein");
DisplayTrace("Amazing! This really works");
ShowActiveScripts();
--God(0, 2);
Suicide();
end;

ф-ция DebugView содержит набор следующих служебных команд:
Password("Panzerklein") – активирует режим паролей;
DisplayTrace("Amazing! This really works") – стандартный оператор вывода текста на экран. В данном случае он нужен для того, что бы понять, работает скрипт или нет. Если в тексте скрипта нет синтаксических и/или орфографических ошибок, то при запуске миссии на экране появится строка Amazing! This really works. В противном случае – скрипт не работает, и требует тщательной проверки на ошибки (самая нудная часть работы картодела!!!!!!!!!!!)
ShowActiveScripts() – выводит через диалоговое окно список работающих на данный момент ф-ций скрипта. Диалоговое окно (или как оно там называется?) открывается клавишей «тильда» во время игры.
--God(0, 2); - режим «бога». Значение параметров в скобках смотрите в справочнике.
Два тире подряд в начале строки обозначают, что вся эта строка – всего лишь комментарий к программе (режим бога не включится). Комментарии никуда не выводится, и нужны только для пояснений или подписей внутри самого скрипта. Подобным образом, поставив в начале строки два тире, вы можете написать любую информацию, используя при этом любые символы. Программа автоматически пропускает (не читает) все строки, которые начинаются с двух тире. Если потребуется включить режим «бога», то для того что бы вышеуказанная строка --God(0, 2) стала активной, уберите оба тире.
При необходимости, можно ввести в ф-цию DebugView еще одну строку:
ChangeWarFog(N); - показывает зону видимости и юниты игрока N.
Соответственно, что бы вся ф-ция DebugView заработала, ее нужно запустить, к примеру через Init, добавив в него строку:
RunScript(“DebugView”,1000);
Примечание. В принципе, ф-цию DebugView можно и не вводить в состав скрипта при проверке. Но тогда все необходимые пароли вам прийдется вводить непосредственно в игре при каждом запуске вашей миссии.

Сценарная область — механизм, позволяющий обращаться к поименованной области карты из сценария. В частности, сценарий может проверять соблюдение или несоблюдение определенных условий в границах сценарной области.

Чтобы задать сценарную область:

откройте свиток Map Tools (Инструменты карты) на панели Workspace (Режим);
щелкните по радиокнопке Script Area Tool (Инструмент сценарной области);
выберите форму создаваемой сценарной области с помощью радиокнопок Rectangle (Прямоугольник) и Circle (Круг);
растяните области на карте, перемещая мышь при нажатой левой кнопке;
задайте имя сценарной области в появившемся окне.
Имя новой сценарной области появится в списке на панели Workspace (Режим).

Для удаления сценарной области выделите ее имя в списке на панели Workspace (Режим) и нажмите кнопку Delete (Удалить) над списком.


«Такой вот вопрос: откуда брать названия функций?

К примеру- мне надо вызвать штурмовики или же переместить группу юнитов (технику) при выполнения определенного условия в определенное место»

- «Придумываешь сам. Можешь назвать GitlersSturmovik, например.
Только функции заданий должны называться Objective0, Objective1,...Objective10 и т.д. Эти менять не стоит.»
Примеры:
Подрыв объекта:
DamageObject (iScript, fDamage) fDamage=0 тогда объект уничтожается вставишь в:

function Init()
DamageObject (iScript, 0) хана мосту
end;

АРТ. УДАР

function Artbomb21544()
Cmd( 16, 215, GetScriptAreaParams("art21544"));
RunScript("Artstop21546",90000);
Suicide();
end;

function Artstop21546()
Cmd( 9, 215);
Suicide();
end;

215 - скриптовые номера пушек

Проверка условия ПОБЕДЫ
function CheckWin()
if ( GetNUnitsInParty(1) <= 5) then – если юнитов игрока 1 меньше равно 5
DisplayTrace("Win!!!");
Win(0); -- победа
Suicide();
end;
end;

Проверка условия ПОРАЖЕНИЯ

function ToBeDefeated()
if (GetNUnitsInParty(0)) == 0 then -- если юнитов игрока 0 (наших) = 0
Loose(); -- поражение
Suicide();
end;
end;

-- блок скриптов, отвечающих за рождение грузовиков взамен погибших

function GiveTrucks()
if ((GetNUnitsInScriptGroup(20001) + GetNUnitsInScriptGroup(20002)) < 1) then -- если сумма юнитов в группах 20001 и 20002 меньше 1
LandReinforcement(20002); -- высадка подкрепления 20002
end;
end; -- поскольку отсутствует команда Suicide(); этот блок выполняется бесконечно

function GiveEngineers()
if ((GetNUnitsInScriptGroup(20003) + GetNUnitsInScriptGroup(20004)) < 1) then
LandReinforcement(20004);
end;
end;

function GiveMedicine()
if ((GetNUnitsInScriptGroup(20005) + GetNUnitsInScriptGroup(20006)) < 1) then
LandReinforcement(20006);
end;
end;

function GiveFuel()
if ((GetNUnitsInScriptGroup(20007) + GetNUnitsInScriptGroup(20008)) < 1) then
LandReinforcement(20008);
end;
end;

Стандартная функция выдачи текстовика заданий

function Objective1()
ObjectiveChanged(1,0); -- задание 1 помечается активным
Suicide();
end;

Команда помечает задание 1 выполненным

ObjectiveChanged(1,1);
__________________________________________________
-- функция победы, выполняется проверка глобальных переменных temp.chapterX.objective.X

function ToWin_00_00() if ( GetIGlobalVar("temp.chapter5.objective.0", 0)
* GetIGlobalVar("temp.chapter5.objective.1", 0)
* GetIGlobalVar("temp.chapter5.objective.3", 0)
* GetIGlobalVar("temp.chapter5.objective.4", 0)
* GetIGlobalVar("temp.chapter5.objective.2", 0) == 1) then
Win(0); -- победа
Suicide();
end;
end; -- в конструкции if-then необходимо два раза написать end;

Проверка выполнения задания:

function Check3()
if GetNUnitsInArea(0, "WILL01") >= 1 then
DisplayTrace("Вы нашли боевую технику и наших товарищей!!! Готовьте их к бою, командир!");
ChangePlayer (701, 0); -- юниты с ID 701 передаются игроку 0 (нам)
SetIGlobalVar("temp.chapter5.objective.0", 1); -- установка глобальной переменной, которая задействована в проверке ПОБЕДЫ
Suicide();
end;
end;
______________________________________________
-- приказ юнитам выдвинуться в указанную скриптовую зону
function R_01()
Cmd(3, 999, GetScriptAreaParams("G_01")); -- 3 - атаковать, 999 - ID юнитов, GetScriptAreaParams("G_01") - указывает область для атаки
Suicide();
end;

Вот вам тоже, относительно небольшой скрипт. Но очень полезный при организации атак противника:
function A207()
LandReinforcement(207);
RunScript("A2071",10000);
RunScript("A207Stop",900000);
Suicide();
end;

function A2071()
local a,b,c;
for a=2071,2078,1 do
b=(a*10)+1;
c=(a*10)+2;
Cmd(3,b,GetScriptAreaParams(b));
Cmd(3,c,GetScriptAreaParams(b));
end;
RunScript("A2072",5000);
Suicide();
end;

function A2072()
local a,b,c,d,e;
for a=2071,2078,1 do
b=(a*10)+1;
c=(a*10)+2;
for d=1,7,1 do
e=((a*10)+d);
if((GetNUnitsInScriptGroup(b,1)==GetNScriptUnitsInArea(b,e))and(GetNUnitsInScriptGroup(c,1)==GetNScriptUnitsInArea(c,e))and((GetNUnitsInSc riptGroup(b,1)>0)or(GetNUnitsInScriptGroup(c,1)>0)))then
Cmd(3,b,GetScriptAreaParams(e+1));
Cmd(3,c,GetScriptAreaParams(e+1));
Suicide();
end;
end;
end;
RunScript("A2073",5000);
Suicide();
end;

function A2073()
RunScript("A2072",5000);
Suicide();
end;

function A207Stop()
KillScript("A2072");
KillScript("A2073");
Suicide();
end;

Этот скрипт организовывает атаку группы из восьми танков, при каждом из которых закреплен взвод пехоты. Каждый из взводов пехоты следует за своим танком. Танки двигаются по восьми последовательным зонам. У каждого танка свои зоны. В данном случае их всего 64 зоны (по 8 на каждый танк). На каждой из зон танк останавливается и ждет пока его догонит его пехота, и далее они вновь продолжают движение. Таким образом достигается эффект взаимодействия танка с пехотой. Скрипт так же учитывает случаи, если ко то из пары убит. Тогда танк или пехота уже не ждут своего мертвого напарника, а продолжают атаку в одиночку. Единственное слабое место - если танк подорвется на мине, пехота без него дальше не пойдет, так как танк еще жив.
В скрипте используется сквозная система номерации как скриптовых номеров юнитов, так и их зон.
В приведенном скрипте она следующая:
Атакует группа 207
Группа состоит из восьми пар: 2071 - 2078;
В каждой паре юниты так же имеют отдельные номера: танк 20711, пехота 20712 (к номеру пары приставлена одна цифра, танк - 1, пехота - 2);
Названия зон следования для каждой пары состоит из номера пары и приставленного к нему номера (по счету) зоны. Пример последовательности зон для пары 2071: 20711, 20712, 20713, ... , 20718. Пара 2071 последовательно двигается в боевой готовности по выше написанным восьми зонам. Каждая из пар движется параллельно, каждая по своей восьмерке зон.

Скрипт легко копируется, и в нем (помимо названий функций) нужно только сменить номера пар на новые. Самое сложное для данного скрипта - не сделать опечатки при раздаче номеров юнитам и при раздаче номеров зонам (все таки 64 зоны нужно назвать).
Скрипт легко укоротить, или расширить до нужного количества пар и нужного количества зон.
Однако, он немного жрет памяти, так как обсчитывает много информации на единицу времени. При движении по зонам 8 на 8, это уже немного ощущается. По этому, я не рекомендую использовать паралельно больше 2х таких атак. В конце скрипта есть функция остановки данного блока. Я его ввел, что бы по истечении определенного времени (за которое атака гарантированно успеет полностью завершиться) принудительно остановить работу блока, и немного разгрузить игру.
 

 
Аватара пользователя
клерик Не в сети
Автор мода
Автор мода
 
Сообщений: 389
Зарегистрирован: 08 ноя 2011, 22:25
Cпасибо сказано: 179
Спасибо получено: 302 раз в 193 сообщениях

Медали: 14
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС I ст. (1) За Службу Родине в ВС II ст. (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1)
Орден Александра Невского (1) 50-лет Карибскому Кризису-1962 (1) 3 года форуму (1) Высшая награда форума (1) Красная Звезда к 9 мая (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 120
 
Добавить очки репутации Уменьшить очки репутации

Re: Скриптование карт. LUA

Сообщение клерик » 06 май 2013, 12:42

Скрипт «Организация атаки нескольких групп по определенному маршруту»

function AttackNZone(n ,GroupID)
Group_List[GroupID].CurrentZoneNumber = n;
variable_name = string.format("temp.Group"..tostring(GroupID).."CurrentZoneNumber");
SetIGlobalVar(variable_name, n);
local x, y = GetScriptAreaParams(GetNZoneName(Group_List[GroupID].CurrentZoneNumber ));
Cmd(3, GroupID, x, y);
end;

function SwarmNToNextWayPoint(GroupID)

Group_List = {[201] = {CurrentZoneNumber = GetIGlobalVar("temp.Group201CurrentZoneNumber", 1)},
[202] = {CurrentZoneNumber = GetIGlobalVar("temp.Group202CurrentZoneNumber", 1)},
[203] = {CurrentZoneNumber = GetIGlobalVar("temp.Group203CurrentZoneNumber", 1)},
[311] = {CurrentZoneNumber = GetIGlobalVar("temp.Group311CurrentZoneNumber", 1)},
[415] = {CurrentZoneNumber = GetIGlobalVar("temp.Group415CurrentZoneNumber", 1)}}


if IsRobotNGroupInCurrentZone(GroupID) then

if Group_List[GroupID].CurrentZoneNumber == 10 then
return;
else
AttackNZone(Group_List[GroupID].CurrentZoneNumber + 1, GroupID);

return;
end;
else
AttackNZone(Group_List[GroupID].CurrentZoneNumber, GroupID);
end;

end;

function GetNZoneName(n)
if n then
return "za"..n;
end;
end;

function EnemyAttackN1()
SwarmNToNextWayPoint(201);
end;

function EnemyAttackN2()
SwarmNToNextWayPoint(202);
end;
function EnemyAttackN3()
SwarmNToNextWayPoint(203);
end;
function EnemyAttackN4()
SwarmNToNextWayPoint(311);
end;
function EnemyAttackN5()
SwarmNToNextWayPoint(415);
end;

-----------------------------------------------
function IsRobotNGroupInCurrentZone(GroupID)
return (GetNScriptUnitsInArea(GroupID, GetNZoneName(Group_List[GroupID].CurrentZoneNumber)) > 0)
end;

----------------------------------------------
function atak ()
RunScript("EnemyAttackN1", 61000);
RunScript("EnemyAttackN2", 90000);
RunScript("EnemyAttackN3", 68000);
RunScript("EnemyAttackN4", 157000);
RunScript("EnemyAttackN5", 45000);
Suicide();
end;

Данный скрипт используется при обороне объектов.
Противник имеет группы под номерами 201; 202; 203; 311 и 415. Эти группы последовательно двигаются по зонам za0 … za8 и атакуют все на своем пути. Один раз, задав маршрут можно организовать несколько атак по нему, причем условия выдвижения вражеских групп можно задать любые.
В скрипте можно задать любое количество групп и зон, по которым они двигаются.
Теперь самое интересное. Можно задать не один, а несколько маршрутов.
Для этого нужно заменить букву N на цифру маршрута и задать новые зоны.
Например, для 1 маршрута с 6 зонами будут следующие команды.
EnemyAttack11; IsRobot1GroupInCurrentZone(GroupID); Swarm1ToNextWayPoint; Get1ZoneName и т.д.
Зоны – zonea0 … zonea4
Второй маршрут буде иметь 8 зон
EnemyAttack21; IsRobot2GroupInCurrentZone(GroupID); Swarm2ToNextWayPoint; Get2ZoneName и т.д.
Зоны – zoneb0 … zoneb7
Ниже привожу список функций, где необходимо заменить N цифрой маршрута.
AttackNZone; GetNZoneName; SwarmNToNextWayPoint; IsRobotNGroupInCurrentZone.
Изображение
 

За это сообщение пользователю клерик "Спасибо" сказали
Bruticus, urban

 
Аватара пользователя
Bruticus Не в сети
Генерал-майор
Генерал-майор
 
Сообщений: 61
Зарегистрирован: 22 окт 2013, 22:47
Откуда: Россия
Cпасибо сказано: 41
Спасибо получено: 50 раз в 28 сообщениях

Медали: 10
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1) Орден Александра Невского (1) 3 года форуму (1)
Красная Звезда к 9 мая (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 28
 
Добавить очки репутации Уменьшить очки репутации

Re: Скриптование карт. LUA

Сообщение Bruticus » 11 окт 2014, 05:43

Доброго времени суток. Может кто помочь создать скрипт, чтоб у группы юнитов, подчинённых компьютеру, восстанавливались патроны? С восстановлением ХП я разобрался, а вот с патронами пока не получается...
 

За это сообщение пользователю Bruticus "Спасибо" сказали
urban

 
Аватара пользователя
клерик Не в сети
Автор мода
Автор мода
 
Сообщений: 389
Зарегистрирован: 08 ноя 2011, 22:25
Cпасибо сказано: 179
Спасибо получено: 302 раз в 193 сообщениях

Медали: 14
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС I ст. (1) За Службу Родине в ВС II ст. (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1)
Орден Александра Невского (1) 50-лет Карибскому Кризису-1962 (1) 3 года форуму (1) Высшая награда форума (1) Красная Звезда к 9 мая (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 120
 
Добавить очки репутации Уменьшить очки репутации

Re: Скриптование карт. LUA

Сообщение клерик » 08 ноя 2014, 11:13

К сожалению такой скрипт создать не получится.
Я нашел руководство к LUA на английском и выяснил, что команда для восстановления боеприпасов у юнитов подчиненным компьютеру (Cmd (23,...)) не реализована.
Пробовал сам. Грузовики ехали к точке для восстановления боеприпасов и просто остановились, дальше ни чего не делая.

Могу порекомендовать реализовывать восстановление боеприпасов у компьютерных юнитов через Стартовые команды войскам редактора карт.
Изображение
 

За это сообщение пользователю клерик "Спасибо" сказали
urban

 
Аватара пользователя
Bruticus Не в сети
Генерал-майор
Генерал-майор
 
Сообщений: 61
Зарегистрирован: 22 окт 2013, 22:47
Откуда: Россия
Cпасибо сказано: 41
Спасибо получено: 50 раз в 28 сообщениях

Медали: 10
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1) Орден Александра Невского (1) 3 года форуму (1)
Красная Звезда к 9 мая (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 28
 
Добавить очки репутации Уменьшить очки репутации

Re: Скриптование карт. LUA

Сообщение Bruticus » 08 ноя 2014, 21:32

клерик писал(а): Грузовики ехали к точке для восстановления боеприпасов и просто остановились, дальше ни чего не делая.

видимо я не совсем понятно выразился...
Хочу обойтись без помощи грузовиков. Чтоб боеприпасы, до поры до времени , были бесконечными. С ХП получилось.
Дело в том, что по сюжету, нужно будет пробиться к группе десантников, попавших в окружение и появление грузовиков снабжения там не совсем уместно. Без подобного скрипта не обойтись. ХП восстанавливается, но кончаются патроны и во время успеть не получается :smile21:

клерик писал(а):Я нашел руководство к LUA на английском

можешь ссылку на скачивание или выложить где, чтоб скачать ?
 

 
Аватара пользователя
клерик Не в сети
Автор мода
Автор мода
 
Сообщений: 389
Зарегистрирован: 08 ноя 2011, 22:25
Cпасибо сказано: 179
Спасибо получено: 302 раз в 193 сообщениях

Медали: 14
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС I ст. (1) За Службу Родине в ВС II ст. (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1)
Орден Александра Невского (1) 50-лет Карибскому Кризису-1962 (1) 3 года форуму (1) Высшая награда форума (1) Красная Звезда к 9 мая (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 120
 
Добавить очки репутации Уменьшить очки репутации

Re: Скриптование карт. LUA

Сообщение клерик » 14 янв 2015, 09:29

У тебя со скриптом получилось?
если нет скинь образец скрипта для восстановления ХП
пробую оттолкнутся от него
Изображение
 

 
Аватара пользователя
Bruticus Не в сети
Генерал-майор
Генерал-майор
 
Сообщений: 61
Зарегистрирован: 22 окт 2013, 22:47
Откуда: Россия
Cпасибо сказано: 41
Спасибо получено: 50 раз в 28 сообщениях

Медали: 10
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1) Орден Александра Невского (1) 3 года форуму (1)
Красная Звезда к 9 мая (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 28
 
Добавить очки репутации Уменьшить очки репутации

Re: Скриптование карт. LUA

Сообщение Bruticus » 15 янв 2015, 16:36

Со скриптом. восстановления ХП, получилось.
Вот он:

function zdorovie()
local hps = GetObjectHPs(scriptid);
if (hps ~= 0) then
DamageObject(scriptid, -newhp );
end;
end;

или так:

function zdorovie()
DamageObject(scriptid, -newhp);
end;

* scriptid - сценарный номер юнита
* newhp - новое значение HPs. С минусом. Если, к примеру, поставить значение -50, то ровно на 50 единиц будет восстанавливаться ХП единицы каждую секунду.

Оба варианта рабочие, сам проверял )
 

За это сообщение пользователю Bruticus "Спасибо" сказали
ildar, urban, клерик


 
Аватара пользователя
клерик Не в сети
Автор мода
Автор мода
 
Сообщений: 389
Зарегистрирован: 08 ноя 2011, 22:25
Cпасибо сказано: 179
Спасибо получено: 302 раз в 193 сообщениях

Медали: 14
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС I ст. (1) За Службу Родине в ВС II ст. (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1)
Орден Александра Невского (1) 50-лет Карибскому Кризису-1962 (1) 3 года форуму (1) Высшая награда форума (1) Красная Звезда к 9 мая (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 120
 
Добавить очки репутации Уменьшить очки репутации

Re: Скриптование карт. LUA

Сообщение клерик » 18 янв 2015, 22:24

слушай если не получается со скриптами попробуй так.

включи в десантную группу инженерный грузовик на базе "вилиса" или его захват
у меня тоже есть задача с десантниками и там группа захватывает грузовики
Изображение
 

За это сообщение пользователю клерик "Спасибо" сказали
Bruticus

 
Аватара пользователя
Bruticus Не в сети
Генерал-майор
Генерал-майор
 
Сообщений: 61
Зарегистрирован: 22 окт 2013, 22:47
Откуда: Россия
Cпасибо сказано: 41
Спасибо получено: 50 раз в 28 сообщениях

Медали: 10
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1) Орден Александра Невского (1) 3 года форуму (1)
Красная Звезда к 9 мая (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 28
 
Добавить очки репутации Уменьшить очки репутации

Re: Скриптование карт. LUA

Сообщение Bruticus » 19 янв 2015, 18:04

клерик писал(а):слушай если не получается со скриптами попробуй так.

включи в десантную группу инженерный грузовик на базе "вилиса" или его захват
у меня тоже есть задача с десантниками и там группа захватывает грузовики

Да, придется придумать что-нибудь в обход :)

клерик
Откуда можно скачать руководство ЛУА ? Не те базовые функции , от разрабов, а что-то расширенное, глубокое.
 

 
Аватара пользователя
клерик Не в сети
Автор мода
Автор мода
 
Сообщений: 389
Зарегистрирован: 08 ноя 2011, 22:25
Cпасибо сказано: 179
Спасибо получено: 302 раз в 193 сообщениях

Медали: 14
Орден Красной Звезды (1) Орден Красного Знамени (1) За Службу Родине в ВС I ст. (1) За Службу Родине в ВС II ст. (1) За Службу Родине в ВС III ст. (1) Орден Победы (1) Орден Дружбы Народов (1)
Орден Александра Невского (1) 50-лет Карибскому Кризису-1962 (1) 3 года форуму (1) Высшая награда форума (1) Красная Звезда к 9 мая (1) Карибский Кризис (1) Воин-интернационалист I ст. (1)

Очков репутации: 120
 
Добавить очки репутации Уменьшить очки репутации

Re: Скриптование карт. LUA

Сообщение клерик » 05 окт 2015, 16:03

нашел интересную функцию LUA

ClearDepotUpgrade();

очищает склад игрока или противника от юнитов из предыдущих глав

Player:ClearDepotUpgrade(); - очищает склад игрока

Robot:ClearDepotUpgrade(); - очищает склад противника
Изображение
 


За это сообщение пользователю клерик "Спасибо" сказали
ALEX21375, urban


 

Вернуться в Мастерская: информация


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4

cron