Рассмотрим что нам из этого можно менять для создания своего телепорта:
1. [1] номер секции. номера в alif_локация должны идти строго по порядку
2. name = moy_teleport_0001 здесь пишется имя телепорта(любое), единственно на что надо обратить внимание – это то, что если вам лень менять имена, то номер телепорта менять придется обязательно т.е. создадим несколько телепортов с одним именем, это будут такие телепорты: name = moy_teleport_0001 name = moy_teleport_0002 name = moy_teleport_0003 …………………………… name = moy_teleport_xxxx
3. position = 118.185966491699,8.19023418426514,-49.18896484375 это точка, на которой появится наш телепорт
4. direction = 0,0,0 это «направление взгляда» нашего телепорта (0,0,0, - на север)
5. game_vertex_id = 979 и level_vertex_id = 314612 гейм- и левел-вертексы
point1 = moy_teleport_walk_polet1 это ссылка на секцию в way_локация (точка телепортации)
look1 = moy_teleport_look_polet1 это ссылка на секцию в way_локация (направление взгляда ГГ при телепортации)
Одно замечание: если вам не важно, куда будет смотреть ГГ после «перелета», то строку look1 = moy_teleport_look_polet1 можно вырезать, тогда отпадает необходимость создания секции [moy_teleport_look_polet1] в way-локация.
7. shape0:radius = 2.5 это радиус «захвата» нашего телепорта, чем меньше радиус – тем меньше телепорт и соответсвенно чем больше радиус – тем больше телепорт.
гейм- и левел-вертексы соответственно «точки приземления» и направления взгляда.
Одно важное замечание! 1. Если вы создавая телепорт в его секции напишете только ссылку на «путь»(walk) к точке переноса, но не напишете ссылку на «взгляд»(look), а в way_локация создадите обе секции «путь» и «взгляд»(walk и look), ничего страшного не случится, но если наоборот, в секции телепорта напишете ссылки и на «путь» и на «взгляд»(walk и look) а в way_локации создадите только одну секцию( или «путь» или «взгляд»), то ждите вылетов или как минимум некорректной работы вашего телепорта. 2. Этот телепорт "работает только в пределах одной локации.
Вот и весь урок. Надеюсь теперь вы сможете без проблем создавать свои телепорты в игре.
В следующем уроке мы рассмотрим пример создания телепортов через скрипт.
4. direction = 0,0,0 это «направление взгляда» нашего телепорта (0,0,0, - на север)
Изменяя данные координаты можно разворачивать плоскость телепорта куда угодно по горизонтали, вертикали и вокруг собственной оси. Полный разворот на 360 градусов соответствует 6 единицам. Например, если указать координаты 0,-1.5,0 то "лицо" телепорта развернется вокруг своей вертикальной оси по часовой стрелке на 90 градусов. Однако, не следует забывать и вот об этой части секции телепорта: ; cse_shape properties shapes = shape0 shape0:type = sphere shape0:offset = 0,0,0 shape0:radius = 2.5 Здесь видно, что он представляет собой сферу и если в строке шейп0 все координаты стоят равные 0, то сфера имеет правильную форму. При изменении их можно достичь получения ее разнообразной формы. К сожалению, визуально это не будет заметно, так как внешний вид телепорта задается другой секцией, при спавне которой мы и видим его изображение, которое собственно и "крутим-вертим" как нам удобно - это визуал телепорта, появляющегося в игре. Например:
[960] ; cse_abstract properties section_name = zone_teleport name = teleport_visual position = 134.899993896484,5.5,-51.5 direction = 1.5,0,0
function actor_update(delta) local i,v,acter_poz,s
-- Получим позицию актера (что-бы каждый раз не запрашивать) acter_poz = db.actor:position()
-- Проверяем наши телепорты for i, v in pairs(teleport_binders) do s = v.parametrs
local obj = level.object_by_id( i ) if obj ~= nil then -- Наш телепорт в онлайне проверяем дальше if s.teleporte ~= nil and s.teleporte ~= false then -- Телепорт запущен if ( time_global() <= s.time ) then -- Если время отведенное на показ спецэфектов -- прошло, производим телепортацию teleportate(s.poz_x,s.poz_y,s.poz_z) if s.rotate ~= nil then db.actor:set_actor_direction(s.rotate) end s.teleporte = false end return end
-- Пороверим не забрел-ли актер в наш телепорт if (abs_comp(s.x, acter_poz.x)< v.parametrs.radius and abs_comp(s.z, acter_poz.z)< v.parametrs.radius and abs_comp(s.y, acter_poz.y)< v.parametrs.z_radius) then -- Актер в зоне действия телепорта, запустим телепорт s["teleporte"] = true s["time"] = time_global() + 500
-- Запускаем спецэфекты телепортации level.add_pp_effector ("teleport.ppe", 2006, false) end end end end
function bind( obj ) obj:bind_object( restrictor_teleport( obj ) ) end
---------------------------------------------------------------------------------------------------- class "restrictor_teleport" ( object_binder )
function restrictor_teleport:__init(obj, char_ini) super(obj) end
function restrictor_teleport:net_spawn(data) local char_ini = system_ini()
-- Если это телепорт то занесем его в специальный список телепортов if self.teleport == true then teleport_binders[self.object:id()] = self
-- Заполним таблицу параметров self["parametrs"] = {} if char_ini:line_exist(self.section, "radius") then self.parametrs["radius"] = tonumber(char_ini:r_string(self.section, "radius")) else self.parametrs["radius"] = 2 -- Дефолтный радиус по xy end if char_ini:line_exist(self.section, "z_radius") then self.parametrs["z_radius"] = tonumber(char_ini:r_string(self.section, "z_radius")) else self.parametrs["z_radius"] = self.parametrs["radius"] -- если радиус высоты не задан то задаем равным радиусу xy end
-- Запомним позицию что-бы каждый раз не считать local s_obj = alife():object(self.object:id()) self.parametrs["x"] = tonumber(s_obj.position.x); self.parametrs["y"] = tonumber(s_obj.position.y); self.parametrs["z"] = tonumber(s_obj.position.z);
if char_ini:line_exist(self.section, "rotate") then self.parametrs["rotate"] = tonumber(char_ini:r_string(self.section, "rotate")) end end return true end
function restrictor_teleport:net_destroy() -- Удаляем наш телепорт teleport_binders[self.object:id()] = nil self.parametrs = nil object_binder.net_destroy(self) end
function restrictor_teleport:reload(section) local char_ini = system_ini()
self.section = section -- Если это телепорт то if char_ini ~= nil and char_ini:line_exist(self.section, "teleport") then self["teleport"] = true end end
2. Чтобы наш телепорт работал необходимо прицепить функцию actor_update() к биндеру актера, для чего в файле bind_stalker.script найдем функцию: function actor_binder:update(delta) В ней найдем вызов обновления рестрикторов bind_restrictor.actor_update(delta) под которым вставим строку с вызовом нашей функции обновления: bind_mteleport.actor_update(delta)
т.е. оригинальный биндер актора выглядит так:
нужная нам часть:
Код
-- обновление рестрикторов, которые под логикой, срабатывает через интервалы времени if self.next_restrictors_update_time < time then bind_restrictor.actor_update(delta)
self.next_restrictors_update_time = time + 200
task_manager.actor_update() end
а так должен выглядеть правленный:
Код
-- обновление рестрикторов, которые под логикой, срабатывает через интервалы времени if self.next_restrictors_update_time < time then bind_restrictor.actor_update(delta) bind_mteleport.actor_update(delta) --наша строчка self.next_restrictors_update_time = time + 200
task_manager.actor_update() end
3.
Далее, открываем файл zone_teleport.ltx по пути gamedata\config\misc и в самый конец его вставляем:
Код
[m_teleport_1]:zone_teleport teleport = standart script_binding = bind_mteleport.bind ;Параметры нашего телепорта radius = 1 ;Высота захвата телепорта z_radius = 1
;Куда телепортируемся (телепортация всегда идет в пределах карты) poz_x = 106.72 poz_y = 18.09 poz_z = 169.16 ; Угол зрения при появлении. Если параметра нет то не меняется rotate = 3.8
это секция нашего телепорта
[m_teleport_1] - имя нашего телепорта(для каждого создаваемого телепорта должно быть свое)
poz_x = 106.72 poz_y = 18.09 poz_z = 169.16 --координаты куда происходит телепортация
4.
Далее создадим любой скриптовый файл, ну например ddd.script и в этот файл помещаем функцию спавна нашего телепорта:
Код
function spawn_perebros() alife():create("m_teleport_1",vector():set(-90.52,1.23,-37.37),119023,321) end
где: spawn_perebros название функции(для каждого создаваемого телепорта свое) m_teleport_1 имя телепорта в файле zone_teleport.ltx (-90.52,1.23,-37.37),119023,321) координаты,левел и гейм вертексы точки спавна нашего телепорта
5.
Ну и последнее. Надо как-то вызвать наш телепорт. Для этого можно такую конструкцию:
Код
<action>ddd.spawn_perebros</action>
где ddd - имя скриптового файла с нашей функцией спавна телепорта spawn_perebros - имя нашей функции
например, вставить в любой диалог, любому НПС и после диалога с ним появится наш телепорт по заданным координатам (-90.52,1.23,-37.37),119023,321)
Frankenshtayn, а можно расписать поподробнее пятый пункт (Телепорт через скрипт), пытаюсь установить на Локации Кордон, но при диалоге с Сидоровичем ни чего не происходит, дополните пожалуста инструкцию по вызову скрипта на примере Сидоровича.
volazar, потому и пишу вопрос, т.к. не знаю куда ее прописать, "тыкаю" ее куда угодно и бесталку. Сейчас установлено: ТЧ 1.0004+НС+допа+ОПП+ЧШ, вот и хочу что-бы после диалога с Сидоровичем, например после получения ремкомплекта, он выдавал их и открывался самопальный телепорт. Если идти пошагово по инструкции от Frankenshtayn: 1.В моей сборке уже присутствует; 2.В моей сборке уже присутствует; 3.Создаю свой телепорт
[kordon_teleport_1]:zone_teleport teleport = standart script_binding = bind_mteleport.bind ;Параметры нашего телепорта radius = 2 ;Высота захвата телепорта z_radius = 1
;Куда телепортируемся (телепортация всегда идет в пределах карты) poz_x = 16.418500900269 poz_y = 16.154039382935 poz_z = 670.52667236328 ; Угол зрения при появлении. Если параметра нет то не меняется rotate = 3.8
т.е. точка приземления на северном блок-посту 4. создал файл по инструкции ddd.script
function spawn_perebros() alife():create("kordon_teleport_1",vector():set(-249.61483764648,-19.551191329956,-127.22341918945),10148,8) end
т.е. телепорт создается прямо у выхода из бункера Сидоровича 5. <action>ddd.spawn_perebros</action> -- хочу прописать Сидоровичу
Frankenshtayn, спасибо за помощь, но как я понял, Вы привели пример на all.spawn(не) и увязали ее с подземкой агропрома, я пока с этим не работаю, почему и пытаюсь пока разобраться со скриптами и похоже удалось. Т.к. уже на Кордоне образовался у меня Фанат и веток диалогов у него мало, я данную конструкцию привязал к нему. После обращения: «И что у Вас тут интересного?» и окончания диалога, сработал телепорт. Вот что мне нужно было: D:\Program Files (x86)\GSC World Publishing\S.T.A.L.K.E.R\gamedata\config\gameplay\dialogs_escape.XML
Отлично сработали точки телепорта и его телепортация на северный блок-пост Кордона.
Сейчас новая проблема))), а как его сделать разовым, что-бы после использования он ликвидировался.
Ну если я, т.е мы с Frankenshtayn, включили телепорт, значит будем его вместе отключать. Создаем новый скрипт файл например: ddd_del.SCRIPT
function del_tele_lov() for a=10,65634,1 do local obj=alife():object(a) if obj and string.find(obj:name(),"kordon_teleport_1") then alife():release(obj,true) end end end
Опять прописываем в диалог Фанату отключение телепорта: <action>ddd_del.del_tele_lov</action>
И на заданный ему вопрос: «А что ты думаешь о ЗОНЕ?» и его диалога, телепорт отключится. Конечно, можно бы было вообще дописать диалог Фанату вкл./выкл. телепорта, но это уже уроки моддингаот volazar – «создание диалогов».
Внимание!. Данный телепорт делался на сборке: ТЧ 1.0004+НС+допа+ОПП+(ЧШ), и координаты могут не совпать с другими сборками, лучше их устанавливать самостоятельно.
Сообщение отредактировал filoret - Пятница, 12.07.2013, 17:51
filoret, Ну, гадая что и как ты делал, ничего путного не посоветуем... А вообще вот посмотри: (пропустим шаг 1 и 2, т.к. если правильно понимаю, здесь все в порядке) шаг з: шаг4: Профиль непися с диалогом: Сам диалог с экшеном: Вот результат:
Все это проделано буквально за 20 минут, и все работает. Из этого значит, что ты где-то ошибся... где?... Отгадать не могу... Проверяй все свои файлы, при отрицательном результате, выложи сюда свои правки, попробуем помочь.
спасибо за помощь, но как я понял, Вы привели пример на all.spawn(не) и увязали ее с подземкой агропрома, я пока с этим не работаю
filoret, эээ... Или мы не понимем друг друга, или Вы невнимательно просмотрели скрины... Там аллспавн вообще не упомянут... На первом скрине - секция телепорта в zone_teleport.ltx, на втором скрине - функция спавна этого телепорта скриптовым методом в скрипте fr_tm.script, на третьем скрине я показал, что диалог о появлении телепорта зарегестрирован в профиле НПС, ну а на четвертом - сам диалог с экшеном....
Цитата (filoret)
Отлично сработали точки телепорта и его телепортация на северный блок-пост Кордона.
Замечательно! Значит правильно и в нужное место вставлен экшен.
Цитата (filoret)
Сейчас новая проблема))), а как его сделать разовым, что-бы после использования он ликвидировался.
Удалить его можно так: вызвать в нужный момент любым доступным способом функцию:
Код
function del_tele_lov() for a=10,65634,1 do local obj=alife():object(a) if obj and string.find(obj:name(),"kordon_teleport_1") then alife():release(obj,true) end end end
Телепорт с возможностью телепортации ГГ на другую локацию
Для телепортации ГГ на другую локацию создадим скриптовый файл, например abc.script и в него вставляем такой код:
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)
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()
function my_tele_start() --функция телепортации-- create_level_changer(20101, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), 10193,--л-вертекс на локации, куда телепортируемся------ 2437,--г-вертекс на локации, куда телепортируемся------ vector():set(66.210,15.040,4.250), ---координаты на локации, куда телепортируемся---- vector():set(0.0, 0.0, 0.0), "l11_Pripyat", --локация, куда телепортируемся-- 1) end
function delete_my_tele() --функция удаления телепорта-- local sim = alife() local se_obj = sim:story_object(20101) if se_obj then sim:release(se_obj, true) end local actor = db.actor end
Небольшое пояснение: Функции телепортации и удаления телепорта должны лежать в одном скрипте с нетпакетом(в данном примере в abc.script) 20101 - сид нашего телепорта регестрируем в game_story_ids.ltx В общем все просто, вызываем функцию my_tele_start() и происходит телепортация на выбранную Вами локацию(естественно нужно не ошибиться с координатами и вертексами), затем необходимо удалить данный телепорт, т.к. он остается на своем месте, и в следующи раз в него можно "нечаянно вляпаться" и опять телепортироваться. Для его удаления вызываем удобным для Вас способом функцию delete_my_tele() и телепорт удалится.
Привет всем. Скопировал сдесь и хотел опробовать (Телепорт через скрипт). У меня происходит вылет при загрузке игры(тч 10004 - без модов.) все файлы прилагаю подскажите может что то упустил?
--config\misc\zone_teleport--
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[m_teleport_1]:zone_teleport teleport = standart script_binding = bind_mteleport.bind ;Параметры нашего телепорта radius = 1 ;Высота захвата телепорта z_radius = 1
;Куда телепортируемся (телепортация всегда идет в пределах карты) poz_x = -213.209 poz_y = 30.048 poz_z = -297.363 ; Угол зрения при появлении. Если параметра нет то не меняется rotate = 3.8
-- обновление рестрикторов, которые под логикой, срабатывает через интервалы времени if self.next_restrictors_update_time < time then bind_restrictor.actor_update(delta) bind_mteleport.actor_update(delta) self.next_restrictors_update_time = time + 200
function actor_update(delta) local i,v,acter_poz,s
-- Получим позицию актера (что-бы каждый раз не запрашивать) acter_poz = db.actor:position()
-- Проверяем наши телепорты for i, v in pairs(teleport_binders) do s = v.parametrs
local obj = level.object_by_id( i ) if obj ~= nil then -- Наш телепорт в онлайне проверяем дальше if s.teleporte ~= nil and s.teleporte ~= false then -- Телепорт запущен if ( time_global() <= s.time ) then -- Если время отведенное на показ спецэфектов -- прошло, производим телепортацию teleportate(s.poz_x,s.poz_y,s.poz_z) if s.rotate ~= nil then db.actor:set_actor_direction(s.rotate) end s.teleporte = false end return end
-- Пороверим не забрел-ли актер в наш телепорт if (abs_comp(s.x, acter_poz.x)< v.parametrs.radius and abs_comp(s.z, acter_poz.z)< v.parametrs.radius and abs_comp(s.y, acter_poz.y)< v.parametrs.z_radius) then -- Актер в зоне действия телепорта, запустим телепорт s["teleporte"] = true s["time"] = time_global() + 500
-- Запускаем спецэфекты телепортации level.add_pp_effector ("teleport.ppe", 2006, false) end end end end
function bind( obj ) obj:bind_object( restrictor_teleport( obj ) ) end
---------------------------------------------------------------------------------------------------- class "restrictor_teleport" ( object_binder )
function restrictor_teleport:__init(obj, char_ini) super(obj) end
function restrictor_teleport:net_spawn(data) local char_ini = system_ini()
-- Если это телепорт то занесем его в специальный список телепортов if self.teleport == true then teleport_binders[self.object:id()] = self
-- Заполним таблицу параметров self["parametrs"] = {} if char_ini:line_exist(self.section, "radius") then self.parametrs["radius"] = tonumber(char_ini:r_string(self.section, "radius")) else self.parametrs["radius"] = 2 -- Дефолтный радиус по xy end if char_ini:line_exist(self.section, "z_radius") then self.parametrs["z_radius"] = tonumber(char_ini:r_string(self.section, "z_radius")) else self.parametrs["z_radius"] = self.parametrs["radius"] -- если радиус высоты не задан то задаем равным радиусу xy end
-- Запомним позицию что-бы каждый раз не считать local s_obj = alife():object(self.object:id()) self.parametrs["x"] = tonumber(s_obj.position.x); self.parametrs["y"] = tonumber(s_obj.position.y); self.parametrs["z"] = tonumber(s_obj.position.z);
if char_ini:line_exist(self.section, "rotate") then self.parametrs["rotate"] = tonumber(char_ini:r_string(self.section, "rotate")) end end return true end
function restrictor_teleport:net_destroy() -- Удаляем наш телепорт teleport_binders[self.object:id()] = nil self.parametrs = nil object_binder.net_destroy(self) end
function restrictor_teleport:reload(section) local char_ini = system_ini()
self.section = section -- Если это телепорт то if char_ini ~= nil and char_ini:line_exist(self.section, "teleport") then self["teleport"] = true end end
Вылет говорит об ошибке (скорей всего синтаксис) в файле bind_mteleport.
Володя, если в этом скрипте у Giznyhvatit, больше ничего нет, то ошибки быть не должно(то что показано под спойлером - без ошибок, проверил чекером, да и сравнил на всякий случай со своим рабочим))... А кроме синтаксической ошибки в bind_mteleport, такой вылет может говорить только об отсутствии этого скрипта... А вообще ты прав - хотелось бы посмотреть файлы...
привет, все файлы в спойлерах , то что в спойлерах вставлял в свои файлы. У меня вопрос, какие файлы отвечают за телепорт и все что с ним связано? рестриктор в алл.спавне не нужен?
Сообщение отредактировал Giznyhvatit - Вторник, 22.10.2013, 23:04
Парни все отбой! мой косяк, лень было создать файл скрипт, просто схватил лтх(ный) файл, очистил и вставил в него конфиги от - bind_mteleport. А сейчас после ваших слов, задумался о том что игра его невидит, проверил точно, нужно было с папки со скриптами брать, а я видимо из папки misc схватил и вот результат))))) Вы уж извените))) все работает отлично!!!
Сообщение отредактировал Giznyhvatit - Вторник, 22.10.2013, 23:44
Как сделать телепортацию ГГ в ТЧ, после принятия водки? Перемещение героя происходит в пределах одной локации. Не обязательно что бы был телепорт, главное что после принятия водки ГГ перемещается на указаные координаты
Так же нашел функцию телепортации по одной локации, подскажите пожалуйста, куда её вставит для разового перемещения? То есть после тестов, я удалю эту функцию. Я это вижу так, функцию вставляем в скриптовый файл, а сам файл вызываем после принятия бутылки водки [code] function teleportate_to_() local a = vector() a.x = -241.71509460448 a.y = -26.742816052856 a.z = -304.54711914063 db.actor:set_actor_position(a) end
Сообщение отредактировал Askar - Четверг, 06.05.2021, 08:05
Далее, в самом конце файла, после самого последнего end, вставляешь такую конструкцию:
Код
function actor_binder:use_inventory_item(obj) if string.find(obj:section(), "vodka") then dds_spawn.oblom() end end
Где vodka - нужный итем, dds_spawn - скриптовый файл, в котором лежит функция телепортации, oblom() имя фукции телепортации, которая лежит в файле dds_spawn. Функцию телепортации можно вставлять в принципе в любой скриптовый файл. Лучше всего создать свой скриптовый файл, например my_script_funk.script и поместить его по пути gamedata\scripts, и в нем испытывать фсе свои изобретения, дабы не ушатать скрипты ТЧ. В предложенном мной примере, есть нюанс - либо надо ставить условие на однократное срабатывание функции телепорта, либо создавать (копировать) уникальную бутылку водки в единичном экземпляре и по ее использованию уже вызывать функцию телепорта. Если же оставить всё так как есть, то после каждой выпитой бутылки ГГ будет "улетать" в координаты указанные в функции телепортации.