Информация: Уважаемые посетители! В течение нескольких месяцев на форуме существовала проблема с регистрацией новых пользователей, о которой администрации стало известно недавно. Если вы ранее пытались зарегистрироваться на форуме, но не получили на ваш e-mail письмо с ссылкой для подтверждения регистрации, просим вас зарегистрироваться повторно. Приносим извинения за доставленные неудобства. Если вы все еще испытываете проблемы с регистрацией на форуме, обратитесь за помощью на e-mail: mr.angelo@railroadsim.net

Как оформить свой сценарий в "новом стиле".

Обсуждение маршрутов, объектов, сценариев

Как оформить свой сценарий в "новом стиле".

Сообщение sergz692 » 06.02.2013, 14:26

Наверное все хоть один раз видели, как RSC стала оформлять свои "фирменные" сценарии в последних дополнениях. Один стиль красивых анимированных окошек с сообщениями чего стоит:
Изображение
В TS 2013 в этот арсенал добавили даже управление погодой. Всё это можно видеть в сценариях для Шерман Хилл. Все материалы в этой теме будут посвящены тому чтобы перенять и освоить эту технологию.

Сразу хочу сказать, что для работы потребуются сторонние инструменты, поскольку придётся на прямую редактировать файлы "Scenario.bin" и "ScenarioProperties.xml".

Что конкретно выбрать советовать не буду - люди здесь в большинстве опытные, разберутся сами. Скажу только, что лично я пользовал штатную утилиту TS "serz.exe" для конвертирования bin в xml и обратно, а так же редактор XMLBlueprint.

Кроме этого технология предполагает написание сопровождающего скрипта на языке lua. Все "фирменные" сценарии поддерживает такой специально написанный скрипт, который находится в файлах "ScenarioScript.lua" - исходный код lua, "ScenarioScript.luac" - откомпилированный код, и файл контрольной суммы - "ScenarioScript.luac.MD5".

Для компиляции кода lua используется штатный компилятор "luac.exe", который находится в той же папке, что и утилита "serz.exe".

К счастью, экспериментально установлено, что для штатной работы скрипта достаточно факта самого наличия файла "ScenarioScript.luac.MD5", контрольная сигнатура в нём на соответствие не проверяется, так что возможно использовать файл "ScenarioScript.luac.MD5" из любого фирменного сценария.

Для примеров и демонстрации будет использоваться моя собственная разработка, которую можно скачать здесь: http://yadi.sk/d/0b36dWdH3dMYw
Подробнее об этом демо-сценарии (для Шермана) можно почитать тут : forum53/topic10360.html

Есть ещё и альтернативный демо-сценарий для Касл-Рока: http://yadi.sk/d/1rlpf4Aq3dMZq

Скрипт для своих сценариев я изначально писал как универсальный, то есть, принимая некоторые соглашения и простые правила, вы сможете использовать этот готовый отлаженный код для своих сценариев, не написав самостоятельно ни одной строчки на lua. Думаю, что очень многих это вполне удовлетворит. :nyam:

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

На этом вводную часть можно считать законченной.


Теперь поговорим о создании анимированных сообщений.

Скачайте и у установите демо-сценарий, если кто-то ещё этого не сделал.

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

Найдите папку с установленным демо-сценарием, сейчас мы будем изучать содержимое подпапок "En" и "Ru". Как можно видеть там лежат два идентичных по названиям набора html файлов. Это и есть сообщения сценария. Можете открыть любой из них двойным щелчком, и полюбоваться в окне браузера. Всё просто, не правда ли?

Названия html-файлов соответствуют именам событий, при наступлении которых скрипт отображает соответствующее сообщение. Правила для именования этих событий, а так же технологию встраивания оных в файл "Scenario.bin" подробнее разберём в следующий раз. А пока ограничимся тем, что всего наборов html-файлов для сценария потребуется ровно столько, сколько языков вы собираетесь поддерживать.

Очевидная логика намекает, что в нашем примере поддерживается английский и русский языки, а для поддержки, скажем немецкого, понадобился бы ещё один набор, помещённый в папку "De".

На тонкостях создания и редактирования html-контента подробно останавливаться, думаю, не будем. Добавлю только, что все html-файлы должны создаваться в кодировке UTF-8, и что все используемые при его создании графические объекты имеет смысл помещать в папке сценария. Можете просто брать в качестве шаблона мои файлы.

Желающие попрактиковаться уже прямо сейчас могут начать создавать html-файлики для своего сценария. Однако я бы предложил начать с локализации какого-нибудь "фирменного" сценария. Наверняка у каждого хоть один такой, да найдётся.

Создайте подпапку "Ru" в папке этого сценария и скопируйте в неё все файлы из папки "En". Отредактируйте каждый из них, заменив английский текст переводом. Не забывайте про кодировку. Запустите локализованный сценарий, и наслаждайтесь.

На сегодня, пожалуй, всё. Пишите вопросы и комментарии, постараюсь ответить до продолжения, которое, скорее всего, будет завтра. :hi:
Последний раз редактировалось sergz692 18.06.2013, 18:17, всего редактировалось 3 раз(а).
sergz692
 
Сообщения: 30
Зарегистрирован: 22.01.2013, 00:13
Благодарил (а): 4 раз.
Поблагодарили: 32 раз.
Играю в: RailWorks

Re: Как оформить свой сценарий в "новом стиле".

Сообщение Trainman » 06.02.2013, 14:53

Ждем продолжения. Полного мануала так сказать
Trainman
 
Сообщения: 153
Зарегистрирован: 14.02.2012, 22:13
Откуда: Минск
Благодарил (а): 194 раз.
Поблагодарили: 75 раз.
Блог: Просмотр блога (2)
Играю в: RailWorks
Роль: Пассажир :)
Имя: Vladimir

Теперь самое время поговорить о событиях.

Сообщение sergz692 » 07.02.2013, 02:40

События возникают в игре, в тот самый момент когда фиксируется выполнение (удачное или неудачное) текущей инструкции для поезда, под управлением игрока.

Сразу следует отметить, что для 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".

Пока всё, дерзайте. Как обычно жду вопросов и комментариев. :hi:
sergz692
 
Сообщения: 30
Зарегистрирован: 22.01.2013, 00:13
Благодарил (а): 4 раз.
Поблагодарили: 32 раз.
Играю в: RailWorks

Re: Как оформить свой сценарий в "новом стиле".

Сообщение elros » 07.02.2013, 03:17

крутой мануал получается, всё понятно, спасибо!!!!!!
elros
 
Сообщения: 38
Зарегистрирован: 26.07.2008, 17:55
Благодарил (а): 35 раз.
Поблагодарили: 22 раз.
Имя: Сергей

Re: Как оформить свой сценарий в "новом стиле".

Сообщение Skif » 07.02.2013, 09:15

Если не считать, что для скачивания демо-сценария нужно прежде скачать ПЛАТНЫЙ маршрут, то все ништяк.. ;)
Skif
 
Сообщения: 2871
Зарегистрирован: 01.10.2009, 17:42
Благодарил (а): 263 раз.
Поблагодарили: 813 раз.
Блог: Просмотр блога (2)
Имя: Дмитрий

Re: Как оформить свой сценарий в "новом стиле".

Сообщение YuriA » 07.02.2013, 10:23

Skif, а разве "Sherman Hill" это не "умолчальный" маршрут? У меня он есть и стоит в купленных. Хотя я ничего дополнительного не покупал.
YuriA
 
Сообщения: 13
Зарегистрирован: 07.11.2012, 10:55
Благодарил (а): 9 раз.
Поблагодарили: 1 раз.
Имя: Юрий

Re: Как оформить свой сценарий в "новом стиле".

Сообщение sergz692 » 07.02.2013, 11:39

Skif писал(а):Если не считать, что для скачивания демо-сценария нужно прежде скачать ПЛАТНЫЙ маршрут, то все ништяк.. ;)

Вообще-то и скачать и установить демо-сценарий можно и без этого платного маршрута вовсе. Просто поиграть в демо-сценарий не получится. :P

Но для изучения данного мануала ЭТО абсолютно не важно. Создавайте свой сценарий, на том маршруте, что у вас есть, будете проверять этот материал прямо в деле, "с колёс". Чуть сложнее, зато совершенно бесплатно. :up:

Единственная трудность которая у вас будет: в управлении погодой придётся ограничиться теорией, поскольку оно реализовано пока (на сколько я знаю) только на этом платном дополнении, и даже материала для собственных изысканий взять будет не откуда. :wink:

YuriA писал(а):Skif, а разве "Sherman Hill" это не "умолчальный" маршрут?

Он "умолчальный" только для тех, кто купил именно TS 2013, то есть после какогото там октября 12 года. А всем остальным тока "за денежку", лично я чтобы поиметь Шерман Хилл и Мюнхен - Аугсбург (отдельно они не продавались, и было не ясно будут ли) раскошелился второй раз, на люксовую версию. :nyam:


Добавлено спустя 11 часов 2 минуты 36 секунд:
Кто-нибудь уже может похвастать первыми успехами?

Кстати, если кто будет пользоваться для редактирования файлов сценария другими инструментами, не плохо бы отписаться здесь. ;)
sergz692
 
Сообщения: 30
Зарегистрирован: 22.01.2013, 00:13
Благодарил (а): 4 раз.
Поблагодарили: 32 раз.
Играю в: RailWorks

И снова про html-файлы...

Сообщение sergz692 » 09.02.2013, 00:44

Не думал я, что придётся вернуться к этой теме, но...

Замечание Skifа сподвигло меня сгородить ещё одну демонстрашку, совем коротенькую.
Надеюсь что, "Железная дорога Касл-Рока" уж точно есть у всех? :P

Скачать новый демо-сценарий можно тут: http://yadi.sk/d/1rlpf4Aq3dMZq

Теперь о главном. Сделал html-файлики по образу и подобию цементного сценария:
Код: Выделить всё
<HTML>
   <BODY BGCOLOR="#0000007F">
      <FONT COLOR="#FFFFFF" FACE="Arial" SIZE="4">      
         <TABLE>
            <TR valign="top">   
               <TD><FONT COLOR="#FFFFFF" FACE="Arial" SIZE="4">
                      <P align="center"><B>Рабочий:</B></P>
                  <P align="center"><img src="../WM.png" alt="" width="128" height="128" /></P>
               </FONT></TD>
               <TD><FONT COLOR="#FFFFFF" FACE="Arial" SIZE="4">
                  <P>Эй, гони-ка сюда!</P>
               </FONT></TD>
            </TR>
         </TABLE>
      </FONT>
   </BODY>
</HTML>


И с ходу напоролся на то, что картинка и часть текста из окна пропали:
Изображение

Путём долгих экспериментов удалось выяснить, что "шкуру портит" атрибут выравнивания в теге "<P align="center">":
Код: Выделить всё
<HTML>
   <BODY BGCOLOR="#0000007F">
      <FONT COLOR="#FFFFFF" FACE="Arial" SIZE="4">      
         <TABLE>
            <TR valign="top">   
               <TD><FONT COLOR="#FFFFFF" FACE="Arial" SIZE="4">
                  <P><img src="../WM.png" alt="" width="128" height="128" /></P>
               </FONT></TD>
               <TD><FONT COLOR="#FFFFFF" FACE="Arial" SIZE="4">
                      <P><B>Рабочий:</B></P>
                  <P>Эй, гони-ка сюда!</P>
               </FONT></TD>
            </TR>
         </TABLE>
      </FONT>
   </BODY>
</HTML>


И сразу дело пошло на лад, правда сообщение пришлось чуток переформатировать:
Изображение

Вот так вот, а казалось бы, в чём разница? >:D
Для экспериментов нерабочий вариант первого сообщения оставил в файле "wrong - msg000.html"

Про остальные возможности скрипта, и про управление камерой, думаю, поговорим завтра. :hi:
Последний раз редактировалось sergz692 18.06.2013, 18:18, всего редактировалось 2 раз(а).
sergz692
 
Сообщения: 30
Зарегистрирован: 22.01.2013, 00:13
Благодарил (а): 4 раз.
Поблагодарили: 32 раз.
Играю в: RailWorks

Возможности универсального скрипта и управление камерой

Сообщение sergz692 » 10.02.2013, 20:01

Последний ключевой вопрос, который ещё не был здесь освещён - полное описание универсального скрипта.

Универсальный скрипт может принимать и обрабатывать следующие события:

  1. События-команды:
    • "lock" - заблокировать управление поездом
    • "unlock" - разблокировать управление поездом
    • "stop" - применить аварийное торможение
    • "halt" - заглушить двигатель локомотива
    • "cab" - активировать камеру в кабине локомотива
    • "break" - досрочно завершить сценарий с неудачей
  2. События, выводящие текстовые сообщения:
    • "msgFileName=N" - выводит сообщение из файла "msgFileName.html",
      в окне размера "s"=(l,r,s), в режиме "g"=(p,g), с таймаутом N, но не менее 15 с

      Примеры:
      "mlp000" - текстовое сообщение в большом окне, в режиме паузы, из файла "mlp000.html"
      "mlg001" - текстовое сообщение в большом окне, без паузы, из файла "mls001.html", с таймаутом 15 с
      "mrp002" - текстовое сообщение в среднем окне, в режиме паузы, из файла "mrp002.html"
      "msg003=40" - текстовое сообщение в малом окне, без паузы, из файла "msg003.html", с таймаутом 40 с
  3. События, управляющие поездом:
    • "engParName=C" - устанавливает управляющее значение C для параметра "ParName"

      Примеры:
      "engHeadlights=1" - включить головной прожектор
      "engReverser=1" - реверсор в положение "вперёд", "-1" соответствует "назад", а для паровоза "%" от -0.75 до 0.75
      "engRegulator=0.45" - регулятор в положение "45%", от 0 до 1
      "engTrainBrakeControl=0" - тормоза поезда в "0%", от 0 до 1

      Список далеко не полный, кто что ещё сможет "нарыть", пишите тут.
  4. События, управляющие камерой:
    • "camCameraName=T" - активировать камеру "CameraName" на время T, если T не задано или 0,
      время шоу определяется настройками камеры

      Примеры для некоторых встроенных камер:
      "camCouplingCamera" - камера сцепки
      "camCabCamera" - камера в кабине, эквивалетно команде "cab"
      "camTrackSideCamera" - боковая камера
      "camFreeCamera" - свободная камера
      "camYardCamera" - видимо то же, что и боковая
      "camHeadOutCamera" - выглянуть из кабины сбоку

      Про полноту списка опять же не говорю.
  5. События, управляющие погодой:
    • "wetWeatherEventChain" - запустить погодную цепочку с именем "WeatherEventChain"

      Примеры и подробности будут отдельно.

Цепочки событий

Универсальный скрипт позволяет обрабатывать несколько событий последовательно, то есть по цепочке.

События в цепочке отделяются друг от друга знаком "+"
Если между знаками "+" находится число, то это задержка в секундах до исполнения следующего события в цепочке
Один знак "+" без указания задержки означает, что следующее событие в цепочке будет обработано через 0.1 с

Предположим, что в теге "Scenario.bin" записана такая строка:
Код: Выделить всё
<SuccessEvent d:type="cDeltaString">lock+camCamera1+36+msg000+10+engHeadlights=1+engReverser=1+engRegulator=0.45+engTrainBrakeControl=0+15+cab+10+unlock</SuccessEvent>


Тогда эта цепочка будет обработана универсальным скриптом следующим образом:
  1. Событие - "lock"
  2. Задержка 0.1 с
  3. Событие - "camCamera1"
  4. Задержка 36 с
  5. Событие - "msg000"
  6. Задержка 10 с
  7. Событие - "engHeadlights=1"
  8. Задержка 0.1 с
  9. Событие - "engReverser=1"
  10. Задержка 0.1 с
  11. Событие - "engRegulator=0.45"
  12. Задержка 0.1 с
  13. Событие - "engTrainBrakeControl=0"
  14. Задержка 15 с
  15. Событие - "cab"
  16. Задержка 10 с
  17. Событие - "unlock"

Представьте себе, что без цепочки, для каждого события (ну может быть кроме первого) пришлось бы
добавлять в сценарий отдельную триггерную инструкцию. Кстати RSC именно так и делает :olen:

Остаётся добавить, что разобранная цепочка практически полностью обеспечивает работу моей новой демонстрашки.
Собственно кроме неё там есть ещё одно единственное событие, выдающее финальное сообщение сценария.

И подробнее про управление камерой

В TS 2013 появился очень удобный инструмент для создания скриптовых "роликов".
Называется он "Cinematic Camera" и находится в палитре редактора сценариев:
Изображение
В центре картинки можно видеть как "Cinematic Camera" отображается "на местности".
Если выбрать этот оъбект двойным щелчком, то справа откроется окошко свойств.

1) Имя камеры. Именно это имя потом будет фигурировать в событии "camXXXXXX"
2) Кнопочки помогающие сориентировать камеру. Одна из них наводит камеру на сценарные объекты,
а вторая на маршрутные.

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

3) Кнопочка воспроизведения позволяет "взглянуть" через эту камеру, и проверить "кадр"

После того как камера установлена, можно определить ещё одну точку кнопочкой (4), после нажатия которой
выделенную камеру можно тащить в другое место. Устанавливаем, наводим, проверяем. Две точки положения
этой камеры теперь связаны синими линиями.

Переключаться между точками можно кнопочками (5)

Время "просмотра" в поле (6) определяет скорость "полёта" камеры до позиции следующей точки.

После того как все точки и ракурсы выбраны, а время просмотра установлено, нажатие кнопочки (3) покажет
весь "ролик" от начала и до конца:

Если необходимо, чтобы камера оставалась неподвижной в точке на какое-то время, создайте в этой точке ещё одну.
Просто нажмите кнопку (4) и не трогайте камеру, тогда она будет "висеть" на этом месте всё указанное в (6) время.


Вроде бы всё про камеру, только кину, пожалуй, ещё и ссылочку на англоязычный форум по этой же теме:
http://forums.uktrainsim.com/viewtopic. ... 6&t=127205

Осталось только рассказать про погоду. Но это уже как-нибудь в следующий раз :hi:


PS: Да, так самолично кодить на lua желающие есть? Нужна ли тема с обсуждением кода моего скрипта, примерами, или нет? А то все молчат :P
sergz692
 
Сообщения: 30
Зарегистрирован: 22.01.2013, 00:13
Благодарил (а): 4 раз.
Поблагодарили: 32 раз.
Играю в: RailWorks

Re: Как оформить свой сценарий в "новом стиле".

Сообщение supermax » 10.02.2013, 21:12

Отличное пособие. Ещё бы сделал кто-нибудь хороший мануал по профессиональному созданию обычных сценариев и сценариев на время. Обучающие мануалы нужны почти во всех областях - начиная от редактора сценариев заканчивая редактором маршрутов RW.
И попросил бы тег с параметрами не называть "универсальным скриптом", это просто тег с параметрами и не более. А то коробит меня эта фраза сильно :)
Вот пример функций для скрипта сценария:
1. Включение камеры с заданным именем на определённое время (для триггера).
Код: Выделить всё
SysCall ( "CameraManager:ActivateCamera", "[имя_камеры]", [задержка] );

где
имя_камеры - указывается заданное конфигом имя камеры, либо зарезервированные имена.
задержка - задержка удержания камеры, указывается в секундах.

2. Перемещение свободной камеры в заданную точку на определённое время (для триггера).
Код: Выделить всё
SysCall ( "CameraManager:JumpTo", [latitude], [longitude], [Height] );

где
[latitude] - указывается широта в формате: X.XXXXX
[longitude] - указывается долгота в формате: X.XXXXX
[Height] - высота камеры над землёй, указывается в метрах

3.Перемещение камеры к определённому объекту (для триггера).
Код: Выделить всё
SysCall ( "CameraManager:LookAt", [Name]);

где
Name - указывается имя объекта в редактора (мало какие объекты имеют уникальные имена) или номер объекта (это имеют единицы ПС собственные номера, их можно увидеть щёлкнув 2 раза по вагону, локу и глянув номерок в панельке справа).

4.Блокирование элементов управления локомотива игрока
Код: Выделить всё
SysCall ( "ScenarioManager:LockControls");

При выполнении триггера бокируются все леверы, кнопки в кабине игрока, пока не будет подана противоположная по значению команда, см. ниже.

5.Разблокирование элементов управления локомотива игрока
Код: Выделить всё
SysCall ( "ScenarioManager:UnlockControls");


Разблокировка ранее заблокированных элементов управления.
Существует некоторый функционал по скриптам и для команд для ботов, ну точнее по срабатыванию триггера например включить прожектор у состава AI... По факту это как раз аналог команд для ботов в ТРС, правда в РВ реализован на примитивнейшем уровне и тем более очень много полезного функционала скрыто в недрах кода :)

Также у меня есть набор целых мессаджей которые можно выдавать в сценариях... Обработать бы как-нибудь всю эту информацию да в мануальчик)))
7 раз подумай - 1 раз напиши.
supermax
 
Сообщения: 596
Зарегистрирован: 24.08.2011, 14:03
Откуда: Краснодар
Благодарил (а): 70 раз.
Поблагодарили: 238 раз.
Блог: Просмотр блога (2)
Играю в: RailWorks
Имя: Максим

Re: Как оформить свой сценарий в "новом стиле".

Сообщение sergz692 » 10.02.2013, 21:32

sergz692 писал(а):Скрипт для своего сценария я изначально писал как универсальный, то есть, принимая некоторые соглашения и простые правила, вы сможете использовать этот готовый отлаженный код для своих сценариев, не написав самостоятельно ни одной строчки на lua...


... не забудьте перекопировать туда же следующие файлы из папки демо-сценария: "ScenarioScript.lua", "ScenarioScript.luac" и "ScenarioScript.luac.MD5".

supermax писал(а):И попросил бы тег с параметрами не называть "универсальным скриптом", это просто тег с параметрами и не более. А то коробит меня эта фраза сильно :)

Вы, простите, что сказать-то хотели? :blink: :P

supermax писал(а):Вот пример функций для скрипта сценария:

Это лишь отдельные строки кода. Раз уж начали, привели бы полный код скрипта для сценария, да с подробными пояснениями. :wink:
sergz692
 
Сообщения: 30
Зарегистрирован: 22.01.2013, 00:13
Благодарил (а): 4 раз.
Поблагодарили: 32 раз.
Играю в: RailWorks

И последнее. Про погоду ;)

Сообщение sergz692 » 12.02.2013, 20:53

Для управления погодой в TS 2013 к сценарию необходимо подключить так называемую "дополнительную" погоду, это отдельный bin-файл содержащий описание вызываемых погодных цепочек. Для подключения погды к сценарию необходимо отредактировать файл "ScenarioProperties.xml".

Открываем "ScenarioProperties.xml" в редакторе, и ищем там тег "<WeatherExtensionBlueprint>":
Код: Выделить всё
<WeatherExtensionBlueprint>
   <iBlueprintLibrary-cAbsoluteBlueprintID>
      <BlueprintSetID>
         <iBlueprintLibrary-cBlueprintSetID>
            <Provider d:type="cDeltaString">RSC</Provider>
            <Product d:type="cDeltaString">ShermanHill</Product>
         </iBlueprintLibrary-cBlueprintSetID>
      </BlueprintSetID>
      <BlueprintID d:type="cDeltaString">weather\thunderheads.xml</BlueprintID>
   </iBlueprintLibrary-cAbsoluteBlueprintID>
</WeatherExtensionBlueprint>

Необходимо заполнить соответствующими значениями следующие суб-теги:
"<Provider" - имя подпапки по пути "Steam\steamapps\common\railworks\Assets"
"<Product" - имя подпапки в папке описаной тегом "<Provider"
"<BlueprintID" - путь и имя bin-файла относительно папки описанной тегом "<Product"

Погодный файл, который в нашем случае находится в "Assets\RSC\ShermanHill\Weather\Thunderheads.bin", конвертируем утилитой "serz.exe" в xml-формат, открываем в редакторе и ищем тег "<TriggeredWeatherEventChain>":
Код: Выделить всё
<TriggeredWeatherEventChain>
   <cTriggeredWeatherEventChain d:id="44208376">
      <Name d:type="cDeltaString">FirstChain</Name>
      <BlendOutTime d:type="sFloat32" d:alt_encoding="000000403333D33F" d:precision="string">0.3</BlendOutTime>
      <LoopMode d:type="cDeltaString">eStop</LoopMode>
                                *******************************************************************
   </cTriggeredWeatherEventChain>
   <cTriggeredWeatherEventChain d:id="81368480">
      <Name d:type="cDeltaString">SecondChain</Name>
      <BlendOutTime d:type="sFloat32" d:alt_encoding="000000403333D33F" d:precision="string">0.3</BlendOutTime>
      <LoopMode d:type="cDeltaString">eStop</LoopMode>
                                *******************************************************************
   </cTriggeredWeatherEventChain>
   <cTriggeredWeatherEventChain d:id="77232544">
      <Name d:type="cDeltaString">FinalStorm</Name>
      <BlendOutTime d:type="sFloat32" d:alt_encoding="000000000000F03F" d:precision="string">1</BlendOutTime>
      <LoopMode d:type="cDeltaString">eStop</LoopMode>
                                *******************************************************************
   </cTriggeredWeatherEventChain>
   <cTriggeredWeatherEventChain d:id="63148064">
      <Name d:type="cDeltaString">PrettyRainbowAhh</Name>
      <BlendOutTime d:type="sFloat32" d:alt_encoding="000000000000F03F" d:precision="string">1</BlendOutTime>
      <LoopMode d:type="cDeltaString">eStop</LoopMode>
                                *******************************************************************
   </cTriggeredWeatherEventChain>
</TriggeredWeatherEventChain>

Изучаем вложенные в него цепочки, описанные тегами "<cTriggeredWeatherEventChain", собственно нас интересует вложенные туда субтеги "<Name".

Имя содержащееся в теге "<Name" с префиксом "wet" и будут именем события, обрабатывая которое, универсальный скрипт запустит соответствующую погодную цепочку.

Не сложно увидеть, что файл "Thunderheads.bin" поддерживает следующие "погодные" события: "wetFirstChain", "wetSecondChain", "wetFinalStorm" и "wetPrettyRainbowAhh".


Собственно на этом всё. Мануал свёрстан. Желаю творческих успехов! :hi:


Добавлено спустя 3 часа 37 минут 34 секунды:

Да, и вопрос по скриптописательству так и остался открытым :)

Lua-код универсального скрипта постим/обсуждаем? :book:
Если постим и обсуждаем, то здесь, или в отдельной теме? :vah:
Последний раз редактировалось sergz692 09.03.2013, 02:23, всего редактировалось 2 раз(а).
sergz692
 
Сообщения: 30
Зарегистрирован: 22.01.2013, 00:13
Благодарил (а): 4 раз.
Поблагодарили: 32 раз.
Играю в: RailWorks

Re: Как оформить свой сценарий в "новом стиле".

Сообщение djus » 13.02.2013, 13:33

Очень хороший материал, большое спасибо!
Немного разобрался получилось вот такое дэмо

http://yadi.sk/d/c_tsYwSX2_PEA :D

Всё очень хорошо расписано понятным языком :essen:

Есть вопрос : Можно при воспроизведении камеры убрать панель F4 - ?
А то мешает очень, смотреться не очень да вообще она не к месту.
В сценарии видно, в начале когда камера перемещается.
Аватара пользователя
djus
 
Сообщения: 87
Зарегистрирован: 22.01.2013, 01:15
Откуда: Объект 19
Благодарил (а): 184 раз.
Поблагодарили: 132 раз.
Играю в: RailWorks
Имя: виталий

Re: Как оформить свой сценарий в "новом стиле".

Сообщение sergz692 » 13.02.2013, 15:08

djus
Панель убирается при блокировке управления поездом. Правда прибегая к такому радикальному средству
необходимо учитывать, что в этот момент происходит с поездом игрока: блокировка контроля не приводит
к остановке поезда, игрок просто лишается возможности хоть как-то влиять на процесс ;)

А так всё просто, создаёте цепочку типа: "lock+camCameraName=T1+T2+unlock", где Т1 время показа "ролика",
которое может быть задано, в том числе, и через настройки самой камеры, а Т2 - время через которое
управление вернётся обратно к игроку.


Вскрыл демонстрашку, сейчас первая цепочка выглядит так:
"msg004=23+halt+camcamera1+50+cab+4+msg000+20+msp001"
Чтобы всё было как задумано, рекомендую такую модификацию:
"lock+msg004=23+halt+camcamera1+50+cab+unlock+4+msg000+20+msp001"


Поигрался в демонстрашку: вполне достойно. :up:

Если есть желание увидеть один из глюков TS 2013, то добавь время стоянки на последнем пункте, минут до 10.
Тогда можно будет лицезреть, как поезд (Сервис2 кажется) который идёт сзади доедет до Хекспирии, свернёт
на тот же самый запасной и врежется в наш поезд. =:)

Перевести его на другую колею тоже не получится (ещё один глюк), тогда и наш поезд попадёт туда же, и в Хекспирию
он просто не сможет заехать. Единственных вариант - тихо "утилизировать" этот поезд где-нибудь в портале по пути. :P
sergz692
 
Сообщения: 30
Зарегистрирован: 22.01.2013, 00:13
Благодарил (а): 4 раз.
Поблагодарили: 32 раз.
Играю в: RailWorks

Re: Как оформить свой сценарий в "новом стиле".

Сообщение YuriA » 15.02.2013, 09:52

Поигрался с "цементным" сценарием. До конца не дошёл, всё времени не хватает. Ну конечно с погодой ты перемудрил. Время 11.30, а темень такая что ничего не видно. Дождь заливает так, что дворники не справляются. Жесть полная, апокалипсис. Хотя понятно что это демо, для показа возможностей.

p.s. При загрузке сохранённого сценария, опять ясное небо. Я ещё подумал, чего-то у меня дворники мотаются. Два раза пробовал,из разных точек сохранения, эффект один и тот же - дождя нет, дворники работают (это понятно я их не выключил при сохранении).
YuriA
 
Сообщения: 13
Зарегистрирован: 07.11.2012, 10:55
Благодарил (а): 9 раз.
Поблагодарили: 1 раз.
Имя: Юрий

След.

Вернуться в [RW] Маршруты и сценарии

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

Сейчас этот форум просматривают: Google [Bot] и гости: 2