Вступ
Перед вивченням цього уроку раджу освоїти урок "Створення діалогів", що знаходиться дещо вище.
Невеликі правила, дотримуючись яких, можна зберегти собі багато нервів:
- завжди зберігайте резервні копії файлів, що модифікуються - намагайтеся частіше тестувати внесені зміни - так простіше зрозуміти, в чому ви помилилися (якщо активно працювати пару годин без зупинки, не разу не протестувавши внесені зміни, то потім буде дуже складно зрозуміти - чому ж, чорт візьми , гра вилітає при спробі поговорити з Сидоровичем?) - перед початком роботи створіть нову папку gamedata, а свої моди сховайте подалі: працювати з "чистою" версією гри не приклад зручніше і простіше; особливо протипоказаний Repair Mod, який із новими діалогами часто конфліктує. Про те, як створити діалоги та квести, що виключають можливість конфлікту з іншими подібними модами, див.
Створення базового діалогу
Почнемо створення квесту з написання невеликого лінійного діалогу.
Відкриваємо файл gamedata\config\gameplay\character_desc_escape.xml і проводимо такі маніпуляції:
- знаходимо рядок <actor_dialog>escape_trader_done_blockpost_box</actor_dialog> - додаємо після неї новий - <actor_dialog>escape_trader_oops</actor_dialog> - зберігаємо зміни
Ми додали до Діалогу з Сидоровичем нову гілку, вірніше лише посилання на неї. Сама внутрішня структура гілки зберігається у файлі gamedata\config\gameplay\dialogs_escape.xml , який ми відкриваємо та виробляємо:
- знаходимо в будь-якому місці файлу проміжок між </dialog> і <dialog id="..."> - засовуємо туди таку конструкцію:
<dialog id="escape_trader_oops"> <precondition>escape_dialog.trader_alredy_give_job</precondition> <has_info>tutorial_end</has_info> <phrase_list> <phrase id="0"> <text>escape_trader_oops_0</text> <next>1</next> </phrase> <phrase id="1"> <text>escape_trader_oops_1</text> <next>2</next> </phrase> <phrase id="2"> <text>escape_trader_oops_2</text> <next>3</next> </phrase> <phrase id="3"> <text>escape_trader_oops_3</text> </phrase> </phrase_list> </dialog>
- Зберігаємо зміни
Тепер у нас прописано структуру нової гілки діалогу. Залишилося зробити ще одну річ - прописати рядки, які відображатимуться замість escape_trader_oops_... .
Для цього відкриємо файл gamedata\config\text\rus\stable_dialogs_escape.xml і зробимо таке:
- знаходимо будь-який зручний проміжок між </string> та <string id="..."> - прописуємо туди наступні рядки:
<string id="escape_trader_oops_0"> <text>Сидрыч, давай поговорим о... водке.</text> </string> <string id="escape_trader_oops_1"> <text> водке? Да какая водка? Нет её у меня, кончилась. Вроде у Волка на чердаке была, что-то он однажды об этом упоминал... Принеси, а?</text> </string> <string id="escape_trader_oops_2"> <text>Да сбегаю я сейчас, сбегаю... алкоголик, блин.</text> </string> <string id="escape_trader_oops_3"> <text>Беги, беги... сил уж нет ждать.</text> </string>
- Зберігаємо зміни
Всі. Діалог готовий. Можна вантажити гру і дивитися, чи працює нова гілка. А тепер будемо прикріплювати до цього неподобства квест "Принеси горілки Сидоровичу".
Створення базового квесту
Активацію квесту у діалог прикріпити досить просто. Проводимо з файлом gamedata\config\gameplay\dialogs_escape.xml наступні маніпуляції:
- додаємо вміст фрази <phrase id="2"> наступним:
<phrase id = "2" > <text > escape_trader_oops_2 </text > <give_info > kvest_vodka_started </give_info > <next > 3 </next > </phrase >
- Зберігаємо зміни
Тепер після фрази Міченого "Нехай я збігаю зараз, збігаю..." Сидорович таки втягує нам квест "Принеси горілку". Але не поспішайте тестувати зміни. Ми додали до діалогу згадку про квест, хоча він ще не створений.
Виправимо це непорозуміння. Відкрийте файл gamedata\config\gameplay\tasks_escape.xml і на початку файлу створіть таку конструкцію:
<game_task id="esc_test_vodka_task"> <title>Принести водки</title> <!-- заголовок квеста --> <objective> <text>Принести водки Сидоровичу</text> <icon>ui_iconsTotal_find_item</icon> <infoportion_complete>test_quest_vodka_otdana</infoportion_complete> </objective> <objective> <text>Вернуться с водкой обратно</text> <map_location_type hint="esc_dinamit_to_volk">green_location</map_location_type> <object_story_id>Escape_novice_lager_volk</object_story_id> <infoportion_complete>test_quest_vodka_otdana</infoportion_complete> </objective> <objective> <text>Найти водку на чердаке</text> <map_location_type hint="escape_trader">blue_location</map_location_type> <object_story_id>Escape_Trader</object_story_id> <infoportion_complete>test_quest_vodka_otdana</infoportion_complete> </objective> </game_task>
Ми прописали дані про квест: назву, іконку, рядки завдань, розташування маркерів тощо.
До цього файлу ми повернемося, т.к. у цьому варіанті багато що проставлялося не інакше як від балди. Я ще подумаю, як змусити завдання "Повернутися з горілкою назад" з'явитися в PDA, бо воно щось не бажає явити себе народу... втім, гаразд, головне, що все працює і не вилітає. А виправлення таких дрібних багів - справа десята. Продовжимо.
Відкриємо файл gamedata\config\gameplay\info_l01escape.xml і зареєструємо типи умов (вони нам ще стануть у нагоді для завершення роботи над квестом):
- після рядка <game_information_portions> прописуємо:
<info_portion id = "test_quest_vodka_otdana" > </info_portion > <info_portion id = "kvest_vodka_started" > <task > esc_test_vodka_task </task > </info_portion > <info_portion id = "otkazalsya_prinesty_vodku" > </info_portion >
З прописуванням умов – все.
Тепер займемося однією невеликою, але потрібною річчю - прописуванням екранних підказок, які висвічуються під час отримання/виконання етапу/завершення завдання.
Для цього відкриємо файл gamedata\config\text\rus\string_table_tasks_escape.xml і пропишемо там:
<string id = "esc_test_prinesti_vodku" > <text > Принести пляшку горілки </text > </string > <string id = "esc_test_prinesti_vodku_1" > <text > Знайти горілку на горищі у Вовка </text > </string > <string id = "esc_test_prinesti_vodku_2" > <text > Принести горілку Сидоровичу </text > </string >
Тепер можна тестувати, що вийшло. Звіряємо результати:
- після закінчення розмови про горілку у вас з'являється нове завдання - у завданні маркером відзначений Вовк (найближчий до горища маркер, тому і відмічений) - при отриманні завдання на екрані висвічується повідомлення
Можна братися до третьої стадії. Що ми забули? Правильно – можливість виконати квест.
Реалізація можливості виконати квест
Насправді – все просто. Усі умови тощо. вже нами створено, залишилося лише застосувати їх у діалозі. Давайте дещо змінимо його структуру, зробимо його гіллястим та функціональним:
0. Сідрич, давай поговоримо про... горілку. (перехід до 1)
1. Про горілку? Та яка горілка? Нема її в мене, скінчилася. Наче у Вовка на горищі була, щось він одного разу про це згадував... Принеси, га? (Вибір - перехід до 2, 4, 5; спочатку доступний тільки 2 варіант)
2. Та збігаю я зараз, збігаю... алкоголік, млинець. ( Отримання квесту, перехід до 3, після цього перестає бути доступний )
3. Біжи, біжи... сил уже немає чекати. (кінець, перехід до списку гілок Сидоровича)
4. Ось вона, твоя пляшка горілки. Ну, точніше, не твоя, а Вовка... (з'являється лише за наявності горілки в інвентарі, під час виборів горілка передається Сидоровичу, квест виконується, йде перехід до 7 )
5. Вибач, Сідрич, я поки що не роздобув, терпи ... (з'являється тільки якщо взяти квест, перехід до 6)
6. Ану марш звідси! Без пляшки прийшов... ууу, вражина... (перехід до 8)
7. Тепер моя буде, Мічений! Ти так вовку і передай. Дякую, виручив... тримай нагороду. (Видача нагороди, перехід до 8)
8. Ну тебе в пень... (кінець, перехід до списку гілок Сидоровича)
А ось так це буде виглядати у файлі gamedata\config\gameplay\dialogs_escape.xml :
<dialog id="escape_trader_oops"> <precondition>escape_dialog.trader_alredy_give_job</precondition> <has_info>tutorial_end</has_info> <phrase_list> <phrase id="0"> <text>escape_trader_oops_0</text> <next>1</next> </phrase> <phrase id="1"> <text>escape_trader_oops_1</text> <next>2</next> <next>4</next> <next>5</next> </phrase> <phrase id="2"> <dont_has_info>kvest_vodka_started</dont_has_info> <text>escape_trader_oops_2</text> <give_info>kvest_vodka_started</give_info> <next>3</next> </phrase> <phrase id="3"> <text>escape_trader_oops_3</text> <action>dialogs.break_dialog</action> </phrase> <phrase id="4"> <text>escape_trader_oops_4</text> <precondition>escape_dialog.have_a_vodka</precondition> <action>escape_dialog.otday_vodku</action> <next>7</next> </phrase> <phrase id="5"> <has_info>kvest_vodka_started</has_info> <text>escape_trader_oops_5</text> <next>6</next> </phrase> <phrase id="6"> <text>escape_trader_oops_6</text> <next>8</next> </phrase> <phrase id="7"> <text>escape_trader_oops_7</text> <give_info>test_quest_vodka_otdana</give_info> <action>escape_dialog.transfer_deneg</action> <next>8</next> </phrase> <phrase id="8"> <text>escape_trader_oops_8</text> </phrase> </phrase_list> </dialog>
Тепер додамо в гру скрипти "передача грошей" та "передача горілки". Відкрийте файл gamedata\scripts\escape_dialog.script і перед роздільником Trader додайте туди наступні рядки:
function transfer_deneg ( first_speaker , second_speaker ) dialogs.relocate_money ( second_speaker, 4000 , "in" ) end function otday_vodku ( npc, actor ) dialogs.relocate_item_section ( npc, "vodka" , "out" ) end function have_a_vodka ( stalker, player ) return stalker:object ( "vodka" ) ~= nil end
Готово. Запускайте гру та милуйтеся.
Для тих, хто ще з нами – зараз ми модифікуємо квест так, щоб унеможливити конфлікти з іншими подібними модами.
Реалізація сумісності
Чому наш мод не може працювати разом із аналогічними йому модами? Так тому, що файли dialogs_escape.xml та деякі інші у них перетинаються. Тому виділимо їх окремо від основних діалогів:
Замість dialogs_escape.xml ми будемо використовувати новий - dialogs_new.xml . Замість stable_dialogs_escape.xml ми будемо використовувати файл stable_dialogs_new.xml (важливо! не знаю чому, але він повинен лежати в text\... , а не text\rus\...) .
Відповідно весь реалізований нами новий контент перекидаємо в порожні файли (дотримуючись форматування), підчистивши за собою на старому місці.
Єдине, що залишиться зробити після встановлення того ж таки Repair Mod'а - заново додати гілку діалогу Сидоровичу у файлі character_desc_escape.xml. Решту у новому варіанті нашого мода переписувати не доведеться – для діалогів відведено три файли.
Інші файли відносяться вже до квестової частини і ні з чим перетинатися не можуть – де ви бачили інші моди з новими квестами? Я – ні.
Відкрийте файл gamedata\config\localization.ltx та зареєструйте там stable_dialogs_escape.ltx . Потім відкрийте файл gamedata\config\system.ltx і в розділі Dialogs в кінці рядка (після dialogs_aes ) пропишіть dialogs_new (без .ltx !).
Всі. Тепер ваші діалоги підвантажуватимуться зі сторонніх файлів.
Окрема подяка:
XiaNi - за страшний та непричесаний, але працюючий приклад квесту, на основі якого я й освоїв принципи квестобудування =)
Keha – за урок створення нових діалогів
Доповнення
1. Якщо змінити шапку нашого діалогу у файлі dialogs_escape.xml зі старого варіанта на такий, то гілка зникне після виконання завдання:
function transfer_deneg(first_speaker, second_speaker) dialogs.relocate_money(second_speaker, 4000, "in") end function otday_vodku (npc, actor) dialogs.relocate_item_section(npc, "vodka", "out") end function have_a_vodka (stalker, player) return stalker:object ("vodka") ~= nil end
...
Чи не тестував. Справа за вами =)
Фух, начебто все... Дякую всім, завіса =)