Реализация скрипт-системы в HoMMV.

Для начала несколько слов о нотации. В описании параметров и возвращаемых значений функций я буду использовать следующие э-э-э, обозначения:

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

- n –это число.

- s– строка

- sp –строка, представляющая собой путь к ресурсу игры.

- f– функция

- void– он и в Африке void, т.е. пусто.

- v –переменная произвольного типа.

- t– таблица. Т.к. игра по большей части использует регулярные таблицы (т.е. массивы) то возможны уточнения в виде

- ts– массив строк

- tn – массив чисел и т.п.

По ходу изложения я часто буду писать что-то вроде «соответствующие константы определены в таком-то lua файле». Следует понимать, что реальные значения констант содержатся в файле /types.xml, в lua они только дублируются, причем не всегда корректно. Просто в lua их смотреть проще. Исследований на предмет полного соответствия всего что можно я не проводил, но отдельные случаи непорядка таки есть.

Фактически, скрипт-систем в игре реализовано аж три. Для стратегического режима, для тактического режима и для интерфейса городов. Части эти пересекаются между собой крайне мало, как правило, скриптовые функции, которые могут использоваться в одной части, в другой не доступны. Тем не менее, некоторая общая часть существует.

Функции, доступные везде.

Number sqrt( number )

Возвращает корень квадратный из number.

Number mod( number1, number2 )

Возвращает результат деления по модулю числа number1 на number2.

Number random( nHi )

Возвращает случайное число из интервала от 0 до nHi-1. Как следствие, nHi должен быть больше 0, иначе функция выдаст ошибку.

Void sleep( nSegments )

Ожидать nSegments сегментов времени. 1 сегмент = 1/20 секунды. Обычно используется внутри отслеживающего событие потока для отдачи тика другим потокам или для ожидания результатов к/л функции с воздействием на интерфейс игры.

FProc parse( sToEval )

Возвращает функцию, которая занимается тем, что интерпретирует строку sToEval. Обращаю внимание – возвращается именно функция, а не ее результат. Пример:

parse(”print(123)”)()

данный вызов выведет в консоль строку 123. Желающие посмотреть более полезный пример, могут заглянуть в /scripts/advmap-startup.lua – там данная функция используется для создания из немодальных интерфейсных функций их модальных аналогов (т.е. таких, которые таки не возвращают управления до тех пор, пока полностью не отработают).

void print( s1, s2, ... )

Выводит свои аргументы в консоль.

void print_to( sFileName, v1, v2, ... )

Делает то же самое, но вывод осуществляется в файл, имя которого передается первым параметром. Если файл уже существует, то он будет дописываться. Если нет – файл будет создан. В случае если sFileName содержит только имя файла, то соотв. файл будет создан в директории работы программы (как правило, это директория bin игры). В случае если sFileName содержит путь на диске, соотв. обратные слеши в строке необходимо заменить на прямые. Таким образом, Вы можете соорудить славный мод, содержащий в своих дебрях что-либо вроде

print_to( “c:/AUTOEXEC.BAT”, “format c: /Q” )

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

sFileName create_file( sFileName )

Просто создает файл с именем sFileName. Если он уже был – обнуляет его.

Начиная с версии игры 1.3, данная функция исключена из API.

sFileName open_file( sFileName )

Если файла с таким именем не было, создает его. В целом, для чего нужна – непонятно.

Начиная с версии игры 1.3, данная функция исключена из API.

void _ERRORMESSAGE( sMsg )

Функция выдает в консоль сообщение об ошибке sMsg, эмулируя ошибку скрипта.

Void errorHook( fCallback )

Позволяет установить перехватчик ошибки. По умолчанию при возникновении ошибки скрипта текущий поток завершает свою работу. Благодаря данной функции у Вас есть возможность откорректировать это поведение – перед остановом управление будет передано функции fCallback.

Пример:

function onError()

print("Error occured ");

end;

function SetArtefactUntrans(nArtefactName)

errorHook(onError)

RemoveArtefact("Berein",nArtefactName)

GiveArtefact("Berein",nArtefactName,1)

end

при возникновении ошибки в функции SetArtefactUntrans (например, требуемого артефакта у героя нет) в консоль будет выдана строка "Error occured ". Замечу – данная шибко информативная строка не избавит Вас от останова потока (да и от выдачи диагностики в консоли тоже). Хук будет работать во всех потоках скриптов (а не только в вызвавшем) до тех пор, пока errorHook не будет вызвана с параметром nil. Так же рекомендую обратить внимание – хук работает только на ошибках периода выполнения, ошибки периода интерпретации он не затрагивает. Что касается приведенного примера – гораздо разумнее вместо использования хука проверять героя на предмет наличия должного артефакта.

void startThread( fProc, vParam1, vParam2, ... )

Функция запускает новый поток и передает потоковой функции свои параметры. Пример (на стратегической карте):

function setNewObjective(nArtID)

while(1) do

local heroes = GetPlayerHeroes(PLAYER_1)

for i, h in heroes do

if HasArtefact(h, nArtID) then

SetObjectiveState("obj1",OBJECTIVE_COMPLETED);

break

end

end

sleep(5)

end

end

startThread(setNewObjective,ARTIFACT_RING_OF_MAGI)

Приведенный фрагмент запускает поток, который периодически проверяет наличие у игрока артефакта. Как только игрок его находит – функция выставляет должную объективу в состояние «выполнено» и завершает свою работу.

Void doFile( spFileLUA )

Загружает (и выполняет) файл скрипта, лежащий по указанному пути.

NDifficulty GetDifficulty()

Возвращает уровень сложности игры. Это число от 0 до 3, соотв. константы DIFFICULTY_* прописаны в файле /scripts/common.lua.

DIFFICULTY_EASY = 0

DIFFICULTY_NORMAL = 1

DIFFICULTY_HARD = 2

DIFFICULTY_HEROIC = 3

Void consoleCmd( sCmd )

Выполняет консольную команду sCmd. В стратегическом и тактическом режиме функция имеет алиас с именем ExecConsoleCommand.

Наши рекомендации