Stalker Clear Sky Информация [105] | Сталкер Видео [302] | Сталкер Зов Припяти информация [133] | Первый литконкурс от stalker-gsc.ru [69] |
Фан рассказы [2616] | Стихи, песни, поэмы [727] | Интервью [140] | Чернобыль [304] |
Сталкер - основное [119] | Сталкинг [39] | Превью, обзоры игр Stalker [34] | Рецензии на игру Сталкер [30] |
Разное [333] | Интересные игры [30] | Каталог [407] | Второй литконкурс от stalker-gsc.ru [112] |
Обзор модификаций [44] |
Stalker 2 » Статьи » Разное |
15:53:42 Создание переходов между уровнями | |
Материал из S.T.A.L.K.E.R. Inside Wiki. В этой статье я попытаюсь передать практический опыт скриптового создания точек перехода между уровнями. Файл all.spawn меняться не будет, поэтому такой механизм более удобен для совмещения модов и не требует начала новой игры. В качестве примера попробуем реализовать режим freeplay - продолжение игры после уничтожения О-Сознания. Для этого нужно создать как минимум две точки — возврат на ЧАЭС-1 со внутреннего дворика (после уничтожения О-Сознания) и переход из ЧАЭС-1 в Припять. К слову сказать, если вернуться на ЧАЭС-1, то там будет продолжать действовать таймер "выброса", который в конце-концов включит "deadzone". Отключить счетчик мне пока не удалось, но зато можно легко отключить сам "выброс" и всласть побегать по уровню. Часть 1. Генерация работающего LEVEL_CHANGER Стандартной функции alife():create(…) недостаточно для создания полноценного level_changer. Собственно методика создания сложных объектов описана в статье Один из методов спавна. Сложность заключалась лишь в порядке полей и свойствах Shape. Неоценимую помощь в этом вопросе оказала утилита ACDC (created by bardak). Ниже я привожу код функции, которая создает и инициализирует level_changer: function create_level_changer( p_story_id, -- STORY_ID нового level_changer (понадобится нам позже) p_position, -- вектор, координаты точки, в которой будет располагаться центр нового level_changer p_lvertex_id, -- level_vertext_id - идентифицируют уровень, на котором будет создан level_changer p_gvertex_id, -- game_vertext_id p_dest_lv, -- level_vertex_id - идентифицируют уровень, на который level_changer будет перебрасывать игрока p_dest_gv, -- game_vertex_id p_dest_pos, -- координаты точки, в которой на новом уровне окажется игрок p_dest_dir, -- направрение взгляда игрока p_dest_level, -- название уровня, например "L11_Pripyat" p_silent -- следует задать 1, чтобы подавить вопрос о смене уровня (автоматический переход)) local obj = alife():create("level_changer", p_position, p_lvertex_id, p_gvertex_id) level.map_add_object_spot(obj.id, "level_changer", "") local packet = net_packet() obj:STATE_Write(packet) -- свойства cse_alife_object local game_vertex_id = packet:r_u16() local cse_alife_object__unk1_f32 = packet:r_float() local cse_alife_object__unk2_u32 = packet:r_u32() local level_vertex_id = packet:r_u32() local object_flags = packet:r_u32() local custom_data = packet:r_stringZ() local story_id = packet:r_u32() local spawn_story_id = packet:r_u32() -- свойства cse_shape local shape_count = packet:r_u8() for i=1,shape_count do local shape_type = packet:r_u8() if shape_type == 0 then -- sphere local center = packet:r_vec3() local radius = packet:r_float() else -- box local axis_x_x = packet:r_float() local axis_x_y = packet:r_float() local axis_x_z = packet:r_float() local axis_y_x = packet:r_float() local axis_y_y = packet:r_float() local axis_y_z = packet:r_float() local axis_z_x = packet:r_float() local axis_z_y = packet:r_float() local axis_z_z = packet:r_float() local offset_x = packet:r_float() local offset_y = packet:r_float() local offset_z = packet:r_float() end end -- свойства cse_alife_space_restrictor local restrictor_type = packet:r_u8() -- свойства cse_level_changer local dest_game_vertex_id = packet:r_u16() local dest_level_vertex_id = packet:r_u32() local dest_position = packet:r_vec3() local dest_direction = packet:r_vec3() local dest_level_name = packet:r_stringZ() local dest_graph_point = packet:r_stringZ() local silent_mode = packet:r_u8() packet:w_begin(game_vertex_id) -- game_vertex_id packet:w_float(cse_alife_object__unk1_f32) packet:w_u32(cse_alife_object__unk2_u32) packet:w_u32(level_vertex_id) -- level_vertex_id packet:w_u32( bit_not(193) ) -- object_flags = -193 = 0xFFFFFF3E packet:w_stringZ(custom_data) packet:w_u32(p_story_id) -- story_id packet:w_u32(spawn_story_id) packet:w_u8(1) -- количество фигур-- packet:w_u8(0) -- тип фигуры: сфера-- packet:w_vec3(vector():set(0, 0, 0)) -- sphere_center-- packet:w_float(3.0) packet:w_u8(1) -- тип фигуры: box packet:w_float(2) -- axis_x_x packet:w_float(0) -- axis_x_y packet:w_float(0) -- axis_x_z packet:w_float(0) -- axis_y_x packet:w_float(4) -- axis_y_y packet:w_float(0) -- axis_y_z packet:w_float(0) -- axis_z_x packet:w_float(0) -- axis_z_y packet:w_float(4) -- axis_z_z packet:w_float(0) -- offset_x packet:w_float(0) -- offset_y packet:w_float(0) -- offset_z packet:w_u8(3) -- restrictor_type packet:w_u16(p_dest_gv) -- destination game_vertex_id packet:w_u32(p_dest_lv) -- destination level_vertex_id packet:w_vec3(p_dest_pos) -- destination position packet:w_vec3(p_dest_dir) -- destination direction (направление взгляда) packet:w_stringZ(p_dest_level) -- destination level name packet:w_stringZ("start_actor_99") -- some string, always const packet:w_u8(p_silent) -- 1 for silent level changing packet:r_seek(0) obj:STATE_Read(packet, packet:w_tell()) -- news_manager.send_tip(db.actor, "LC creation finished", nil, nil, 30000)endДля shape типа "box" загрузка координат методом packet:r_matrix() окончилась неудачей. Я подозреваю, что не был прочитан вектор "offset", но точной уверенности нет, поэтому пока остановился на покомпонентной выборке и сохранении координат. [править]Часть 2. Создание точек перехода Теперь следует написать функции создания нужных точек перехода и подключить их к игре. Сами функции просты: function exit_monolit() if (not has_alife_info("freeplay_activated1")) then create_level_changer(11410, vector():set(-13.26, 47.71, 46.57), 200, 2417, 162109, 2384, vector():set( 375.615, 0.224, 27.737 ), vector():set( 0.0, 0.0 , 0.0 ), "L12_Stancia", 1) db.actor:give_info_portion("freeplay_activated1") end -- создается переход из ЧАЭС в Припять create_chaes2pripyat_exit() -- актер перебрасывается в level_changer, возвращающий его на ЧАЭС, ко входу в бункер db.actor:set_actor_position( vector():set(-13.26, 47.71, 46.57) )end function refuze_o_sozn() if (not has_alife_info("freeplay_activated2")) then create_level_changer(21410, vector():set(946.872, 6.0, 167.66), 240852, 2637, 472710, 2280, vector():set( 1062.15, -0.0982, -3.512 ), vector():set( 0.0 , 0.0 , -1.0 ), "L12_Stancia", 1) db.actor:give_info_portion("freeplay_activated2") end -- создается переход из ЧАЭС в Припять create_chaes2pripyat_exit() -- актер перебрасывается в level_changer, возвращающий его к правым воротам ЧАЭС db.actor:set_actor_position( vector():set(946.872, 6.0, 167.66) )end function create_chaes2pripyat_exit() -- создается переход из ЧАЭС в Припять if (not has_alife_info( "exit_chaes2pripyat_created" )) then create_level_changer(31410, vector():set( 917.35, 0.419, -316.35 ), 403866, 2401, 73868, 2117, vector():set( 31.3, 3.0, 240.0 ), vector():set( 0.0, 0.0, -1.0 ), "L11_Pripyat", 0) db.actor:give_info_portion("exit_chaes2pripyat_created") endendФункцию exit_monolit я создал исключительно для тестирования, но решил оставить и тут. Вдруг кто-то захочет реализовать более сложный возврат: Меченого грузят в "грузовик смерти" и он снова приходит в себя на кордоне... Функция exit_monolit создает «тихий» переход на уровень ЧАЭС-1 и обычный - в начале уровня ЧАЭС-1 для возврата в Припять, после чего перебрасывает актера прямо внутрь созданного перехода. Функция refuze_o_sozn делает тоже самое, только игрок появляется перед воротами в правом верхем углу карты (мне кажется, что так более логично). Все телепорты защищаются уникальными info_portions, дабы избежать их повторного создания, ведь игрок может захотеть «закончить» игру несколько раз. Теперь подключение. Во-первых надо добавить новые info-portions. Я решил не изменять оригинальные файлы игры, а сделал для них (ну и для других тоже) отдельный файл config\gameplay\_info_sa.xmlследующего вида: <?xml version="1.0" encoding="windows-1251" ?> <game_information_portions> <info_portion id="freeplay_activated1"></info_portion> <info_portion id="freeplay_activated2"></info_portion> <info_portion id="exit_chaes2pripyat_created"></info_portion> </game_information_portions>Теперь в этот файл можно будет добавлять новые info_portion, которые вы будете использовать в своих сюжетах. Подключается этот файл в system.ltx в секции «info_portions»: [info_portions];список xml файлов, содержащих info_portionsfiles = _info_sa, info_portions, ....................Кстати, именно так я рекомендую добавлять новые диалоги и новых персонажей. Это упростит процессы совмещения модов и аддонов. Следующий шаг - подключение наших скриптов к игре. Для этого откройте файл config\ui\ui_movies.xmlнайдите элементы «mov_desire_» (их пять, по количеству ложных концовок игры - все варианты общения с Монолитом). Внутри каждого элемента есть дочерние элементы «function_on_stop», которые задают функцию, запускающуюся сразу после ролика. Стандартное содержимое: <function_on_stop>xr_effects.game_credits</function_on_stop>Функция xr_effects.game_credits запускает финальные титры. Именно ее и нужно заменить на вызов нашей функции _freeplay_sa.exit_monolit. Вот что должно получиться: <function_on_stop>_freeplay_sa.exit_monolit</function_on_stop><!-- original: <function_on_stop>xr_effects.game_credits</function_on_stop> -->Старый элемент я советую не удалять, а закомментировать. Чуть ниже «mov_desire_5» находится тэг ролика для концовки «Присоединение к О-Сознанию». Его мы трогать не будем - Меченый станет медузой. А вот после него - тэг для ролика «Отказ от О-Сознания»: «mov_refuse_osoznanie». Функцию завершения в нем заменим следующим образом: <function_on_stop>_freeplay_sa.refuze_o_sozn</function_on_stop><!-- original: <function_on_stop>xr_effects.game_credits</function_on_stop> --> Можно запускать и, если есть сохранения перед монолитом и/или о-сознанием, тестировать. Первые переходы срабатывают «тихо» - запрос на смену уровня не выдается (в параметре p_silent задана 1). До перехода в Припять можно успеть добежать, пока не сработал выброс... Но это как-то неправильно, выброс надо остановить (он же произошел, пока мы были внутри станции). «По-честному» (скриптом, без модификации all.spawn) таймер выброса отключить не получится, но зато выброс можно подавить небольшим «хаком». Найдите файл xr_logic.script, а в нем - функцию switch_to_section. Ее нужно модифицировать следующим образом: -- Выполняет переключение на указанную секцию, если задана.-- Если section == nil, остается работать старая секция.function switch_to_section(npc, st, section) if section == nil or section == "" then return false end -- 15.03.2008 by SA: -- отключает "смертельные зоны" на ЧАЭС после запуска режима FREEPLAY -- таймер не отключается, но сам "выброс" не происходит if (section == "sr_aes_deadzone") then if (has_alife_info("freeplay_activated1") or has_alife_info("freeplay_activated2")) then return false end end ... далее без изменений ...endДанный способ оставляет висящий на нулях таймер и все эффекты начала выброса, но сам «выброс» отключается. И последнее: переход ЧАЭС1-Припять необходимо отметить на карте. Для этого существует вполне «легальный» механизм. Находим файл level_tasks.script и в конце функции add_lchanger_location дописываем следующее: -- aes (++16.03.2008 by SA): obj = sim:story_object(31410) if obj then level.map_add_object_spot(obj.id, "level_changer", "To Pripyat") endЗдесь 31410 - story_id нашего level_changer, который создается нашей функцией create_chaes2pripyat_exit. На этом пока все (мелкие огрехи типа направления взгляда игрока после смены уровня исправлю позже). Прошу тестировать и дополнять. Автор: TuMaN | |
Дата: 09.03.2014 | Категория: Разное |
Просмотров: 3071 Добавил: Mecheniy12 | Рейтинг: 5.0/1 |
Комментарии к материалу Создание переходов между уровнямиВсего комментариев: 1 | |
Рекомендуем:
МЕНЮ
Топ статей
[1002143] Сталкер Зов Припяти...
[955817] Прохождение Сталкер...
[564798] Прохождение Сталкер...
[444477] Сталкер Зов Припяти...
[148569] Lost Alpha - Секрет...
[146717] КАК ПОДСТРОИТЬ ИГРУ...
[124472] S.T.A.L.K.E.R.: Апо...
[115877] Прохождение Stalker...
[114372] Концовка Сталкер Чи...
[98373] Черный Сталкер 2 Зо...
[98031] Прохождение S.T.A.L...
[76220] Мутанты Зоны часть ...
[74871] 100 цитат из книг с...
[73253] Все группировки: Н...
[73199] Мутанты Зоны часть ...
[72901] Экзоскелет
[70490] Сталкер Тайные троп...
[70206] Аномалии - Сталкер ...
[69369] Сердце Оазиса
[63343] Прохождение Сталкер...
[955817] Прохождение Сталкер...
[564798] Прохождение Сталкер...
[444477] Сталкер Зов Припяти...
[148569] Lost Alpha - Секрет...
[146717] КАК ПОДСТРОИТЬ ИГРУ...
[124472] S.T.A.L.K.E.R.: Апо...
[115877] Прохождение Stalker...
[114372] Концовка Сталкер Чи...
[98373] Черный Сталкер 2 Зо...
[98031] Прохождение S.T.A.L...
[76220] Мутанты Зоны часть ...
[74871] 100 цитат из книг с...
[73253] Все группировки: Н...
[73199] Мутанты Зоны часть ...
[72901] Экзоскелет
[70490] Сталкер Тайные троп...
[70206] Аномалии - Сталкер ...
[69369] Сердце Оазиса
[63343] Прохождение Сталкер...
Последние статьи
- Тот самый S.T.A.L.K.E.R.: р...
- Сталкер Зов Припяти - рецен...
- Моды к Stalker Clear Sky
- Sigerous 2.0/Обзор от ATM-C...
- Встреча с Олегом Яворским
- Отчет о плейтесте "Зов...
- Прохождение Сталкер: Зов Пр...
- Сталкер Зов Припяти прохожд...
- Сталкер Зов Припяти - прохо...
- Обзор OGSM 1.7 Final
- Обзор модификации R.M.A. + ...
- Первое в мире превью Stalke...
- Press Tour 26.10.2006 (част...
- Press Tour 25.10.2006 (част...
- Акция "Сталкер-Солидар...
- Сталкер Зов Припяти - рецен...
- Моды к Stalker Clear Sky
- Sigerous 2.0/Обзор от ATM-C...
- Встреча с Олегом Яворским
- Отчет о плейтесте "Зов...
- Прохождение Сталкер: Зов Пр...
- Сталкер Зов Припяти прохожд...
- Сталкер Зов Припяти - прохо...
- Обзор OGSM 1.7 Final
- Обзор модификации R.M.A. + ...
- Первое в мире превью Stalke...
- Press Tour 26.10.2006 (част...
- Press Tour 25.10.2006 (част...
- Акция "Сталкер-Солидар...
Люди говорят
STALKER96kor ответил в Wos Team расширяется (21:29:48)
Жаль мод так и не вышел...были времена
newtime ответил в GSC Game World перенесла выход S.T.A.L.K.E.R. 2: Heart of Chernobyl на конец года (19:02:08)
привет)
Vampire388235 ответил в GSC Game World перенесла выход S.T.A.L.K.E.R. 2: Heart of Chernobyl на конец года (20:59:14)
Шло 24 декабря 2023 года, а сталкер 2 все еще только в надеждах
DiegoLidabo ответил в DB Packer 1.0 (09:11:16)
Нет страницы для скачивания
avast ответил в GSC Game World перенесла выход S.T.A.L.K.E.R. 2: Heart of Chernobyl на конец года (14:48:05)
Что-то мне кажется она вообще не выйдет... Григорович опять чего-нибудь замутит мутное...
Жаль мод так и не вышел...были времена
newtime ответил в GSC Game World перенесла выход S.T.A.L.K.E.R. 2: Heart of Chernobyl на конец года (19:02:08)
привет)
Vampire388235 ответил в GSC Game World перенесла выход S.T.A.L.K.E.R. 2: Heart of Chernobyl на конец года (20:59:14)
Шло 24 декабря 2023 года, а сталкер 2 все еще только в надеждах
DiegoLidabo ответил в DB Packer 1.0 (09:11:16)
Нет страницы для скачивания
avast ответил в GSC Game World перенесла выход S.T.A.L.K.E.R. 2: Heart of Chernobyl на конец года (14:48:05)
Что-то мне кажется она вообще не выйдет... Григорович опять чего-нибудь замутит мутное...
Последнее на форуме
Статистика
Онлайн всего: 31
Гостей: 31
Сталкеров: 0