События возникают в игре, в тот самый момент когда фиксируется выполнение (удачное или неудачное) текущей инструкции для поезда, под управлением игрока.
Сразу следует отметить, что для AI-поездов выполнение обычных инструкций никаких событий не порождает. Так что если мы хотим привязать событие именно к AI-поезду, то это возможно исключительно через триггерную инструкцию. Собственно, всё как обычно.
Теперь самое время изучить xml-код соответствующий инструкции для поезда, находящийся в файле "Scenario.bin". Первым делом этот файл следует преобразовать в xml-формат с помощью утилиты "serz.exe".
Утилита принимает в качестве аргумента командной строки имя и путь к преобразуемому файлу, результирующий файл записывается в ту же папку, что и исходный. Прямое или обратное преобразование определяется расширением входного файла или соответствующими параметрами командной строки.
Существующие файлы перезаписываются без запроса подтверждения, поэтому настоятельно рекомендую предварительно копировать bin-файл для редактирования в другую папку. Резервная копия редактируемого сценария тоже показана.
Открываем получившийся "Scenario.xml" в редакторе и ищем интересующие нас инструкции. Если вы переделываете свой старый сценарий, то искать следует по части фразы текстового сообщения, если же вы создаёте новый сценарий, то вместо текста сообщения в редакторе сценариев имеет смысл сразу писать имя будущего события. И так мы нашли это:
- Код: Выделить всё
<cStopAtDestinations d:id="1506815728">
<ActivationLevel d:type="sInt16">0</ActivationLevel>
<TriggeredText>
<Localisation-cUserLocalisedString>
<English d:type="cDeltaString"></English>
<French d:type="cDeltaString"></French>
<Italian d:type="cDeltaString"></Italian>
<German d:type="cDeltaString"></German>
<Spanish d:type="cDeltaString"></Spanish>
<Dutch d:type="cDeltaString"></Dutch>
<Polish d:type="cDeltaString"></Polish>
<Russian d:type="cDeltaString"></Russian>
<Other/>
<Key d:type="cDeltaString">46d15bae-8768-4695-86c0-9e1cb429e8a9</Key>
</Localisation-cUserLocalisedString>
</TriggeredText>
<UntriggeredText>
<Localisation-cUserLocalisedString>
<English d:type="cDeltaString"></English>
<French d:type="cDeltaString"></French>
<Italian d:type="cDeltaString"></Italian>
<German d:type="cDeltaString"></German>
<Spanish d:type="cDeltaString"></Spanish>
<Dutch d:type="cDeltaString"></Dutch>
<Polish d:type="cDeltaString"></Polish>
<Russian d:type="cDeltaString"></Russian>
<Other/>
<Key d:type="cDeltaString">84c2f238-6c51-40ac-b438-43a7187902d3</Key>
</Localisation-cUserLocalisedString>
</UntriggeredText>
<DisplayText>
<Localisation-cUserLocalisedString>
<English d:type="cDeltaString"></English>
<French d:type="cDeltaString"></French>
<Italian d:type="cDeltaString"></Italian>
<German d:type="cDeltaString"></German>
<Spanish d:type="cDeltaString"></Spanish>
<Dutch d:type="cDeltaString"></Dutch>
<Polish d:type="cDeltaString"></Polish>
<Russian d:type="cDeltaString">Диспетчер: 3839, следуйте через парк, вагонетки стоят с западной стороны, на соседнем пути справа от вас.</Russian>
<Other/>
<Key d:type="cDeltaString">bc6286df-f47f-4eff-b14a-49e52335536f</Key>
</Localisation-cUserLocalisedString>
</DisplayText>
<TriggerTrainStop d:type="bool">0</TriggerTrainStop>
<TriggerWheelSlip d:type="bool">0</TriggerWheelSlip>
<WheelSlipDuration d:type="sInt16">0</WheelSlipDuration>
<TriggerSound>
<cGUID>
<UUID>
<e d:type="sUInt64">0</e>
<e d:type="sUInt64">0</e>
</UUID>
<DevString d:type="cDeltaString">00000000-0000-0000-0000-000000000000</DevString>
</cGUID>
</TriggerSound>
<TriggerAnimation>
<cGUID>
<UUID>
<e d:type="sUInt64">0</e>
<e d:type="sUInt64">0</e>
</UUID>
<DevString d:type="cDeltaString">00000000-0000-0000-0000-000000000000</DevString>
</cGUID>
</TriggerAnimation>
<SecondsDelay d:type="sInt16">0</SecondsDelay>
<Active d:type="bool">1</Active>
<ArriveTime>
<sTimeOfDay>
<_iHour d:type="sInt32">0</_iHour>
<_iMinute d:type="sInt32">0</_iMinute>
<_iSeconds d:type="sInt32">0</_iSeconds>
</sTimeOfDay>
</ArriveTime>
<DepartTime>
<sTimeOfDay>
<_iHour d:type="sInt32">0</_iHour>
<_iMinute d:type="sInt32">0</_iMinute>
<_iSeconds d:type="sInt32">0</_iSeconds>
</sTimeOfDay>
</DepartTime>
<Condition d:type="cDeltaString"></Condition>
<SuccessEvent d:type="cDeltaString"></SuccessEvent>
<FailureEvent d:type="cDeltaString"></FailureEvent>
<Started d:type="bool">0</Started>
<Satisfied d:type="bool">0</Satisfied>
<DeltaTarget>
<cDriverInstructionTarget d:id="1508219136">
<DisplayName d:type="cDeltaString">Siding94</DisplayName>
<Timetabled d:type="bool">0</Timetabled>
<Performance d:type="sInt32">100</Performance>
<MinSpeed d:type="sInt32">1</MinSpeed>
<DurationSecs d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</DurationSecs>
<EntityName d:type="cDeltaString">Siding94</EntityName>
<TrainOrder d:type="bool">0</TrainOrder>
<Operation d:type="cDeltaString">Default</Operation>
<Deadline>
<sTimeOfDay>
<_iHour d:type="sInt32">0</_iHour>
<_iMinute d:type="sInt32">0</_iMinute>
<_iSeconds d:type="sInt32">0</_iSeconds>
</sTimeOfDay>
</Deadline>
<PickingUp d:type="bool">1</PickingUp>
<Duration d:type="sUInt32">10</Duration>
<HandleOffPath d:type="bool">0</HandleOffPath>
<EarliestDepartureTime d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</EarliestDepartureTime>
<DurationSet d:type="bool">0</DurationSet>
<ReversingAllowed d:type="bool">1</ReversingAllowed>
<Waypoint d:type="bool">0</Waypoint>
<ProgressCode d:type="cDeltaString">INSTRUCTION_STATE_INACTIVE</ProgressCode>
<ArrivalTime d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</ArrivalTime>
<DepartureTime d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</DepartureTime>
<TickedTime d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</TickedTime>
<DueTime d:type="sFloat32" d:alt_encoding="00000020F0E27F40" d:precision="string">510.184</DueTime>
<RailVehicleNumber/>
<TimingTestTime d:type="sFloat32" d:alt_encoding="000000C07CDF7E40" d:precision="string">493.968</TimingTestTime>
<GroupName>
<Localisation-cUserLocalisedString>
<English d:type="cDeltaString"></English>
<French d:type="cDeltaString"></French>
<Italian d:type="cDeltaString"></Italian>
<German d:type="cDeltaString"></German>
<Spanish d:type="cDeltaString"></Spanish>
<Dutch d:type="cDeltaString"></Dutch>
<Polish d:type="cDeltaString"></Polish>
<Russian d:type="cDeltaString"></Russian>
<Other/>
<Key d:type="cDeltaString">c5b55b9c-697b-4c41-b863-09697e3d58da</Key>
</Localisation-cUserLocalisedString>
</GroupName>
<ShowRVNumbersWithGroup d:type="bool">0</ShowRVNumbersWithGroup>
<HandOffRelayTarget d:type="bool">0</HandOffRelayTarget>
</cDriverInstructionTarget>
</DeltaTarget>
<TravelForwards d:type="bool">0</TravelForwards>
</cStopAtDestinations>
Тег "<TriggeredText>" отвечает за выдачу сообщения при удачном завершении инструкции.
Тег "<UntriggeredText>" отвечает за выдачу сообщения при неудачном завершении инструкции.
Тег "<DisplayText>" выдаёт сообщение при любом (удачном/ неудачном) завершении инструкции.
Все три тега, как видно, полностью соответствуют полям в форме редактора сценариев. Поскольку сообщения теперь будут выдаваться из скрипта, то текст во всех этих трёх тегах следует вычистить.
Чуть ниже есть ещё два нужных нам тега.
Тег "<SuccessEvent " описывает имя события при удачном завершении инструкции.
Тег "<FailureEvent" описывает имя события при неудачном завершении инструкции.
В нашем примере, удалённый из тега "<DisplayText>" текст сообщения теперь находится в файле "msg002.html", следовательно имя нашего события будет "msg002", и мы должны поместить его в тег "<SuccessEvent":
- Код: Выделить всё
<cStopAtDestinations d:id="1501640304">
<ActivationLevel d:type="sInt16">0</ActivationLevel>
<TriggeredText>
<Localisation-cUserLocalisedString>
<English d:type="cDeltaString"></English>
<French d:type="cDeltaString"></French>
<Italian d:type="cDeltaString"></Italian>
<German d:type="cDeltaString"></German>
<Spanish d:type="cDeltaString"></Spanish>
<Dutch d:type="cDeltaString"></Dutch>
<Polish d:type="cDeltaString"></Polish>
<Russian d:type="cDeltaString"></Russian>
<Other/>
<Key d:type="cDeltaString">46d15bae-8768-4695-86c0-9e1cb429e8a9</Key>
</Localisation-cUserLocalisedString>
</TriggeredText>
<UntriggeredText>
<Localisation-cUserLocalisedString>
<English d:type="cDeltaString"></English>
<French d:type="cDeltaString"></French>
<Italian d:type="cDeltaString"></Italian>
<German d:type="cDeltaString"></German>
<Spanish d:type="cDeltaString"></Spanish>
<Dutch d:type="cDeltaString"></Dutch>
<Polish d:type="cDeltaString"></Polish>
<Russian d:type="cDeltaString"></Russian>
<Other/>
<Key d:type="cDeltaString">84c2f238-6c51-40ac-b438-43a7187902d3</Key>
</Localisation-cUserLocalisedString>
</UntriggeredText>
<DisplayText>
<Localisation-cUserLocalisedString>
<English d:type="cDeltaString"></English>
<French d:type="cDeltaString"></French>
<Italian d:type="cDeltaString"></Italian>
<German d:type="cDeltaString"></German>
<Spanish d:type="cDeltaString"></Spanish>
<Dutch d:type="cDeltaString"></Dutch>
<Polish d:type="cDeltaString"></Polish>
<Russian d:type="cDeltaString"></Russian>
<Other/>
<Key d:type="cDeltaString">bc6286df-f47f-4eff-b14a-49e52335536f</Key>
</Localisation-cUserLocalisedString>
</DisplayText>
<TriggerTrainStop d:type="bool">0</TriggerTrainStop>
<TriggerWheelSlip d:type="bool">0</TriggerWheelSlip>
<WheelSlipDuration d:type="sInt16">0</WheelSlipDuration>
<TriggerSound>
<cGUID>
<UUID>
<e d:type="sUInt64">0</e>
<e d:type="sUInt64">0</e>
</UUID>
<DevString d:type="cDeltaString">00000000-0000-0000-0000-000000000000</DevString>
</cGUID>
</TriggerSound>
<TriggerAnimation>
<cGUID>
<UUID>
<e d:type="sUInt64">0</e>
<e d:type="sUInt64">0</e>
</UUID>
<DevString d:type="cDeltaString">00000000-0000-0000-0000-000000000000</DevString>
</cGUID>
</TriggerAnimation>
<SecondsDelay d:type="sInt16">0</SecondsDelay>
<Active d:type="bool">1</Active>
<ArriveTime>
<sTimeOfDay>
<_iHour d:type="sInt32">0</_iHour>
<_iMinute d:type="sInt32">0</_iMinute>
<_iSeconds d:type="sInt32">0</_iSeconds>
</sTimeOfDay>
</ArriveTime>
<DepartTime>
<sTimeOfDay>
<_iHour d:type="sInt32">0</_iHour>
<_iMinute d:type="sInt32">0</_iMinute>
<_iSeconds d:type="sInt32">0</_iSeconds>
</sTimeOfDay>
</DepartTime>
<Condition d:type="cDeltaString"></Condition>
<SuccessEvent d:type="cDeltaString">msg002</SuccessEvent>
<FailureEvent d:type="cDeltaString"></FailureEvent>
<Started d:type="bool">0</Started>
<Satisfied d:type="bool">0</Satisfied>
<DeltaTarget>
<cDriverInstructionTarget d:id="1501647032">
<DisplayName d:type="cDeltaString">Siding94</DisplayName>
<Timetabled d:type="bool">0</Timetabled>
<Performance d:type="sInt32">100</Performance>
<MinSpeed d:type="sInt32">1</MinSpeed>
<DurationSecs d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</DurationSecs>
<EntityName d:type="cDeltaString">Siding94</EntityName>
<TrainOrder d:type="bool">0</TrainOrder>
<Operation d:type="cDeltaString">Default</Operation>
<Deadline>
<sTimeOfDay>
<_iHour d:type="sInt32">0</_iHour>
<_iMinute d:type="sInt32">0</_iMinute>
<_iSeconds d:type="sInt32">0</_iSeconds>
</sTimeOfDay>
</Deadline>
<PickingUp d:type="bool">1</PickingUp>
<Duration d:type="sUInt32">10</Duration>
<HandleOffPath d:type="bool">0</HandleOffPath>
<EarliestDepartureTime d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</EarliestDepartureTime>
<DurationSet d:type="bool">0</DurationSet>
<ReversingAllowed d:type="bool">1</ReversingAllowed>
<Waypoint d:type="bool">0</Waypoint>
<ProgressCode d:type="cDeltaString">INSTRUCTION_STATE_INACTIVE</ProgressCode>
<ArrivalTime d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</ArrivalTime>
<DepartureTime d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</DepartureTime>
<TickedTime d:type="sFloat32" d:alt_encoding="0000000000000000" d:precision="string">0</TickedTime>
<DueTime d:type="sFloat32" d:alt_encoding="00000020F0E27F40" d:precision="string">510.184</DueTime>
<RailVehicleNumber/>
<TimingTestTime d:type="sFloat32" d:alt_encoding="000000C07CDF7E40" d:precision="string">493.968</TimingTestTime>
<GroupName>
<Localisation-cUserLocalisedString>
<English d:type="cDeltaString"></English>
<French d:type="cDeltaString"></French>
<Italian d:type="cDeltaString"></Italian>
<German d:type="cDeltaString"></German>
<Spanish d:type="cDeltaString"></Spanish>
<Dutch d:type="cDeltaString"></Dutch>
<Polish d:type="cDeltaString"></Polish>
<Russian d:type="cDeltaString"></Russian>
<Other/>
<Key d:type="cDeltaString">c5b55b9c-697b-4c41-b863-09697e3d58da</Key>
</Localisation-cUserLocalisedString>
</GroupName>
<ShowRVNumbersWithGroup d:type="bool">0</ShowRVNumbersWithGroup>
<HandOffRelayTarget d:type="bool">0</HandOffRelayTarget>
</cDriverInstructionTarget>
</DeltaTarget>
<TravelForwards d:type="bool">0</TravelForwards>
</cStopAtDestinations>
В данном конкретном пример параметры в инструкции "Следовать..." заданы таким образом, что она просто не может завершиться неудачно, во всех остальных случаях о содержимом тега "<FailureEvent" также необходимо побеспокоиться.
Вообще говоря, появление события описанного как "<FailureEvent" означает, что сценарий однозначно закончится для игрока неудачей. Так что может быть стоит прекратить "мучения" и досрочно завершить сценарий?
Как это сделать, поговорим в следующий раз.
Осталось сформулировать правила именования событий, выдающих анимированные сообщения:
1) имя такого события должно начинаться с латинской буквы "m";
2) вторая буква имени события определяет размер окна для вывода сообщения: "l" - большое окно; "r" - среднее окно; и малое окно, если это любая другая буква;
3) третья буква имени события определяет режим в котором выдаётся сообщение: "p" - для режима паузы, игра будет приостановлена, пока окно сообщения не будет закрыто; обычный режим, игра не приостанавливается, если это любая другая буква.
4) четвёртый и последующие символы имени события теоретически могут быть любыми. Однако я бы поостерёгся использовать что-то другое кроме латинских букв и цифр, а так же делать имя длиннее 8 символов, ибо старой доброй формулы 8.3 никто не отменял.
Давайте немного потренируемся:
Событие "mlp000" - текстовое сообщение в большом окне, в режиме паузы, из файла "mlp000.html";
Событие "mls001" - текстовое сообщение в большом окне, из файла "mls001.html";
Событие "mrp002" - текстовое сообщение в среднем окне, в режиме паузы, из файла "mrp002.html";
Событие "msg003" - текстовое сообщение в малом окне, из файла "msg003.html";
Рекомендую не плодить разнообразие в именах, и для всех событий соответствующих малому окну и обычному режиму всегда использовать один и тот же префикс, на пример "msgXXXX".
По умолчанию, окно сообщения будет автоматически закрыто через 15 секунд после его появления, если игрок никак на него не прореагировал. Если необходимо задать иное, но большее 15 секунд время таймаута, то это число секунд следует указать после имени события, отделив от него знаком равенства: "msg003=40". Текстовое сообщение в малом окне, из файла "msg003.html", с таймаутом перед закрытием в 40 секунд.
И последнее. После того, как вы преобразуете отредактированный файл "Scenario.xml" обратно в "Scenario.bin", и поместите его в папку со своим сценарием, не забудьте перекопировать туда же следующие файлы из папки демо-сценария: "ScenarioScript.lua", "ScenarioScript.luac" и "ScenarioScript.luac.MD5".
Пока всё, дерзайте. Как обычно жду вопросов и комментариев.