Код Корсаров, как и большинства других игр, в некоторой степени событийно-ориентирован.
Справка:Событи́йно-ориенти́рованное программи́рование (англ. «event-driven programming») — парадигма программирования, в которой выполнение программы определяется событиями — действиями пользователя (клавиатура, мышь, сенсорный экран), сообщениями других программ и потоков, событиями операционной системы (например, поступлением сетевого пакета).
Что это значит? При совершении какого-то действия приложение рассылает определённое событие, после чего оно (событие) попадает в т.н. «Event pool» (из уровня скриптов эта куча недоступна). В этой куче находятся все необработанные, но разосланные события. При обработке каждого события (т.е. через определенное время) оно удаляется из пула событий и происходит вызов процедуры, связанной с событием - слушателя события.
На примере:
Игрок совершает выстрел из пушек корабля. Выстрел - это вполне себе событие. Но само по себе, это событие, ничего в себе не несёт. Ну вот событие и событие, что дальше?
А чтобы происходили какие-то действия дальше - на это событие должны быть подписаны какие-то слушатели. Какие слушатели могут быть у события выстрела? Допустим, у нас есть крутая система с генерацией дыма из дула пушки. На какое событие ей быть подписанной, если не на это?
Вот совершили вы выстрел. Игра рассылает сообщение о том, что данное событие произошло, на всех слушателей. В нашем случае - это генерация дыма. И дальше происходят действия, записанные в функции, которую мы указали как коллбек данного слушателя - т.е. генерация дыма.
Игрок совершает выстрел из пушек корабля. Выстрел - это вполне себе событие. Но само по себе, это событие, ничего в себе не несёт. Ну вот событие и событие, что дальше?
А чтобы происходили какие-то действия дальше - на это событие должны быть подписаны какие-то слушатели. Какие слушатели могут быть у события выстрела? Допустим, у нас есть крутая система с генерацией дыма из дула пушки. На какое событие ей быть подписанной, если не на это?
Вот совершили вы выстрел. Игра рассылает сообщение о том, что данное событие произошло, на всех слушателей. В нашем случае - это генерация дыма. И дальше происходят действия, записанные в функции, которую мы указали как коллбек данного слушателя - т.е. генерация дыма.
Справка:Колбэк-функция (англ. «callback function») или обратный вызов - это функция, переданная в другую функцию в качестве аргумента, которая затем вызывается по завершению какого-либо действия.
Event Management
Для работы с событиями в скриптовой части игры доступно восемь функций. Давайте поочерёдно разберём каждую из них и посмотрим примеры использования.
SetEventHandler
// синтаксис
void SetEventHandler(string eventName, string functionName, bool post);
#event_handler(string eventName, string functionName, bool post);
// пример
SetEventHandler("frame", "RefreshTableByFrameEvent", false); // выполняется при вызове ф-ции "Event()"
SetEventHandler("frame", "ProcessFrame", true); // выполняется при вызове ф-ции "PostEvent()"
SetEventHandler - добавляет обработчик (слушателя) к событию.
Данная функция принимает три аргумента:
string eventName - название события, на которое выполняется подписка. Если события с таким названием не существует - оно будет создано автоматически.
string functionName - название колбэк-функции. Указывается без скобок. Также эта функция не должна принимать аргументов.
bool post - вариант вызова. Посредством Event(), или PostEvent().
Как видим, есть два способа повесить слушателя на событие: при помощи функции или при помощи директивы.
И здесь есть нюанс: слушателя, добавленного при помощи директивы #event_handler, нельзя удалить.
И здесь есть нюанс: слушателя, добавленного при помощи директивы #event_handler, нельзя удалить.
DelEventHandler
// синтаксис
void DelEventHandler(string eventName, string functionName);
// пример
DelEventHandler("frame", "RefreshTableByFrameEvent");
DelEventHandler - удалить обработчик (отменить подписку) с события.
string eventName - название события.
string functionName - название колбэк-функции.
Здесь всё в точности наоборот: указываем событие и название колбэка, который нужно снять с подписки.
Event
// синтаксис
void Event(string eventName, [MSG]);
// пример
Event("NextDay"); // без сообщения
Event("ControlActivation", "s", "ChrAction"); // передача аргумента строкового типа
Справка:В С++ функции могут иметь необязательные аргументы. Они указываются в квадратных скобках.
Event - запустить событие и вызвать все его обработчики.
string eventName - название события.
MSG - передаваемое сообщение. Оно состоит из перечисления типов передаваемых аргументов, а также самих аргументов.
В качестве сообщения могут быть переданы следующие типы данных:
l: int/bool
f: float
s: string
a, i: object или aref
e: ref
Как видим, данная функция может быть вызвана двумя способами: с передачей дополнительных аргументов и без них. Аргументов может быть любое количество - их типы перечисляются без разделительных знаков, а сами аргументы через запятую в той же последовательности, что и перечисленные типы.
PostEvent
// синтаксис
void PostEvent(string eventName, int delay, [MSG]);
// пример
PostEvent("My_eventMoveImg", 100); // без сообщения
int charIndex = sti(CharacterRef.index);
PostEvent("eventDialogExit", 1, "l", charIndex); // передача ID персонажа
PostEvent - запуск события с задержкой на вызов обработчиков.
string eventName - название события.
int delay - задержка вызова, в милисекундах (1s = 1000ms).
MSG - передаваемое сообщение (аналогично предыдущей ф-ции).
Данный вызов колбэков также может быть с передачей аргументов и без. Отличается от предыдущего тем, что вызов обработчиков происходит не моментально, а через указанное кол-во времени.
GetEventData
// синтаксис
[any type] GetEventData();
// пример
SetEventHandler("Control Activation", "InfoShow_Control", 0);
Event("Control Activation", "sl", "ChrAction", 123);
void InfoShow_Control()
{
string controlName = GetEventData(); // "ChrAction"
int num = GetEventData(); // 123
// ...
}
GetEventData - извлекает аргумент из сообщения, переданного в событие.
Эта функция обычно вызывается из функции, зарегистрированной как обработчик событий. Аргументы возвращаются в том порядке, в котором они были переданы в сообщение.
ClearEvents
// синтаксис
void ClearEvents();
ClearEvents - удаляет все обычные обработчики из всех событий.
Не влияет на обработчики событий «post».
ClearPostEvents
// синтаксис
void ClearPostEvents();
ClearPostEvents - удаляет все обработчики «post» из всех событий.
Не влияет на обычные обработчики событий.
EventsBreak
// синтаксис
void EventsBreak();
EventsBreak - останавливает выполнение всех событий для оставшейся части кадра.
В настоящее время эта функция не имеет никакого эффекта, поскольку bEventsBreak всегда имеет значение false при входе в цикл событий.
Edited by avuremybe