Перейти к содержанию
Авторизация  
Hardtmuth

[CoP] Квесты | Убийство мутанта "Press F To Win"

Рекомендуемые сообщения

 

701a2f45b7b652b72.jpg

Квест на убийство мутанта через туториал ("Press F To Win")

Платформа: Сталкер Зов Припяти 1.6.02
Автор: FantomICW, использованы наработки для Смерти Вопреки
Уровень сложности: средний (не для самых зелёных новичков)

Введение
Приветствую! К своему Дню рождения (26.07) я хотел бы преподнести Сталкер-сообществу еще один небольшой подарок. В этот раз мое внимание привлекла тема, затронутая в "Вопроснице"...

Относительно недавно пользователь ap-pro Telnov1996 задал один вопрос:

Цитата

Можно ли организовать скриптовые сцены борьбы с мутантами, работающие по принципу 'Press "F" to win'?


К обсуждению подключились уважаемый Dorian23Grey и, собственно, я сам. Ситуация выходит следующая:
1. Во-первых, на X-Ray сцены с анимациями в стиле CoD, Metro и т. д. делать не очень удобно, как таковые.
2. Требуется иметь отличные умения в анимации объектов.
3. Нужно настроить взаимодействие логики с таймерами и анимации.
На данный момент такое мало кто реализовывал. Однако, вариант, когда ГГ подходит к мутанту, запускается туториал с последующим выполнением убийства, - вполне реализуемая фишка. Сегодня об этом и пойдет речь.
Пускай, на Затоне в пределах Северного озера поселился уникальный болотный псевдогигант, которому совершенно плевать на пули сталкеров. Единственный быстрый способ его устранить - активировать гравитационный артефакт. Когда ГГ подойдет к мутанту с артефактом, запустится туториал с надписью "Активировать артефакт". При нажатии F, запустится функция, которая создаст на месте мутанта партикл разрыва от грави-аномалии.

Подготовка к действу:

Инструментарий

Спойлер

Paint NetAdobe Photoshop или другой редактор текстур (если кто-то будет создавать мутанту уникальную текстуру)
Notepad++

Текстура

Спойлер

Опять же, если желаете сделать для своего мутанта уникальную текстуру, пожалйста. Как по мне, то новую модель или текстуру стоит сделать, ибо супер-крутой псевдогиг должен как-то выделяться среди своих сородичей. Я сделал условный "ретекстур" (в кавычках, потому что ляпнуть чуток крови и "узеленить" текстуру - ретекстуром назвать нельзя) монстра под болото:

b029acee23.png

Если кому нужна текстура, ловите (бамп подключен стандартный).

Партиклы

Спойлер

Для хорошего эффекта разрыва тела в аномалии, я буду использовать некоторые партиклы от АМК:


amk\\blow_body
amk\\zomb_explode

У кого они есть (или есть альтернативный вариант) - супер, отлично. У кого их нету - не волнуйтесь, чуть позже я загружу готовый particles.xr, а пока приложу два варианта таблицы партиклов для обоих случаев.

Координаты

Спойлер

Если вы работаете не в СДК, а с ACDC, то вам нужно будет снять координаты для места, где будет сидеть мутант. Само место действия (примерно) показываю на карте:

dda2729ecf.jpg

Я прошел немного вперед к воде, снял координаты:

d7f5e24623.jpg


-19.00901222229,-7.0012526512146,526.37811279297,907875,47

 

 


Практика:

Часть I - Конфиги диалогов:

Спойлер

1. В configs/gameplay/dialogs_zaton.xml добавим два новых диалога:


<dialog id="zat_super_psevdogig_take_task_dialog"> <!--Взятие квеста-->
                <dont_has_info>psevdogig_task_dialog_done</dont_has_info>
                <phrase_list>
                    <phrase id="0">
                        <text>zat_super_psevdogig_take_task_dialog_0</text>
                        <next>1</next>
                    </phrase>
                    <phrase id="1">
                        <text>zat_super_psevdogig_take_task_dialog_1</text>
            <next>2</next>
                    </phrase>
           <phrase id="2">
                        <text>zat_super_psevdogig_take_task_dialog_2</text>
            <next>3</next>
                    </phrase>
           <phrase id="3">
                        <text>zat_super_psevdogig_take_task_dialog_3</text>
            <next>4</next>
                    </phrase>
           <phrase id="4">
                        <text>zat_super_psevdogig_take_task_dialog_4</text>
            <next>5</next>
                    </phrase>
           <phrase id="5">
                        <text>zat_super_psevdogig_take_task_dialog_5</text>
            <give_info>psevdogig_task_dialog_done</give_info>
            <action>dialogs_zaton.give_super_psevdogig_task</action> <!--Выдаем задание и артефакт-->
                    </phrase>
                </phrase_list>
            </dialog>
         <dialog id="zat_super_psevdogig_task_end_dialog">
             <has_info>zat_super_psevdogig_af_activation</has_info>
                <dont_has_info>psevdogig_task_finished</dont_has_info>
                <phrase_list>
                    <phrase id="0">
                        <text>zat_super_psevdogig_task_end_dialog_0</text>
                        <next>1</next>
                    </phrase>
           <phrase id="1">
                        <text>zat_super_psevdogig_task_end_dialog_1</text>
            <give_info>psevdogig_task_finished</give_info>
            <action>dialogs_zaton.give_super_psevdogig_task_reward</action> <!--Выдаем награду-->
                    </phrase>
                </phrase_list>
            </dialog>

2. Пропишем их Бороде (секция zat_a2_stalker_barmen, файл character_desc_zaton.xml)


<actor_dialog>zat_super_psevdogig_take_task_dialog</actor_dialog>
          <actor_dialog>zat_super_psevdogig_task_end_dialog</actor_dialog>

3. В configs/text/rus/st_dialogs_zaton.xml поместим текстовку диалогов:


<string id="zat_super_psevdogig_take_task_dialog_0">
          <text>Как дела, Борода? Есть новости какие-то?</text>
         </string>
         <string id="zat_super_psevdogig_take_task_dialog_1">
          <text>Здравствуй. Новость-не новость, а у нас на Северном озере поселился какой-то убер-псевдогигант, который не дает сталкерам (да и псевдоплотям, что уж тут говорить) покоя...Тварь неубиваемая какая-то. Посоветовавшись с Гонтой, решили попробовать его (я про псевдогиганта) активацией артефакта ликвидировать. Подходящий артефакт у меня вот есть, а смельчака для этого задания найти не можем...</text>
         </string>
         <string id="zat_super_psevdogig_take_task_dialog_2">
          <text>Знаешь, я мог бы вам помочь.</text>
         </string>
         <string id="zat_super_psevdogig_take_task_dialog_3">
          <text>Ты с Цементного завода рухнул? Да эта хрень тебя может в псевдочебурек превратить...А кто мне будет все те же арты таскать? На ком Лоцман зарабатывать будет? Короче, ты уверен?</text>
         </string>
         <string id="zat_super_psevdogig_take_task_dialog_4">
          <text>Уверен. Мне скучно, прост)00)).</text>
         </string>
         <string id="zat_super_psevdogig_take_task_dialog_5">
          <text>Ну, окей, удачи. Вот тебе "Грави" для активации. Будь аккуратен.</text>
         </string>
         <string id="zat_super_psevdogig_task_end_dialog_0">
          <text>Все, старик. Нету больше твоего убер-псевдогигабайта.</text>
         </string>
         <string id="zat_super_psevdogig_task_end_dialog_1">
          <text>Вах, слушай, молодец какой! Молоток! Возьми себе печеньку.</text>
         </string>

С диалогами все. Здесь все просто, поэтому детально рассказывать о них не буду. Если же эта часть показалась Вам сложной, то, простите, этот урок не совсем для Вашего уровня знаний.

Часть II - Конфиг квеста:

Спойлер

1. В configs/misc/tm_zaton.ltx добавим секция квеста:


[zat_super_psevdogig_task]
icon = ui_inGame2_Logovo_krovososov
prior = 10
storyline = false
title = {+zat_super_psevdogig_af_activation} zat_super_psevdogig_task_2, zat_super_psevdogig_task_1
descr = {+zat_super_psevdogig_af_activation} zat_super_psevdogig_task_2_text, at_super_psevdogig_task_1_text
target = {+zat_super_psevdogig_af_activation} zat_a2_stalker_barmen, zat_super_psevdogig_squad
condlist_0 = {+psevdogig_task_finished} complete

Немного разбора:
- иконка стоит от миссии на устранение логова кровососов
- задание имеет две стадии: часть на устранение мутанта и часть, которая требует поговорить с Бородой (на эту часть обновление происходит при получении инфопорции zat_super_psevdogig_af_activation, мы к ней вернемся позже)
- в первой части метка задания падает на сквад мутанта (его story_id - zat_super_psevdogig_squad), во второй - на Бороду
- квест заканчивается при получении инфы psevdogig_task_finished, которая выдается в уже созданном нами диалоге
Как видите, квест по структуре очень простой.
2. Прописываем в configs/text/rus/st_quests_zaton.xml его текстовую часть:


 <string id="zat_super_psevdogig_task_1">
        <text>Помощь криворуким: устранить убер-псевдогиганта</text>
       </string>
       <string id="zat_super_psevdogig_task_1_text">
        <text>Я оказался прав: все сталкеры на Затоне - криворукие болваны. Теперь мне нужно за них устранить очень крутого мутанта на Северном озере.</text>
       </string>
       <string id="zat_super_psevdogig_task_2">
        <text>Помощь криворуким: сломать Бороде нос</text>
       </string>
       <string id="zat_super_psevdogig_task_2_text">
        <text>Хочу сказать пару ласковых слов Бороде. Какого фига это барыго в экзе не сказало мне, что меня на озере ждет не убер-псевдогигант, а жирная зеленая Гидра Затонская?</text>
       </string>

Переходим к конфигам мутанта.

Часть III - Конфиги мутанта:

Спойлер

1. Файл configs/creatures/m_giant.ltx. Сделаем секцию нашего уникального псевдогиганта. Она будет почти аналогичная обычному гиганту:


[super_psevdogig]:m_gigant_e
$spawn    = "monsters\gigants\super_psevdogig"
visual    = monsters\psevdogigant\psevdogigant_uber   ;Это моя новая модель
corpse_visual      = monsters\psevdogigant\psevdogigant_uber_dead   ;Это тоже
rank    = 50  ;Увеличим ранг
spec_rank   = strong   ;Псевдик Стронг!
radiation_pp_effector_name    =  postprocess_acidic   ;Выставим кислотный постпроцесс
attack_params   = super_psevdogig_attack_params  ;Новая секция параметрво атаки

[super_psevdogig_attack_params]  ;Тут усилен импульс
;--------------------------------------------------------------------------------------------------------------------------------------------    -
;    anim   | time[0..1] | hit_power | impulse | impulse_dir (x,y,z)   |    Field of hit_test  (left,right, top, bottom) |    Test Dist
;--------------------------------------------------------------------------------------------------------------------------------------------    -
;Bite
stand_attack_0 =    0.25,  0.9,     200,        0.5, 1.0, 0.5,   -0.8, 0.8, -1.8, 1.8,       2.6
;Left leg Strike
stand_attack_1 =    0.40,  0.9,     150,        5.0, 2.5, 4.0,   -0.6, 0.6, -1.8, 1.8,       3.2
;Bite2
stand_attack_2 =    0.25,  0.9,     200,        0.5, 1.0, 5.0,   -0.8, 0.8, -1.8, 1.8,       2.6
stand_attack_run_0=     0.5,  0.9,     600,        0.5, 1.0, 5.0,   -0.6, 1.3, -1.8, 1.8,       3.3
jump_attack_1    =  0.1,  2.00,  1600,       0.5, 1.0, 5.0,   -1.0, 1.3, -1.6, 1.6,       5.5

2. Дальше требуется создать мутанту сквад в configs/misc/squad_descr_zaton.xml:


[zat_super_psevdogig_squad]:online_offline_group
faction = monster_special     
npc = super_psevdogig  ;НПС в скваде - наш псевдогигант
target_smart = zat_sim_2  ;Целевой смарт - полуостров на Северном озере
spawn_point = zat_sim_2_giant_home  ;Спавн поинт - поинт "логова" для мутанта
story_id = zat_super_psevdogig_squad  ;Sid совпадает с названием секции (ваш Кэп)

 

Часть IV - Логика мутанта:

Спойлер

1. Прежде всего, открываем файл логики смарта полуострова - configs/scripts/zaton/smart/zat_sim_2.ltx, и внизу добавляем секцию exclusive с ссылкой на эксклюзивную логику гиганта:


[exclusive]
giant = zaton\zat_sim_2_super_psevdogig.ltx

Итак, логика нашего мутанта называется giant.
2. Переходим к самой логике. Создаем файл zaton\zat_sim_2_super_psevdogig.ltx. Заполняем его:


[logic@giant] ;Название логики - giant (смотрите выше)
suitable = {=target_squad_name(zat_super_psevdogig_squad)} true ;Логика доступна только для монстра из нашего сквада
monster_job = true
prior = 200
active = mob_home@giant

[mob_home@giant]
on_info = %=restore_health% ;Здоровье мутанта постоянно пополняется
;Если дистаниция до ГГ меньше 7 метров, в наличии есть квестовый артефакт, а активного туториала нету, то запускается туториал убийства:
on_info2 = {=dist_to_actor_le(7) =actor_has_item(super_psevdogig_af_gravi) !has_active_tutorial} %=run_tutorial(zat_super_psevdogig_af_tutor)%    
;Если дистаниция до ГГ больше 7 метров, в наличии есть квестовый артефакт, а туториал запущен, то запускается туториал убийства:
on_info3 = {=dist_to_actor_ge(7) =actor_has_item(super_psevdogig_af_gravi) =has_active_tutorial} %=stop_tutorial%    
;При получении инфы "zat_super_psevdogig_af_activation", убиваем НПС функцией "kill_npc" из xr_effects.script:
on_info4 = {+zat_super_psevdogig_af_activation} %=kill_npc%
;При получении инфы "zat_super_psevdogig_af_activation_begin", удаляем НПС вообще и запускаем партиклы аномалии/разрыва новой функцией    
on_info5 = {+zat_super_psevdogig_af_activation_begin} %=zat_super_psevdogig_explode_2%
path_home = giant_home ;В way_zaton.ltx это - zat_sim_2_giant_home ("логово")
;Настройки охраны "логова":
home_min_radius = 20
home_max_radius = 50
aggressive = true

3. Настало время использовать ранее снятые координаты. Распаковываем all.spawn с ACDC или же используем СДК Левел Эдитор, чтоб создать точку для монстра в way_zaton.ltx:


[zat_sim_2_giant_home]
points = p0
p0:name = wp00
p0:flags = 0x1
p0:position = -19.00901222229,-7.0012526512146,526.37811279297
p0:game_vertex_id = 47
p0:level_vertex_id = 907875

Собираем спавн.

Часть V - Конфиг квестового артефакта и туториала:

Спойлер

1. В логике мы уже упомянули предмет super_psevdogig_af_gravi. Это секция квестового артефакта, который мы якобы будем активировать. Открываем configs/misc/quest_items.ltx, и добавляем туда его:


[super_psevdogig_af_gravi]:device_pda
visual    = dynamics\artefacts\af_gravi.ogf
description   = st_af_gravi_descr
inv_name   = st_af_gravi_name
inv_name_short  = st_af_gravi_name
inv_weight   = 0.5
inv_grid_x   = 15
inv_grid_y   = 0
cost    = 12000
can_trade   = false ;Нельзя продать
quest_item          = true ;Нельзя выбросить
story_id            = super_psevdogig_af_gravi

Стандартная секция квестового предмета с "родителем" device_pda.
2. Также в логике мы объявили запуск туториала:


%=run_tutorial(zat_super_psevdogig_af_tutor)%

Все туториалы игры прописываются в configs/ui/game_tutorials.xml. Вам, вполне возможно, секция ниже может показаться какой-то странной штукой. На самом деле, там все просто, но, считаю, это лучше разбирать в отдельных уроках по худу и гуи, поэтому сейчас можете не забивать голову. Самые важные параметры я укажу:


<zat_super_psevdogig_af_tutor> <!--Название-->
          <global_wnd/>      
             <item>      
                 <disabled_key>quit</disabled_key>      
                 <length_sec/>      
             
        <!--При нажатии F, запускается функция xr_effects.zat_super_psevdogig_explode_1-->
                 <action id="use" finalize="1">xr_effects.zat_super_psevdogig_explode_1</action>      
                 <guard_key>use</guard_key>
        <!----Ниже уже другие параметры-->
                 <grab_input>0</grab_input>      
                     <main_wnd>
                     <!--Всякие параметры текста. Я задал 32 шрифт и красный цвет по RGB. Секция текста - st_tutor_af_activation-->         
                     <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="graffiti32" r="225" g="36" b="36" a="255" align="c">st_tutor_af_activation</text>      
                     </auto_static>      
                     </main_wnd>      
             </item>      
         </zat_super_psevdogig_af_tutor> <!--Тут секция туториала заканчивается-->

3. Дальше добавим секцию текста st_tutor_af_activation, к примеру, в ui_st_screen.xml:


<string id="st_tutor_af_activation">        
       <text>Активировать артефакт ($$ACTION_USE$$)</text>
      </string>

$$ACTION_USE$$ означает клавишу "Использовать". Это F по умолчанию

Часть VI - Скрипты всего и вся:

Спойлер

1. Начнем с диалогов. В каждом из двух мы запускаем по одной функции. Обе функции в dialogs_zaton.script. Первая:


function give_super_psevdogig_task(first_speaker, second_speaker)
        dialogs.relocate_item_section_to_actor(first_speaker, second_speaker, "super_psevdogig_af_gravi") --Выдаем "Грави"
        task_manager.get_task_manager():give_task("zat_super_psevdogig_task") --Выдаем задание
     xr_effects.create_squad(nil, nil, {"zat_super_psevdogig_squad", "zat_sim_2"}) --Спавним сквад монстра на смарте "zat_sim_2"
end

Во второй будем выдавать награду:


function give_super_psevdogig_task_reward(first_speaker, second_speaker)
     local items_pack = {
         {item = "energy_drink", amount = 2},
         {item = "medkit_army",  amount = 3},
         {item = "antirad",      amount = 2},
         {item = "vodka",        amount = 1},
         {item = "conserva",     amount = 3},
     }
         
     for k,v in pairs(items_pack) do
         dialogs.relocate_item_section_to_actor(first_speaker, second_speaker, v.item, v.amount)
     end
         
        dialogs.relocate_money_to_actor(first_speaker, second_speaker, 3000)
end

Используем условно сложную таблицу items_pack. Каждый ее элемент состоит из двух пунктов:
item - секция предмета
amount - количество, которое нужно выдать
Далее некий цикл в виде стандартного
for k,v in pairs(название_таблицы) do
Это означает, что функция ниже может выполниться для каждого элемента таблицы (v). У нас это:


dialogs.relocate_item_section_to_actor(first_speaker, second_speaker, v.item, v.amount)

Обратите внимание на v.item и v.amount.
Ну, а в выдаче денег не вижу ничего сложного.
2. Последнее, что нам нужно сделать, - это две функции: одна выдается при использовании туториала, а вторая - из логики. В xr_effects.script добавляем первую функцию:


function zat_super_psevdogig_explode_1(actor, npc)
     db.actor:give_info_portion("zat_super_psevdogig_af_activation_begin")  --Выдаем инфу
     remove_item(actor, npc, {"super_psevdogig_af_gravi"})  --Забираем у ГГ артефакт (он же активируется)
end

Опять же, ничего сложного. Два простых действия. Единственное, замечу, что remove_item - это тоже функция из xr_effects.script. Теперь добавляем вторую:


function zat_super_psevdogig_explode_2(actor, npc)
        local fx_table_1 = {
         [1] = {particle = particles_object("anomaly2\\gravity_blast_final00")},
      [2] = {particle = particles_object("anomaly2\\gravity_blast_03")},
      [3] = {particle = particles_object("anomaly2\\gravity_blast_05")},
     }     
             
        local npc_position = npc:position()
         
     for i = 1,3 do
            fx_table_1[i].particle:play_at_pos(npc_position)
     end     
         
     db.actor:give_info_portion("zat_super_psevdogig_af_activation")
     remove_squad(nil, nil, {"zat_super_psevdogig_squad"})
         
     local fx_table_2 = {
         [1] = {particle = particles_object("anomaly2\\body_tear_00")},
      [2] = {particle = particles_object("amk\\blow_body")},
      [3] = {particle = particles_object("amk\\zomb_explode")},
     }
         
     for i = 1,3 do
            fx_table_2[i].particle:play_at_pos(npc_position)
     end
end

У нас есть две таблицы. Каждая имеет три партикла (каждый партикл в функциях ниже объявляется так: таблица.particle). Зачем нужно было делить из на две таблицы? Просто лучше, чтоб партиклы грави-аномалии начали играться чуть раньше партиклов разрыва тела. Цикл здесь задан немного по-другому:


for i = 1,3 do

Гляньте на пронумерованные элементы таблиц, и все станет с этим циклом ясно.
Также надо заметить, что, поскольку функция вызывается прямо из логики НПС, мы можем задать удобную локальную переменную для объявления позиции данного НПС в реальном времени:


local npc_position = npc:position()

Кто не понял, вот это npc, после которого двоеточие, - это и есть псевдогигант. Гляньте на аргументы функции:
(actor, npc)
Итак, мы используем локальную переменную для выполнения функции с циклом/таблицей:


fx_table_1[i].particle:play_at_pos(npc_position)

Задействована движковая функция play_at_pos, предназначенная конкретно для партиклов.
Если у Вас нету партиклов АМК, то вторую таблицу изменяем:


local fx_table_2 = {
      [1] = {particle = particles_object("anomaly2\\body_tear_00")},
   [2] = {particle = particles_object("anomaly2\\body_tear_01")},
   [3] = {particle = particles_object("anomaly2\\body_tear_02")},
  }

Вот и все, со всем разобрались. Смотрим результат.

Результат:

Спойлер

 

На этом урок закончен. Всем большое спасибо! smile

  • Спасибо 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация  

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу