
- •Урок 1. Создание квеста на одновременный поиск двух различных предметов.
- •Урок 3. Реализация квеста на одновременный поиск заданного количества различных предметов, определенных в рандомной таблице. Определение новой условной функции в xr_conditions.Script
- •Урок 4. Построение квеста на одновременный поиск заданного количества заранее опеределенных различных предметов.
- •Урок 6. Реализация квеста на выполнение определенного действия через логику рестриктора, работа с туториалом. Последовательность в выполнении на несколько этапов.
- •Урок 9. Создание квеста с добавлением дополнительных внутри этапных заданий. Особенности - отсутствие диалогов, добавление тайников в качестве квестовых предметов.
- •Урок 10. Реализация квеста с использованием объекта класса inventory_box со сложной логикой. Особенности - отсутствие диалогов, использование рестрикторов, выдача тайника в качестве награды.
- •На этом первый курс квестостроения завершен.
Урок 6. Реализация квеста на выполнение определенного действия через логику рестриктора, работа с туториалом. Последовательность в выполнении на несколько этапов.
Предположим нам необходимо реализовать квест следующего типа: ГГ будет выдано задание на извлечение определенного предмета из физического обьекта на локации. Пусть будет такой вариант: Сыч дает Дягтереву задание на изьятие из старой антенны и генератора на ВНЗ Круг различных деталей. Для осуществления подобных заданий необходимо использовать рестрикторы. Данный тип квестов в корне отличается от простых, когда по заданным меткам необходимо было просто подобрать заспавненные ранее предметы.
Необходимые для редактирования файлы:
1. конфигурационные в (gamedata\configs\gameplay\) -character_desc_zaton.xml -dialogs_zaton.xml -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - quest_items.ltx - death_generic.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_dialogs_zaton.xml - st_quests_zaton.xml - ui_st_screen.xml - st_items_quest.xml 4. конфигурационные в (gamedata\configs\ui\) - game_tutorials.xml 5. логики рескрипторов в (gamedata\configs\scripts\zaton\) - zat_restr_logic_1.ltx - zat_restr_logic_2.ltx 6. скриптовый в (gamedata\scripts\) - dialogs_zaton.script - xr_effects.script - ui_si.script 7. Спавн в файле all.spawn (gamedata\spawns\) - alife_zaton.ltx
Для начала добавим один общий диалог на выдачу и завершения квеста. (В принципе можно было не усложнять и сделать два простых диалога, но рассмотрим более сложный вариант) В файл dialogs_zaton.xml в самом низу добавим диалог:
Code
<dialog id="zat_b106_stalker_sich_test_quest_dialog"> <dont_has_info>zat_b106_sich_quest_complete</dont_has_info> <phrase_list> <phrase id="0"> <text>zat_b106_stalker_sich_test_quest_dialog_0</text> <next>1</next> <next>2</next> </phrase> <phrase id="1"> <dont_has_info>zat_b106_sich_quest_begin</dont_has_info> <text>zat_b106_stalker_sich_test_quest_dialog_1</text> <next>11</next> <next>12</next> </phrase> <phrase id="12"> <text>zat_b106_stalker_sich_test_quest_dialog_12</text> <action>dialogs.break_dialog</action> </phrase> <phrase id="11"> <text>zat_b106_stalker_sich_test_quest_dialog_11</text> <next>111</next> </phrase> <phrase id="111"> <text>zat_b106_stalker_sich_test_quest_dialog_112</text> <action>dialogs_zaton.zat_b106_sich_give_tasks</action> <give_info>zat_b106_sich_quest_begin</give_info> </phrase> <phrase id="2"> <has_info>zat_b106_sich_quest_begin</has_info> <text>zat_b106_stalker_sich_test_quest_dialog_2</text> <next>3</next> <next>4</next> </phrase> <phrase id="4"> <dont_has_info>zat_b106_sich_quest_restr_2</dont_has_info> <text>zat_b106_stalker_sich_test_quest_dialog_4</text> <action>dialogs.break_dialog</action> </phrase> <phrase id="3"> <has_info>zat_b106_sich_quest_restr_2</has_info> <text>zat_b106_stalker_sich_test_quest_dialog_3</text> <give_info>zat_b106_sich_quest_complete</give_info> <next>331</next> </phrase> <phrase id="331"> <text>zat_b106_stalker_sich_test_quest_dialog_331</text> <next>332</next> </phrase> <phrase id="332"> <text>zat_b106_stalker_sich_test_quest_dialog_332</text> <action>dialogs_zaton.zat_b106_sich_quest_relocate_item</action> <next>333</next> </phrase> <phrase id="333"> <text>zat_b106_stalker_sich_test_quest_dialog_333</text> <action>dialogs_zaton.zat_b106_sich_quest_relocate_reward</action> <next>334</next> </phrase> <phrase id="334"> <text>zat_b106_stalker_sich_test_quest_dialog_334</text> </phrase> </phrase_list> </dialog>
Чтобы понимать о чем в диалогах идет речь сразу пропишем русскую транскрипцию фраз в файле st_dialogs_zaton.xml
Code
<string id="zat_b106_stalker_sich_test_quest_dialog_0"> <text>Я по поводу работы.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_1"> <text>Работы, хм. Ах да забыл. Есть у меня одно поручение. Нужно сходить на ВНЗ Круг и снять показатели нескольких старых приборов. С одной антенны и старого генератора. Ну что, согласен?</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_11"> <text>Да, сделаю.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_12"> <text>Пока есть другие дела.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_112"> <text>Отлично, жду. Награду достойную получишь.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_2"> <text>Ну что, сделал что я просил?</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_4"> <text>Нет, работаю над этим.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_3"> <text>Да. Все сделано.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_331"> <text>Отлично, давай сюда приборы.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_332"> <text>Забирай.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_333"> <text>Вот твоя награда. Успехов сталкер.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_334"> <text>Бывай.</text> </string>
Теперь разберем по порядку его структуру. Диалог на выдачу и завершение квеста имеет следующую структуру: 1. Первая часть диалога на выдачу задания. (ветка <next>1</next>) - ГГ предлагают задание и он на выбор может временно отказаться от него, тогда диалог будет доступен во второй раз. Либо же согласиться на исполнение. - соответственно при согласии происходит выдача инфопоршня zat_b106_sich_quest_begin (при старте квеста) и выдача самого квеста через актшион <action>dialogs_zaton.zat_b106_sich_give_tasks</action>. - На этом генерация ветки диалога на выдачу задания будет заблокирована, из-за наличия во фразе 1 условия<dont_has_info>zat_b106_sich_quest_begin</dont_has_info> 2. Вторая часть диалога доступная уже после взятия задания. - Ее генерация происходит путем активации ветки (<next>2</next>), первая фраза которой будет доступна только после старта задания то есть наличия условия <has_info>zat_b106_sich_quest_begin</has_info> - Следующие фразы будут доступны также на выбор (<next>3</next> и <next>4</next>) Фраза 4 будет доступна сразу же после взятия квеста- она будет являться закрывающей диалог (акшион <action>dialogs.break_dialog</action>). Генерируется она путем наличия условия <dont_has_info>zat_b106_sich_quest_restr_2</dont_has_info> Эта фраза сообщает о том что ГГ еще не выполнил задание. - Фраза 3 которая является веткой завершения диалога будет доступна только при наличии условия<has_info>zat_b106_sich_quest_restr_2</has_info> (этот инфопоршень мы получим в процессе выполнения квеста) при этом фраза 4 будет заблокирована. - в третьей фразе будет происходить выдача условия <give_info>zat_b106_sich_quest_complete</give_info> обеспечивающего завершение квеста и полное блокирование диалога. - также отметим наличие акшионов <action>dialogs_zaton.zat_b106_sich_quest_relocate_item</action> и<action>dialogs_zaton.zat_b106_sich_quest_relocate_reward</action> отвечающих за передачу квестовых предметов и выдачу награды.
Объявим используемые инфопоршни в info_zaton.xml. Добавим в конце файла код:
Code
<info_portion id="zat_b106_sich_quest_complete"></info_portion> <info_portion id="zat_b106_sich_quest_begin"></info_portion> <info_portion id="zat_b106_sich_quest_restr_1"></info_portion> <info_portion id="zat_b106_sich_quest_restr_2"></info_portion>
Добавим наш диалог НПС (В данном случае Сычу) для этого в файл character_desc_zaton.xmlв его профиль<specific_character id="zat_b30_owl_stalker_trader" team_default="1"> добавим строку диалога
Code
.... <actor_dialog>zat_b106_stalker_sich_test_quest_dialog</actor_dialog> ....
С диалогами и инфопоршнями разобрались теперь добавим необходимые для выполнения квеста предметы, а также файлы связанный с ними. В файл quest_items.ltx пропишем две секции предметов zat_b206_sich_quest_item_1 и zat_b206_sich_quest_item_2. Оба предмета являются квестовыми- невозможна их продажа и выкладывание из инвентаря
Code
[zat_b206_sich_quest_item_1]:device_pda $spawn = "quest_items\zat_b206_sich_quest_item_1" visual = dynamics\equipments\quest\materials_textolite.ogf description = st_zat_b206_sich_quest_item_1_descr inv_name = st_zat_b206_sich_quest_item_1_name inv_name_short = st_zat_b206_sich_quest_item_1_name inv_weight = 0.1 can_trade = false quest_item = true inv_grid_width = 1 inv_grid_height = 1 inv_grid_x = 2 inv_grid_y = 19 [zat_b206_sich_quest_item_2]:device_pda $spawn = "quest_items\zat_b206_sich_quest_item_2" visual = dynamics\equipments\quest\materials_wire.ogf description = st_zat_b206_sich_quest_item_2_descr inv_name = st_zat_b206_sich_quest_item_2_name inv_name_short = st_zat_b206_sich_quest_item_2_name inv_weight = 0.1 can_trade = false quest_item = true inv_grid_width = 1 inv_grid_height = 1 inv_grid_x = 14 inv_grid_y = 19
В файл death_generic.ltx пропишем: (в данном случае также необязательно так как генерации в инвентаре НПС нет)
Code
.... zat_b206_sich_quest_item_1 = true zat_b206_sich_quest_item_2 = true ....
В файл ui_si.script таблица info_table добавим (для спавна, в принципе работать будет и без внесения в этот файл):
Code
.... "zat_b206_sich_quest_item_1", "zat_b206_sich_quest_item_2", ....
В файл st_items_quest.xml пропишем дескрипцию предметов.
Code
<string id="st_zat_b206_sich_quest_item_1_name"> <text>Первая деталь</text> </string> <string id="st_zat_b206_sich_quest_item_1_descr"> <text>Одна из основных деталей общей схемы в исседовательской антенне.</text> </string> <string id="st_zat_b206_sich_quest_item_2_name"> <text>Вторая деталь</text> </string> <string id="st_zat_b206_sich_quest_item_2_descr"> <text>Одна из компановочных составляющих старого генератора.</text> </string>
С квестовыми предметами разобрались, теперь же добавим рестрикторы используемые в квесте. - Прежде всего создадим сами рестрикторы добавив в файл alife_zaton.ltx распакованного программой ACDC all.spawn
Code
[zaton_1865120] ; cse_abstract properties section_name = space_restrictor name = zat_test_quest_restrictor_1 position = -432.537384048828,11.5833719020996,-46.925877601563 direction = 0,0.841602981090546,0 ; cse_alife_object properties game_vertex_id = 51 distance = 0 level_vertex_id = 131423 object_flags = 0xffffff3e custom_data = <<END [story_object] story_id = zat_restr_1_id [logic] cfg = scripts\zaton\zat_restr_logic_1.ltx END ; cse_shape properties shapes = shape0 shape0:type = box shape0:axis_x = 4,0,0 shape0:axis_y = 0,3.13100147247314,0 shape0:axis_z = 0,0,2 shape0:offset = 0,0,0 ; cse_alife_space_restrictor properties restrictor_type = 3 [zaton_1865121] ; cse_abstract properties section_name = space_restrictor name = zat_test_quest_restrictor_2 position = -391.867065048828,10.9986919020996,-15.951530601563 direction = 0,0.841602981090546,0 ; cse_alife_object properties game_vertex_id = 51 distance = 0 level_vertex_id = 190168 object_flags = 0xffffff3e custom_data = <<END [story_object] story_id = zat_restr_2_id [logic] cfg = scripts\zaton\zat_restr_logic_2.ltx END ; cse_shape properties shapes = shape0 shape0:type = box shape0:axis_x = 4,0,0 shape0:axis_y = 0,3.13100147247314,0 shape0:axis_z = 0,0,2 shape0:offset = 0,0,0 ; cse_alife_space_restrictor properties restrictor_type = 3
- Имена секций рестикторов должны быть уникальны (как собственное имя, так и порядковое внутри алл спавна) - Они должны иметь тип 3 - Координаты точки спавна рестикторов должны задаваться рядом с тем объектом на локации который мы будем использовать. (position, level_vertex_id, game_vertex_id) - story_id = zat_restr_2_id- уникальный айди номер рестриктора на который будет выставляться квестовая метка. - shape0- общий тип и размер зоны рестриктора- при изменении числовых значений можно как увеличить, так и уменьшить радиус активной зоны вблизи юзаемого предмета. - cfg = scripts\zaton\zat_restr_logic_2.ltx- путь к файлу логики рестриктора. Теперь пропишем логики рестрикторов. Рассмотрим только одну- вторая создается по образу первой. Создадим файл zat_restr_logic_1.ltx И пропишем в него следующий код:
Code
[logic] active = sr_idle@start [sr_idle@start] on_info = {+zat_b106_sich_quest_begin =actor_in_zone(zat_test_quest_restrictor_1)} sr_idle@tutorial %=run_tutorial(zat_sich_quest_1_tutor)% on_info2 = {+zat_b106_sich_quest_restr_1} sr_idle@nil [sr_idle@tutorial] on_info = {+zat_b106_sich_quest_begin !actor_in_zone(zat_test_quest_restrictor_1)} sr_idle@start %=stop_tutorial% on_info2 = {+zat_b106_sich_quest_restr_1} sr_idle@nil on_info3 = {!has_active_tutorial} sr_idle@start [sr_idle@nil]
Опишем что означает эта логика и по какому принципу она строиться: - всего логика имеет три секции это sr_idle@start- она же изначально активная, [sr_idle@tutorial] по исполнению гайм туториала, [sr_idle@nil]- нулевое значение логики. - основной принцип работы это проверка наличия двух условий- это старт квеста (zat_b106_sich_quest_begin) и наличия актора в зоне рестиктора =actor_in_zone(zat_test_quest_restrictor_1) при их соблидение подается команда на старт туториала юзания предмета %=run_tutorial(zat_sich_quest_1_tutor)% - если актор находился в зоне рестиктора, но потом вышел из нее !actor_in_zone(zat_test_quest_restrictor_1) происходит выдача команды на остановку туториала %=stop_tutorial% и возвращение логики в исходное стартовое состоянии. Запуск или остановку туториала можно проследить по активации надписи юзания предмета. - соответственно в независимости от того какая секция логики активна при выдаче инфопоршня zat_b106_sich_quest_restr_1происходит обнуление логики рестиктора. Дальнейшая работа туториалов в ней будет невозможно. Текст активирующийся при юзании рестриктора буде прописан в ui_st_screen.xml
Code
<string id="zat_sich_quest_tips"> <text>Извлечь деталь</text> </string>
Сам туториал пропишем в файле game_tutorials.xml
Code
<zat_sich_quest_1_tutor> <global_wnd/> <item> <disabled_key>quit</disabled_key> <length_sec/> <action id="use" finalize="1">xr_effects.zat_sich_quest_1</action> <guard_key>use</guard_key> <grab_input>0</grab_input> <main_wnd> <auto_static start_time="0" length_sec="5000" x="512" y="660" width="300" height="60" alignment="c" stretch="1"la_cyclic="1" la_texture="1" la_alpha="1"> <text font="graffiti22" r="225" g="225" b="250" a="255" align="c">zat_sich_quest_tips</text> </auto_static> </main_wnd> </item> </zat_sich_quest_1_tutor>
Основные параметры это: - <action id="use" finalize="1">xr_effects.zat_sich_quest_1</action> выполняемое действие по скрипту xr_effects.zat_sich_quest_1 - zat_sich_quest_tips- текст сообщения перед юзанием В файл xr_effects.script пропишем скрипты исполняемые при юзании рескриптора.
Code
function zat_sich_quest_1(actor, npc) if xr_conditions.actor_in_zone(actor, npc, {"zat_test_quest_restrictor_1"}) then db.actor:give_info_portion("zat_b106_sich_quest_restr_1") give_actor(db.actor,nil,{"zat_b206_sich_quest_item_1"}) end end function zat_sich_quest_2(actor, npc) if xr_conditions.actor_in_zone(actor, npc, {"zat_test_quest_restrictor_2"}) then db.actor:give_info_portion("zat_b106_sich_quest_restr_2") give_actor(db.actor,nil,{"zat_b206_sich_quest_item_2"}) end end
-Происходит проверка наличия актора в зоне zat_test_quest_restrictor_1 и если оно истинно тогда происходит выдача инфопоршня zat_b106_sich_quest_restr_1 и спавн в рюкзак ГГ айтема zat_b206_sich_quest_item_1
С рестрикторами все ясно. Теперь пропишем остальные скриптовые функции: В файле dialogs_zaton.script добавим следующие функции:
Code
function zat_b106_sich_give_tasks(first_speaker, second_speaker) task_manager.get_task_manager():give_task("geonezis_zat_b206_sich_example_task") end function zat_b106_sich_quest_relocate_item(first_speaker, second_speaker) local items_table = { "zat_b206_sich_quest_item_1", "zat_b206_sich_quest_item_2", } for k,v in pairs(items_table) do if db.actor:object(v) ~= nil then dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, v) end end end function zat_b106_sich_quest_relocate_reward(first_speaker, second_speaker) dialogs.relocate_money_to_actor(first_speaker, second_speaker, 5000) end
Поясним их: - Выдача квеста - Передача квестовых предметов неписю - Выдача ГГ награды за квест
Так и собственно в завершении осталось расписать сам квест: В файл tm_zaton.ltx добавим код:
Code
[geonezis_zat_b206_sich_example_task] icon = ui_inGame2_Zamanchiviy_biznes prior = 1 storyline = false title = {+zat_b106_sich_quest_restr_2} zat_b206_sich_example_title2, {+zat_b106_sich_quest_restr_1 -zat_b106_sich_quest_restr_2} zat_b206_sich_example_title1, {-zat_b106_sich_quest_restr_1} zat_b206_sich_example_title0 descr = {+zat_b106_sich_quest_restr_2} zat_b206_sich_example_text2, {+zat_b106_sich_quest_restr_1 -zat_b106_sich_quest_restr_2} zat_b206_sich_example_text1, {-zat_b106_sich_quest_restr_1} zat_b206_sich_example_text0 target = {+zat_b106_sich_quest_restr_2} zat_b30_owl_stalker_trader_id, {+zat_b106_sich_quest_restr_1 -zat_b106_sich_quest_restr_2} zat_restr_2_id, {-zat_b106_sich_quest_restr_1} zat_restr_1_id condlist_0 = {+zat_b106_sich_quest_complete} complete condlist_1 = {+zat_b106_sich_quest_begin =is_squad_enemy_to_actor(zat_b30_owl_stalker_trader_squad)} fail on_complete = %=inc_faction_goodwill_to_actor(stalker:50)%
Пояснения: - квест исполняется в три этапа- сначала мы юзаем рестриктор 1, потом после этого второй и в завершении отдаем полученные предметы заказчику. Соответственно метки перемещаются с zat_restr_1_id на zat_restr_2_id и в завершении на Сыча zat_b30_owl_stalker_trader_id. При этом же обновляются тайтлы и дескрипшины этапов задания. Основные условия их изменения это выдача или же отсутствие двух основных инфопоршней zat_b106_sich_quest_restr_1 (получаемого при юзании первого рестриктора) и zat_b106_sich_quest_restr_2 (второго) - задание завершается при выдаче инфопоршня zat_b106_sich_quest_complete - квест будет провален если после его старта НПС заказчика стал враждебен по отношению к ГГ=is_squad_enemy_to_actor(zat_b30_owl_stalker_trader_squad) - по завершению квеста происходит повышение репутации у сталкеров %=inc_faction_goodwill_to_actor(stalker:50)% В файле st_quests_zaton.xml пропишем тайтлы и дескрипшины квеста:
Code
<string id="zat_b206_sich_example_title0"> <text>Задание Сыча: извлеките компонент из старой антенны.</text> </string> <string id="zat_b206_sich_example_text0"> <text>Необходимо отправиться на ВНЗ Круг и извлечь деталь обьекта со старой антенны.</text> </string> <string id="zat_b206_sich_example_title1"> <text>Задание Сыча: извлеките вторую деталь со старого генератора</text> </string> <string id="zat_b206_sich_example_text1"> <text>Заберите вторую необходимую заказчику деталь.</text> </string> <string id="zat_b206_sich_example_title2"> <text>Задание Сыча: отдайте заказчику найденные детали.</text> </string> <string id="zat_b206_sich_example_text2"> <text>Передайте все старые детали и компоненты Сычу.</text> </string>
На этом урок добавления подобного класса заданий завершен.
Урок 7. Создание квеста с добавлением дополнительных внутри этапных заданий. Особенности - отсутствие диалогов, использование рестрикторов, добавление квестовых предметов отдельного класса, работа с туториалами.
Поставленная задача в данном уроке будет заключаться в обучении основным принципам создания среднего по сложности квеста в игре Сталкер Зов Припяти без использования каких-либо диалогов. Выдача задания будет осуществляться автоматически, в данном случае зададим ее при старте игры. Также будет показан прием добавления во внутреннею структуру основного задания нескольких дополнительных подквестов и объяснение применение рестриторов на всех поставленных этапах.
Само задание следующее: При старте ГГ на ПДА придет сообщение о необходимости установки схронов. Осуществляется выдача квеста. Необходимо забрать утерянные рюкзаки и заложить их в трех указанных точках. После этого задание автоматически завершается. Выдача награды не предусмотрена.
Необходимые для редактирования файлы: 1. конфигурационные в (gamedata\configs\gameplay\) -character_desc_jupiter.xml -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_jupiter.ltx - quest_items.ltx - devices.ltx - death_generic.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml - st_items_quest.xml - ui_st_screen.xml 4. конфигурационные в (gamedata\configs\misc\trade\) - trade_generic.ltx 5. конфигурационные в (gamedata\configs\ui\) - game_tutorials.xml 6. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов 7. скриптовый в (gamedata\scripts\) - ui_si.script - bind_stalker.script - new_tasks.script - xr_effects.script 8. all.spawn. (gamedata\spawns\) - alife_zaton.ltx
На первоначальном этапе определимся с квестовыми предметами. Всего их шесть. Три будут отвечать за айтем рюкзака до его закладки. Они будут являться потомками основного родительского класса device_pda. Другие три будут определены другим классом, им будет соответствовать установленная логика и они отвечают за рюкзаки после установки схрона. Пропишем секции их конфигов в файле quest_items.ltx (Здесь и далее буду приводить конфиг только одной секции, остальные задаются аналогично только с изменением числовых значений в имени).
Code
[zat_example_taynik_1_item]:device_pda $spawn = "quest_items\zat_example_taynik_1_item" description = zat_example_taynik_item_descr inv_name = zat_example_taynik_item_name visual = dynamics\devices\dev_rukzak\dev_rukzak.ogf inv_weight = 2 story_id = zat_example_taynik_1_item can_trade = false quest_item = true inv_grid_width = 2 inv_grid_height = 2 inv_grid_x = 0 inv_grid_y = 38 .......... [zat_example_taynik_1]:default_inventory_box custom_data = scripts\zaton\inventory_boxs\zat_example_taynik_1.ltx ..........
Первый конфиг не содержит в себе прикрепленного файла в дополнительной секции и определяется как простой квестовый предмет, второй же содержит прикрепленный конфиг с логикой его zat_example_taynik_1.ltx Для определении секции zat_example_taynik_1 необходимо определить родительский класс default_inventory_box в файле devices.ltx
Code
[default_inventory_box] GroupControlSection = spawn_group discovery_dependency = $spawn = "devices\default_inventory_box" class = O_INVBOX cform = skeleton visual = dynamics\devices\dev_rukzak\dev_rukzak.ogf script_binding = bind_physic_object.init radius = 3 inv_grid_width = 2 inv_grid_height = 2 inv_grid_x = 0 inv_grid_y = 38 cost = 3500 can_take = true inv_weight = 1.14 description = inv_name = inv_name_short =
В этой секции указываются основные параметры такие как основной класс, форма, визуал. Кроме того определим его основную логику в конфигурационном файле zat_example_taynik_1.ltx
Code
logic] active = ph_idle@nothing [ph_idle@nothing] nonscript_usable = true tips = st_taynik_check_descr
Здесь указывается активная секция это ph_idle@nothing, а также ее содержание. Тайник после установки можно использовать, т.е. возможно его наполнение различными предметами, также при наведении на него будет активна надпись из секции st_taynik_check_descr…
Зарегистрируем конфиги первой секции предмета тайник zat_example_taynik_..._item. В файле death_generic.ltx пропишем код
Code
..... zat_example_taynik_1_item = true zat_example_taynik_2_item = true zat_example_taynik_3_item = true
В файле ui_si.script добавим
Code
"zat_example_taynik_1_item", "zat_example_taynik_2_item", "zat_example_taynik_3_item",
Обозначим секции, логику и работу рестрикторов необходимых для выполнения внутренних подквестов. В файле alife_zaton.ltx обозначим три секции
Code
[zaton_999999011] ; cse_abstract properties section_name = space_restrictor name = zat_test_quest_restrictor_1 position = 210.996811,15.980440,480.381104 direction = 0,0.841602981090546,0 ; cse_alife_object properties game_vertex_id = 6 distance = 0 level_vertex_id = 1323235 object_flags = 0xffffff3e custom_data = <<END [story_object] story_id = zat_restr_1_id [logic] cfg = scripts\zaton\zat_restr_logic_1.ltx END ; cse_shape properties shapes = shape0 shape0:type = box shape0:axis_x = 4,0,0 shape0:axis_y = 0,3.13100147247314,0 shape0:axis_z = 0,0,2 shape0:offset = 0,0,0
В секции указываются координаты и тип рестрикторов, их идентификатор, имя, тип и размер шейпа. В файле логики zat_restr_logic_1.ltx пропишем:
Code
[logic] active = sr_idle@start [sr_idle@start] on_info = {+zat_test_quest_rest_main_come =actor_in_zone(zat_test_quest_restrictor_1) =actor_has_item(zat_example_taynik_1_item)} sr_idle@tutorial %=run_tutorial(zat_test_quest_1_tutor)% on_info2 = {+zat_test_quest_restr_1} sr_idle@nil [sr_idle@tutorial] on_info = {+zat_test_quest_rest_main_come !actor_in_zone(zat_test_quest_restrictor_1)} sr_idle@start %=stop_tutorial% on_info2 = {+zat_test_quest_restr_1} sr_idle@nil on_info3 = {!has_active_tutorial} sr_idle@start [sr_idle@nil]
Отметим особенности: Активная секция sr_idle@start переход на вторую происходит по достижению трех условий - наличие инфопоршня активности второго этапа основного задания (zat_test_quest_rest_main_come) - актор находиться в зоне действия рестриктора - наличие в его инвентаре zat_example_taynik_1_item При выполнении всех этих условий выполняется работа рестриктора определяемая в туториале zat_test_quest_1_tutor При получении инфопоршня zat_test_quest_restr_1 происходит переход в третью нулевую секцию логики рестриктора sr_idle@nil При выхода актора из зоны рестриктора его работа прекращается и логика переключается во второе состояние sr_idle@tutorial из которого она может снова перейти в первое или в третье. Объявим в файле game_tutorials.xml туторы выполняемые в работе рестрикторов
Code
<zat_test_quest_1_tutor> <global_wnd/> <item> <disabled_key>quit</disabled_key> <length_sec/> <action id="use" finalize="1">xr_effects.zat_test_quest_1</action> <guard_key>use</guard_key> <grab_input>0</grab_input> <main_wnd> <auto_static start_time="0" length_sec="5000" x="512" y="660" width="300" height="60" alignment="c" stretch="1"la_cyclic="1" la_texture="1" la_alpha="1"> <text font="graffiti22" r="225" g="225" b="250" a="255" align="c">zat_test_quest_tips</text> </auto_static> </main_wnd> </item> </zat_test_quest_1_tutor>
Основные параметры это функция скрипта обработчика действия xr_effects.zat_test_quest_1 и активная надпись из секции zat_test_quest_tips В файле xr_effects.scripts определим функции
Code
function zat_test_quest_1(actor, npc) if xr_conditions.actor_in_zone(actor, npc, {"zat_test_quest_restrictor_1"}) then remove_item(actor, npc, {"zat_example_taynik_1_item"}) alife():create("zat_example_taynik_1",vector():set(210.996811,15.980440,480.381104),1323235,6) db.actor:give_info_portion("zat_test_quest_restr_1") end end
Опишем ее: - если выполнено условие нахождение актора в зоне рестриктора zat_test_quest_restrictor_1 то происходит удаление из инвентаря ГГ айтема первого конфига тайника zat_example_taynik_1_item, создается по заданным координатам второй zat_example_taynik_1 и выдается инфопоршень zat_test_quest_restr_1
Выдача задания будет происходит при старте ГГ одновременно с квестами основного сюжета. Для этого добавим инфопоршень выдачи и сам квест в секцию логики [sr_idle] оригинального рестриктор zat_b101_logic.ltx
Code
=give_task(geonezis_zat_test_example_task) +zat_test_quest_begin
Выдача подквестов будет осуществлять в логике другого рестриктора zat_restr_logic_main.ltx Его секция прописывается в all.spawn по аналогии с предыдущими. Сама логика имеет следующий вид:
Code
[logic] active = sr_idle@start [sr_idle@start] on_info = {+zat_test_quest_begin -zat_test_quest_rest_main_come =actor_in_zone(zat_test_quest_restrictor_main)} %=give_task(geonezis_zat_test_example_task_1) =give_task(geonezis_zat_test_example_task_2) =give_task(geonezis_zat_test_example_task_3) +zat_test_quest_rest_main_come% on_info2 = {+zat_test_quest_rest_main_come} sr_idle@nil [sr_idle@nil]
В активной секции при попадании актора в зону рестриктора происходит выдача внутренних подквестов и переход логики в нулевое состояние.
Определим сам квест с подзаданиями:
Code
[geonezis_zat_test_example_task] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = {+zat_test_quest_rest_main_come} zat_test_example_title1, {-zat_test_quest_rest_main_come} zat_test_example_title0 descr = {+zat_test_quest_rest_main_come} zat_test_example_text1, {-zat_test_quest_rest_main_come} zat_test_example_text0 target ={+zat_test_quest_rest_main_come} nil, {-zat_test_quest_rest_main_come} zat_restr_main_id condlist_0 = {+zat_test_quest_complete} complete on_complete = %=inc_faction_goodwill_to_actor(stalker:50)%
Подквесты:
Code
[geonezis_zat_test_example_task_1] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = zat_test_example_1_title descr = zat_test_example_123_text target = zat_restr_1_id condlist_0 = {+zat_test_quest_restr_1} complete on_complete = %=inc_faction_goodwill_to_actor(stalker:50)%
Code
[geonezis_zat_test_example_task_2] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = zat_test_example_2_title descr = zat_test_example_123_text target = zat_restr_1_id condlist_0 = {+zat_test_quest_restr_2} complete on_complete = %=inc_faction_goodwill_to_actor(stalker:50)%
Code
[geonezis_zat_test_example_task_3] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = zat_test_example_3_title descr = zat_test_example_123_text target = zat_restr_1_id condlist_0 = {+zat_test_quest_restr_3} complete on_complete = %=inc_faction_goodwill_to_actor(stalker:50)%
Особенности: - При старте задания необходимо посетить зону основного рестриктора, устанавливается тагет на zat_restr_main_id. В момент посещения активируются подквесты, выдается инфопоршень zat_test_quest_rest_main_come, задание обновляется, его тагет уходит в nill. после взятия всех квестовых айтемов- необходимо завершение всех трех подквестов для получения инфопоршня zat_test_quest_complete Скриптовая функция которая отвечает за создание трех основных квестовых предметов и выдачу завершающего основное задание инфопоршня прописывается в файл new_tasks.script, и объявляется в апдейте актора файла bind_stalker.script
Code
new_tasks.task_spec()
сама функция
Code
--/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_begin") and not has_alife_info("zat_test_quest_spawn_items") then alife():create("zat_example_taynik_1_item",vector():set(248.498016,14.915686,484.567932),1391296,6) alife():create("zat_example_taynik_2_item",vector():set(247.778076,14.872326,484.085999),1390040,6) alife():create("zat_example_taynik_3_item",vector():set(247.055069,14.796996,483.116058),1388814,6) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо установить все тайники. Подбери рюкзаки оставленные сталкерами", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end if has_alife_info("zat_test_quest_restr_1") and has_alife_info("zat_test_quest_restr_2") and has_alife_info("zat_test_quest_restr_3") and not has_alife_info("zat_test_quest_complete") then db.actor:give_info_portion("zat_test_quest_complete") end end end
Описание: При нахождении ГГ на локации Затон и наличии инфопоршня zat_test_quest_begin создаются квестовые айтемы и отправляется мессадж на пда ГГ. При завершении всех трех подквестов выдается инфопоршень zat_test_quest_complete завершения основного.
Все инфопоршни необходимые нам пропишем в файле info_zaton.xml
Code
..... <info_portion id="zat_test_quest_restr_1"></info_portion> <info_portion id="zat_test_quest_restr_2"></info_portion> <info_portion id="zat_test_quest_restr_3"></info_portion> <info_portion id="zat_test_quest_spawn_items"></info_portion> <info_portion id="zat_test_quest_begin"></info_portion> <info_portion id="zat_test_quest_complete"></info_portion> <info_portion id="zat_test_quest_rest_main_come"></info_portion> .....
Всю текстовую транскрипцию определим в xml-файлах. На этом урок завершен.
Урок 8. Создание квеста с добавлением дополнительных внутриэтапных заданий. Особенности- отсутствие диалогов, использование физических объектов класса physic_destroyable_object в качестве квестовых предметов.
В данном уроке речь пойдет о реализации задания подобного тому что было рассмотрено в предыдущем уроке. В отличие от него теперь добавление внутри этапных заданий будет завязано не на применение рестрикторов, а на использование физических объектов специального класса. Задание этих объектов будет осуществлено как в моде SGM (автор GeJorge) Также особенностью будет добавление класса метки объекта (также по аналогии с SGM) что позволит отказаться от применения рестрикторов в определенных моментах. Выдача задания осуществляется при старте игры. Диалогов нет.
Само задание: ГГ на ПДА приходит сообщение о необходимости обыска трех точек с установленными там объектами. Необходимо выяснить что это за объекты и вернуться в стартовую точку. После этого задание автоматически завершается. Выдача награды не предусмотрена.
Необходимые для редактирования файлы:
1. конфигурационные в (gamedata\configs\gameplay\) -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - quest_items.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml - ui_st_screen.xml 4. конфигурационные в (gamedata\configs\models\) - dynamic_objects.ltx 5. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов и объектов 6. скриптовый в (gamedata\scripts\) - bind_stalker.script - new_tasks.script 7. all.spawn. (gamedata\spawns\) - alife_zaton.ltx 8. физическая модель в (gamedata\meshes\dynamics\box\) - konteyner.ogf
Некоторые этапы добавления изменений будут приведены с сокращением, ввиду их схожести с аналогичными в других уроках. Акцент будет сделан на впервые вносимые изменения и аспекты.
Изначально создадим новые классы квестовых предметов. Класс родительского предмета метка будет соответствовать стандартному квестовому device_pda, но будет иметь визуал нулевого значения. поэтому при написания квестов и установки тагета в них можно будет воспользоваться именно этим приемом, а не добавлением цели на айдишнике отдельного рестриктора. пропишем в quest_items.ltx секцию
Code
[quest_spot]:device_pda $spawn = "devices\quest_spot" visual = dynamics\scene_objects\part\part_none.ogf can_take = false
сами добавленные метки имеют следующие секции. как видим они являются потомками родительского класса quest_spot. также указывается айди метки по которому будет прописываться таргет story_id.
Code
[zat_test_stalker_container_1_spot]:quest_spot story_id = zat_test_stalker_container_1_spot [zat_test_stalker_container_2_spot]:quest_spot story_id = zat_test_stalker_container_2_spot [zat_test_stalker_container_3_spot]:quest_spot story_id = zat_test_stalker_container_3_spot
Новый физический объект используемый нами в квесте объявим в файле dynamic_objects.ltx Он будет иметь свой уникальный класс наследуемый от основного physic_destroyable_object Секции конфигов будут следующими:
Code
[box_quest_item]:physic_destroyable_object $spawn = "dynamic_objects\box\box_quest_item" visual = dynamics\box\konteyner.ogf [zat_test_stalker_container_1]:box_quest_item custom_data = scripts\zaton\inventory_boxs\zat_test_stalker_container_1.ltx [zat_test_stalker_container_2]:box_quest_item custom_data = scripts\zaton\inventory_boxs\zat_test_stalker_container_2.ltx [zat_test_stalker_container_3]:box_quest_item custom_data = scripts\zaton\inventory_boxs\zat_test_stalker_container_3.ltx
В основной секции указывается физическая модель предмета visual. В уникальных секциях указываются секции конфигов custom_data
Логика добавленных предметов будет задаваться в файлах zat_test_stalker_container_....ltx следующим образом:
Code
[logic] active = ph_idle@retranslator_take [ph_idle@retranslator_take] nonscript_usable = false tips = st_take_the_quest_item on_use = ph_idle@retranslator_heavy %+zat_test_quest_item_1_used% on_info = {+zat_test_quest_complete} sr_idle@nil [ph_idle@retranslator_heavy] nonscript_usable = false tips = st_quest_item_is_used on_info = {+zat_test_quest_complete} sr_idle@nil [sr_idle@nil]
- активная секция логики ph_idle@retranslator_take - первоначальная активная надпись считывается из секции st_take_the_quest_item - при юзании предмета произойдет выдача инфопорции zat_test_quest_item_1_used и переход во вторую секцию логикиph_idle@retranslator_heavy - при этом изменяется активная надпись на st_quest_item_is_used - при получении инфопорции zat_test_quest_complete логика обнуляется.
Теперь необходимо создать основной рестриктор на обход которого будет завязана основа квеста. Сам рестриктор создаем в all.spawn по аналоги с предыдущими уроками. Логика рестриктора из файла zat_restr_logic_main.ltx имеет следующий вид:
Code
[logic] active = sr_idle@start [sr_idle@start] on_info = {+zat_test_quest_begin -zat_test_quest_rest_main_come =actor_in_zone(zat_test_quest_restrictor_main)} %=give_task(geonezis_zat_test_example_task_1) =give_task(geonezis_zat_test_example_task_2) =give_task(geonezis_zat_test_example_task_3) +zat_test_quest_rest_main_come% on_info2 = {+zat_test_quest_rest_main_come} sr_idle@wait [sr_idle@wait] on_info = {+zat_test_quest_all_item_used -zat_test_quest_complete =actor_in_zone(zat_test_quest_restrictor_main)} %+zat_test_quest_complete% on_info2 = {+zat_test_quest_complete} sr_idle@nil [sr_idle@nil]
разберем ее: - имеет три секции первая активная, во вторую переходит по совокупности полученных условий при обновлении квеста. - при этом происходит выдача трех подзаданий. - для перехода в нулевую секцию необходимо завершение задания.
Выдача задания будет происходит при старте ГГ одновременно с квестами основного сюжета. Для этого добавим инфопоршень выдачи и сам квест в секцию логики [sr_idle] оригинального рестриктор zat_b101_logic.ltx
Code
=give_task(geonezis_zat_test_example_task) +zat_test_quest_begin
Определим сам квест с подзаданиями: основной квест:
Code
[geonezis_zat_test_example_task] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = {+zat_test_quest_all_item_used} zat_test_example_title2, {+zat_test_quest_rest_main_come -zat_test_quest_all_item_used} zat_test_example_title1, {-zat_test_quest_rest_main_come} zat_test_example_title0 descr = {+zat_test_quest_all_item_used} zat_test_example_text2, {+zat_test_quest_rest_main_come -zat_test_quest_all_item_used} zat_test_example_text1, {-zat_test_quest_rest_main_come} zat_test_example_text0 target = {+zat_test_quest_all_item_used} zat_restr_main_id, {+zat_test_quest_rest_main_come -zat_test_quest_all_item_used} nil, {-zat_test_quest_rest_main_come} zat_restr_main_id condlist_0 = {+zat_test_quest_complete} complete on_complete = %=inc_faction_goodwill_to_actor(stalker:50)%
внутренние подквесты:
Code
[geonezis_zat_test_example_task_1] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = zat_test_example_1_title0 descr = zat_test_example_1_text0 target = zat_test_stalker_container_1_spot condlist_0 = {+zat_test_quest_item_1_used} complete
Code
[geonezis_zat_test_example_task_2] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = zat_test_example_2_title0 descr = zat_test_example_2_text0 target = zat_test_stalker_container_2_spot condlist_0 = {+zat_test_quest_item_2_used} complete
Code
[geonezis_zat_test_example_task_3] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = zat_test_example_3_title0 descr = zat_test_example_3_text0 target = zat_test_stalker_container_3_spot condlist_0 = {+zat_test_quest_item_3_used} complete
Особенности: - При старте задания необходимо посетить зону основного рестриктора, устанавливается тагет на zat_restr_main_id. В момент посещения активируются подквесты, выдается инфопоршень zat_test_quest_rest_main_come, задание обновляется, его тагет уходит в nil. после юзания всех квестовых айтемов созданных в начале объектов проиходит завершение всех трех подквестов, основной квест обновляется снова. чтобы завершить его необходимо снова посетить точку основного рестриктора. Скриптовая функция которая отвечает за создание трех основных квестовых предметов и выдачу завершающего основное задание инфопоршня прописывается в файл new_tasks.script, и объявляется в апдейте актора файла bind_stalker.script
Code
new_tasks.task_spec()
сама функция
Code
--/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_begin") and not has_alife_info("zat_test_quest_spawn_items") then alife():create("zat_test_stalker_container_1_spot",vector():set(210.996811,15.980440,480.381104),1323235,6) alife():create("zat_test_stalker_container_2_spot",vector():set(267.914307,17.374102,483.001709),1424536,6) alife():create("zat_test_stalker_container_3_spot",vector():set(305.260254,18.979174,532.515625),1484018,287) news_manager.send_tip(db.actor, "Для начала займи указанную точку", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end if has_alife_info("zat_test_quest_rest_main_come") and not has_alife_info("zat_test_quest_spawn_items_2") then alife():create("zat_test_stalker_container_1",vector():set(210.996811,15.980440,480.381104),1323235,6) alife():create("zat_test_stalker_container_2",vector():set(267.914307,17.374102,483.001709),1424536,6) alife():create("zat_test_stalker_container_3",vector():set(305.260254,18.979174,532.515625),1484018,287) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо исследовать все контейнеры.", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items_2") end if has_alife_info("zat_test_quest_item_1_used") and has_alife_info("zat_test_quest_item_2_used") and has_alife_info("zat_test_quest_item_3_used") and not has_alife_info("zat_test_quest_all_item_used") then db.actor:give_info_portion("zat_test_quest_all_item_used") end end end
описание: - первоначально по выдаче задания происходит создания меток дополнительных подквестов. - при выдачи самих подквестов происходит создание самих предметов необходимых для их выполнения. - при наличии трех инфопорций полученных от юзания всех предметов выдается общий инфопоршень на обновление основного задания.
Все инфопоршни необходимые нам пропишем в файле info_zaton.xml. Всю текстовую транскрипцию определим в xml-файлах. На этом урок завершен.