Этап 5. Управление миром и UI
В этом завершающем Этапе мы рассмотрим способы управления миром и интерфейсом игрока. Научимся спавнить мобов, добавлять картинки, анимировать и многое другое. Этот этап ставит финальную точку в этом Гайде, выдавая на руки все возмозможности квестовой системы
Глава 17. Спавн и проверки
В прошлых Главах мы выдавали игроку задание на убийство и заставляли его бегать по миру, чтобы найти нужных мобов. Это работает и подстегивает исследовать мир, но иногда в некоторых ситацияых это выглядит, как сказать гостю: «Хочень торт? Иди сгоняй на кухню, найди его там в холодильнике и притащи мне».
В этой Главе мы научимся призывать мобов прямо во время диалога, проверять их наличие, очищать мир от всех них и запрещать их естественный спавн
Шаг 1. <spawn/> – Призыв мобов
Тег спавнит нужного моба прямо во время квеста. Буквально, как по щелчку пальцев<spawn/>
Полный синтаксис тега:
<spawn mob="ИмяМоба" distance="5" angry="false"/>
Где:
mob– Системное имя призываемого моба (см. таблицу GigaList)distance– На каком расстоянии (в блоках) заспавнить мобаangry– Делать ли нейтрального моба агрессивным (true/false). Для враждебных и мирных мобов этот атрибут не указывать
!!! Важные нюансы:
- В одном шаге нельзя спавнить больше трёх мобов одного типа за раз. Условно, если напишите 10, то гарантированно заспавнится только 3 моба, а остальные как повезет.
- Боссы и мини-боссы – только по одному. Точно заспавнится только один, если попробуете больше – они просто не появятся
Шаг 2. Практика спавнов
В Главе 16 Аарон просил нас убить Арагога, и мы бегали его искали. Теперь сделаем покруче. Допустим, пока Аарон перед нами распинался, Арагог сам пришел и застал всех в расплох. Получается наша Цель сама к нам пожаловала.
Открываем квест Аарона (WarriorFirstQuest.xml – «Маленькая Проблемка») и находим там наш шаблонный шаг small_problem_step. Теперь нам нужно добавить туда спавн Арагога, но шаблонный шаг такого не позволит. Значит, заменяем его на 4 обычных (step), где в первом нам будут рассказывать историю из intro, во втором он будет орать от испуга, в третьем будет спавн Арагога и сама битва, а в четвертом нам выдадут награду и распрощаются.
Можно было и в 2-3 шага уложиться, но для эффектности сделаем 4, заодно потренируемся и повторим несколько тем из прошлых Глав.
Было:
<killstep id="small_problem_step"><intro>Видишь ли, у меня тут появилась небольшая проблемка. Говорят, что на дне земных провалов на тамошних деревьях растут самые вкусные яблочки. Я бы и рад туда спуститься, но там сидит огромный паук – Арагог. \nЯ, понимаешь ли, даже мелких паучков страшусь, а тут аж огромный Паучище\nВ общем, не мог бы ты мне немножко подсобить с этой маленькой проблемкой? Я готов немного приплатить за это.</intro><desc>Так ты поможешь или нет?</desc><finish>Спасибо. Наконец я смогу без опаски спуститься в те провалы и насладиться тамошними яблочками</finish><kill enemy="GiantSpider" count="1"/><rewards><reward exp="500"/><reward item="Gold Coin" count="30"/></rewards><option to="after_aragog_step" text="Ок"/></killstep>
Стало:
<step id="small_problem_step"><desc>Видишь ли, . . .маленькой проблемкой? Я готов немно...</desc><rewards type="Display"><reward exp="500"/><reward item="Gold Coin" count="30"/></rewards><option to="before_aragog_step" text="Да"/></step><step id="before_aragog_step"><desc></desc><label>[FF0000]А-А-А-А! ОН УЖЕ ЗДЕСЬ![-]\n\nКто не спрятался — я не виноват!</label><option to="battle_aragog_step" text="!!!"/></step><step id="battle_aragog_step"><info>
<label>Убей [FF0000]Арагога[-]</label>
<kill enemy="GiantSpider" count="1"/>
</info>
<option auto="#close"><spawn mob="GiantSpider" distance="3"/></option><option auto="after_battle_aragog_step"><kill enemy="GiantSpider" count="1"/></option></step><step id="after_battle_aragog_step"><desc>Да ты мне жизнь спас! Так ещё я смогу насладиться тамошними яблочками в провалах!\nДержи, ты заслужил</desc><option to="after_aragog_step" text="Ок"/><rewards type="Award"><reward exp="500"/><reward item="Gold Coin" count="30"/></rewards>
<info>
<label>Скажи Аарону, что ты убил Арагога</label>
</info></step>
Обратите внимание на авто-опцию с #close!
В шаге battle_aragog_step банально нет ни одного текстового блока, а это значит, что при переходе на него у игрока будет «пустой экран», точнее сломанный диалог. Чтобы не допустить этого, мы добавляем в самый верх авто-опцию с #close, которая автоматически при переходе на этот шаг закроет сломанное диалоговое окно. В нашем случае, эта авто-опция еще и Арагога спавнит.
Вообще можете использовать эту авто-опцию без вложенных тегов:
<option auto="#close"/>
Обязательно ставьте её в САМЫЙ верх вашего невидимого шага. Игра проходиться по коду сверху вниз, а значит закроет диалоговое окно она в первую очередь. Тем самым игрок даже ничего не заметит.
Шаг 3. <existmobs/> – жив ли моб
Иногда нужно проверить: есть в мире моб или нет. На такой случай как раз есть тег <existmobs/>, который кладется внутрь опций
<existmobs name="ИмяМоба"/>
Условие сработает, если моб жив. Если умер/задеспавнился, то условие не сработает.
Если нам нужно проверить, что моб отсутствует. Умер/задеспавнился, то для этого внутрь <existmobs/> вкладываем тег <inverse>, который инвертирует условие
<existmobs name="ИмяМоба"><inverse/></existmobs>
Использование:
Сработает, если в видимых (прогруженных) чанках есть живая Паула
<option auto="paula_alive_step"><existmobs name="FemaleWarrior"/></option>
Сработает, когда Паулы нет в видимых чанках (задеспавнилась/умерла)
<option auto="paula_dead_step"><existmobs name="FemaleWarrior"><inverse/></existmobs></option>
Наш квест
В нашем квесте мы будем использовать второй вариант с <inverse/>. С помощью него мы будем проверять: аздеспавнился Арагог или нет. Если он задеспавнился, то есть не был убит игроком, то тогда спавним его по-новой.
Для этого внутрь шага battle_aragog_step добавим ещё одну авто-опцию
ОЧЕНЬ ВАЖНО! Добавляем эту авто-опцию СТРОГО под опцией, проверяющей убийство Арагога (где kill). Игра проверяет код сверху вниз. Сначала она проверит, что Арагог не убит игроком (kill) и только потом узнает: есть он в мире вообще или нет (existmobs).
Если перепутать порядок, то, сразу после убийства Арагога, игра заспавнит нового, но при этом авто-опция с kill перейдет на шаг с победой. Получится странная ситуация, когда Босс опять есть, но задание считается выполненым
Код:
<step id="battle_aragog_step"><info><label>Убей [FF0000]Арагога[-]</label><kill enemy="GiantSpider" count="1"/></info><option auto="#close"><spawn mob="GiantSpider" distance="3"/></option><option auto="after_battle_aragog_step"><kill enemy="GiantSpider" count="1"/></option><option auto="battle_aragog_step"><existmobs name="GiantSpider"><inverse/></existmobs></option></step>
Наша новая опция проверяет: задеспавнился Арагог или нет. Если он задеспавнился, то она перезапускает свой же шаг battle_aragog_step
Еще раз, опция с existmobs должна быть ПОД опцией с kill
Как видите, даже если игрок умирает, то Арагог все равно респавнится радом с ним. Даже смерть не спасет
Шаг 4. <clearmobs/> – удалить всех мобов
Перед битвой, например, с Боссом из квеста в мире гарантировано будут бродить другие сущетсва. В игре мобов в прогруженных чанках может быть ограниченное количество. Если этот лимит заполнен, то новые существа (даже те, которые спавняться через <spawn/> в квесте) появляться не будут и это проблема
Для очистки используется тег <clearmobs/>. Он удалет вообще ВСЕХ мобов из мира. Даже NPC, с которым сейчас говорит игрок. Поэтому используйте этот тег осторожно и строго по необходимости.
Добавим в квест Аарона
Добавлять мы будем во всё тот же шаг battle_aragog_step в авто-опцию, которая спавнит Арагога:
<step id="battle_aragog_step"><option auto="#close"><clearmobs/><spawn mob="GiantSpider" distance="3"/></option>. . .</step>
Тут тоже важен порядок! Помним, что игра читает код сверху вниз. Наша опция должна сначала очистить мир от мобов и только потом заспавнить Арагога. Если вы спутаете порядок, то опция заспавнит Арагога и тут же удалит его, вместе с остальными мобами
По желанию, также можно добавить спавн Аарона сразу после убийства Арагога, чтобы игроку не пришлось бегать по миру и искать его:
<step id="battle_aragog_step">. . .<option auto="after_battle_aragog_step"><kill enemy="GiantSpider" count="1"/>
<spawn mob="Warrior" distance="5"/></option>. . .</step>
Шаг 5. <spawnmobs/> – Естественный спавн
Во ремя важных сюжетных битв (с Боссами, например) нужно чтобы не мешали всякие сторонние мобы. Сражаетесь вы с условным Арагогом, почти уже добили его, как вдруг спавниться Волшебник и выносит его. Либо вообще во время битвы на игрока нападают враждебные мобы, а самого Босса дамажат снова появившиеся нейтральные NPC. <clearmobs/> лишь единожды очищает мобов, повторно его применить не получиться, иначе исчезнет ещё сам Босс.
Благо для этого есть тег <spawnmobs/>, который регулирует естественный спавн мобов в мире. Он никак не влияет на спавн через тег <spawn/> в квестах или через спавнеры.
Всего у него есть 2 состояния:
<spawnmobs value="false"/>– Отключает естественный спавн мобов<spawnmobs value="true"/>– Включает его
Важно! Не забывайте включать спавн обратно (value="true") в конце квеста/шага-победы. Иначе мир останется «мертвым» и мобы просто не будут самостоятельно появляться в мире.
Используем в квесте Аарона:
Добавим в шаг battle_aragog_step, в опцию, ведущую на #close, то бишь закрывающее сломанное диалоговое окно. Помним, что в этом шаге нет <desc>, поэтому диалоговое окно тут битое.
<step id="battle_aragog_step"><option auto="#close"><clearmobs/><spawnmobs value="false"/><spawn mob="GiantSpider" distance="3"/></option>. . .</step>
Не забываем обратно включать естественный спавн в шаге-победе (after_battle_aragog_step). Засунем это в кнопку:
<step id="after_battle_aragog_step"><desc>Да ты мне жизнь спас! . . .\nДержи, ты заслужил</desc><option to="after_aragog_step" text="Ок"><spawnmobs value="true"/></option>. . .</step>
Задания на закрепление
- Сделайте квест от Крестьянина, в котором он спавнит трех оборотней
- Сделайте квест от Волшебника, в котором он спавнит 3 волны монстров. На третьей Волне добавьте какого-нибудь Босса, например, Ашкор. Квест визуально оформите на свое усмотрение (уведомления, надписи, разноцевтный текст и так далее)
Заключение
В этой главе вы научились полноценно работать со спавном и очисткой мобов. Теперь вы можете делать более-менее динамические квесты, а не только принеси-подай.
В следующих главах перейдем к картинкам, спецэфектам и анимациям.
Итоговый код Главы
WarriorFirstQuest.xml – «Маленькая Проблемка»
<?xml version="1.0" encoding="UTF-8"?><quest npc="Warrior" title="Маленькая Проблемка"><complete quest="Основной Квест" step="go_to_warrior_step" /><step id="#start"><desc>Привет, Наездник Дракона. Полагаю, тебя послал Волшебник. \nЧтож у меня есть для тебя небольшое заданьеце</desc><option to="small_problem_step" text="?"><journal /></option></step><step id="small_problem_step"><desc>Видишь ли, у меня тут появилась небольшая проблемка. Говорят, что на дне земных провалов на тамошних деревьях растут самые вкусные яблочки. Я бы и рад туда спуститься, но там сидит огромный паук – Арагог. \nЯ, понимаешь ли, даже мелких паучков страшусь, а тут аж огромный Паучище\nВ общем, не мог бы ты мне немножко подсобить с этой маленькой проблемкой? Я готов немно...</desc><rewards type="Display"><reward exp="500"/><reward item="Gold Coin" count="30"/></rewards><option to="before_aragog_step" text="Да"/></step><step id="before_aragog_step"><desc></desc><label>[FF0000]А-А-А-А! ОН УЖЕ ЗДЕСЬ![-]\n\nКто не спрятался — я не виноват!</label><option to="battle_aragog_step" text="!!!"/></step><step id="battle_aragog_step"><info>
<label>Убей [FF0000]Арагога[-]</label>
<kill enemy="GiantSpider" count="1"/>
</info>
<option auto="#close"><clearmobs/><spawnmobs value="false"/><spawn mob="GiantSpider" distance="3"/></option><option auto="after_battle_aragog_step"><kill enemy="GiantSpider" count="1"/><spawn mob="Warrior" distance="5" /></option><option auto="battle_aragog_step"><existmobs name="GiantSpider"><inverse/></existmobs></option></step><step id="after_battle_aragog_step"><desc>Да ты мне жизнь спас! Так ещё я смогу насладиться тамошними яблочками в провалах!\nДержи, ты заслужил</desc><option to="after_aragog_step" text="Ок"/><rewards type="Award"><reward exp="500"/><reward item="Gold Coin" count="30"/></rewards></step><step id="after_aragog_step"><desc>Пока, и ещё раз спасибо за помощь</desc><option to="#close" text="Ок"><spawnmobs value="true"/></option><info><label>Иди к Волшебнику и проверь, есть ли у него задания</label></info><option auto="before_find_bed_step"><complete quest="Основной Квест" step="after_pig_go_warrior"/></option></step><step id="before_find_bed_step"><desc>Слу-у-ушай...</desc><option to="find_bed_step" text="Ок"/></step><removestep id="find_bed_step"><intro>Можешь найти мне кровать? Да, обычную кровать. Моя что-то в совсем уж печально состоянии</intro><desc>Так ты найдешь кровать?</desc><finish>Спасибо, Наездник Дракона. Эта кровать мне очень пригодиться</finish><remove item="Bed" count="1"/><rewards><reward exp="777"/></rewards><option to="#end" text="Ок"/></removestep><step id="#end"><desc>Ну а теперь пока, Наездник Дракона. Был рад повидаться.\nИди к Волшебнику, может, у него есть какое-то задание для тебя</desc><option to="#close" text="Пока"/></step></quest>
Отличный гайд, но осталось несколько вопросов:
1) Куда делся раздел с кастомным магазином из прошлой версии руководства. В 13.5.0? Его больше нельзя кастомизировать?
2) У Фуза в 13.5.0 есть свой магазин, следовательно, они тоже стали квестовыми НПС и для них можно делать кастомные квесты. Или нельзя?
1) Кастомные магазины полностью убраны (даже для Алхимика, Фуза и Крестьян). Теперь игра не будет подгружать квесты, содержащие в коде тег <store>
В логах будет писать:
Skipped custom quest ‘ИмяКвеста’ from file [Путь до XML-файла квеста]: NPC stores are not allowed in custom quests
UnityEngine.DebugLogHandler:Internal_Log(LogType, LogOption, String, Object)
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:LogWarning(Object)
QuestManager:AddUserQuests(XmlSerializer, String)
d__77:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
2) Да, для Фуза можно теперь тоже делать квесты. Список Квестовых NPC только что обновил, просто изначально забыл добавить
Из нюансов: У них пока что нет своего портрета, поэтому будет видно просто имя