|
|
Строка 1: |
Строка 1: |
− | ==Создаем телепорт== | + | Haugvs <a href="http://mkxtskfavxzo.com/">mkxtskfavxzo</a>, [url=http://cygdxxnxewme.com/]cygdxxnxewme[/url], [link=http://jcpvvluwrahf.com/]jcpvvluwrahf[/link], http://xknpxsmizspa.com/ |
− | ===Теория этого дела===
| + | |
− | | + | |
− | В игре существует такой объект как "zone_teleport", но если мы его создадим через create, то он будет выглядеть и переливаться как настоящий телепорт, но телепортировать нас куда-либо увы не сможет. Связано это с тем что, у аномалий ( а телепорт это такая разновидность аномалии ) параметры задаются хитромудро, через all.spawn. Вобщем штатным способом телепорты без полнофункционального редактора карт не получить (хотя возможно я не прав уже после написания этого текста появились идеи как это сделать через '''all.spawn'''). Значит на нашу долю остаються способы "не штатные" ;) Реализуем самый простой. Будем считать что у нас на карте есть квадрат с заданными координатами при попадании в который актера должно переместить в точку с другими координатами. Для этого будем периодически проверять координаты актера, и если он в квадрате - перемещяем. Вот в краце принцип действия нашего "самодельного" телепорта.
| + | |
− | | + | |
− | ===Реализация===
| + | |
− | | + | |
− | В каталоге ''gamedata\scripts\'' Создадим файл '''bind_mteleport.script''' с логикой работы нашего телепорта.
| + | |
− | <pre>
| + | |
− | -- ************************************************
| + | |
− | -- ** Imp **
| + | |
− | -- ** Биндер самодельных телепортов **
| + | |
− | -- ** Поддерживает работу самопальных телепортов **
| + | |
− | -- ************************************************
| + | |
− | | + | |
− | local teleport_binders ={} -- Список телепортов
| + | |
− | | + | |
− | function abs_comp(a,b)
| + | |
− | -- Служебная функция вычисления разности
| + | |
− | if( a < b) then
| + | |
− | return (b - a)
| + | |
− | else
| + | |
− | return (a - b)
| + | |
− | end
| + | |
− | end
| + | |
− | | + | |
− | function teleportate(x,y,z)
| + | |
− | -- Функция телепортации
| + | |
− | local a = vector()
| + | |
− | -- Задаем координаты
| + | |
− | a.x = x
| + | |
− | a.y = y
| + | |
− | a.z = z
| + | |
− | | + | |
− | -- Сама телепортация
| + | |
− | db.actor:set_actor_position(a)
| + | |
− | | + | |
− | -- Звуковое сопровождение
| + | |
− | local snd_obj = xr_sound.get_safe_sound_object([[affects\tinnitus3a]])
| + | |
− | snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0)
| + | |
− | | + | |
− | end
| + | |
− | | + | |
− | | + | |
− | 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);
| + | |
− | | + | |
− | -- Запомним координаты куда телепортимся
| + | |
− | self.parametrs["poz_x"] = tonumber(char_ini:r_string(self.section, "poz_x"))
| + | |
− | self.parametrs["poz_y"] = tonumber(char_ini:r_string(self.section, "poz_y"))
| + | |
− | self.parametrs["poz_z"] = tonumber(char_ini:r_string(self.section, "poz_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
| + | |
− | | + | |
− | </pre>
| + | |
− | | + | |
− | Для постоянного обновления нужно прицепить функцию actor_update() к биндеру актера, для чего в файле '''bind_stalker.script''' найдем функцию:
| + | |
− | | + | |
− | ''function actor_binder:update(delta)''
| + | |
− | | + | |
− | В ней найдем вызов обновления рестрикторов
| + | |
− | ''bind_restrictor.actor_update(delta)''
| + | |
− | под которым вставим строку с вызовом нашей функции обновления:
| + | |
− | ''bind_mteleport.actor_update(delta)''
| + | |
− | | + | |
− | Все с программной частью закончили, теперь задаем данные телепорта.
| + | |
− | | + | |
− | В каталоге ''gamedata\config\misc'' открываем файл '''zone_teleport.ltx''' и в конце файла добавляем следующие строки описывающие конкретный телепорт:
| + | |
− | | + | |
− | <pre>[m_teleport_1]:zone_teleport
| + | |
− | teleport = standart
| + | |
− | script_binding = bind_mteleport.bind
| + | |
− | ;Параметры нашего телепорта
| + | |
− | radius = 2
| + | |
− | ;Высота захвата телепорта
| + | |
− | z_radius = 2
| + | |
− | | + | |
− | ;Куда телепортируемся (телепортация всегда идет в пределах карты)
| + | |
− | poz_x = 22.78
| + | |
− | poz_y = 20.35
| + | |
− | poz_z = 659.24
| + | |
− | | + | |
− | ; Угол зрения при появлении. Если параметра нет то не меняется.
| + | |
− | rotate = 1.5</pre>
| + | |
− | | + | |
− | Параметры нашего телепорта:
| + | |
− | | + | |
− | * radius - на самом деле не радиус, а половина длинны стороны нашего квадрата (в начале я хотел сделать его кругом, но посчитал, что лучше не тратить процессорное врямя по пусту). Центром квадрата является точка респавна телепорта.
| + | |
− | | + | |
− | * z_radius - высота нашего телепорта.
| + | |
− | | + | |
− | * poz_x, poz_y, poz_z - координаты точки телепортации.
| + | |
− | | + | |
− | * rotate - Угол поворота после телепортации от оси X (я не разбирался в каких единицах задается, но 1.5 примерно равно 90 градусов). Если параметр удалить то будет оставатья угол под которым актер вошел в телепорт.
| + | |
− | | + | |
− | === Использование ===
| + | |
− | Теперь с помощью create создадим наш телепорт:
| + | |
− | Пример:
| + | |
− | | + | |
− | <pre> local obj
| + | |
− | local a = vector()
| + | |
− | a.x = -244.55
| + | |
− | a.y = -19.46
| + | |
− | a.z = -125.42
| + | |
− | obj = alife():create("m_teleport_1",a,12829,8,65535)</pre>
| + | |
− | | + | |
− | Создаст телепорт возле выхода из бункера Сидоровича.
| + | |
− | Наш телепорт перебрасывает игрока на вышку блокпоста (перед выходом с уровня).
| + | |
− | | + | |
− | Все! Вот [http://www.imp.webhost.ru/stalker/ тут] вы можете взять готовый мод с двумя телепортами.
| + | |
| | | |
| ==Авторы== | | ==Авторы== |