SoC. Спавн телепортов через скрипт — различия между версиями — S.T.A.L.K.E.R. Inside Wiki

SoC. Спавн телепортов через скрипт — различия между версиями

Материал из S.T.A.L.K.E.R. Inside Wiki

Перейти к: навигация, поиск
(Авторы)
(оформление)
 
(не показана 1 промежуточная версия 1 участника)
Строка 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/
+
==Создаем телепорт==
 +
===Теория этого дела===
  
comment3,
+
В игре существует такой объект как "zone_teleport", но если мы его создадим через create, то он будет выглядеть и переливаться как настоящий телепорт, но телепортировать нас куда-либо увы не сможет. Связано это с тем что, у аномалий ( а телепорт это такая разновидность аномалии ) параметры задаются хитромудро, через all.spawn. Вобщем штатным способом телепорты без полнофункционального редактора карт не получить (хотя возможно я не прав уже после написания этого текста появились идеи как это сделать через '''all.spawn'''). Значит на нашу долю остаються способы "не штатные" ;) Реализуем самый простой. Будем считать что у нас на карте есть квадрат с заданными координатами при попадании в который актера должно переместить в точку с другими координатами. Для этого будем периодически проверять координаты актера, и если он в квадрате - перемещяем. Вот в краце принцип действия нашего "самодельного" телепорта.
 +
 
 +
===Реализация===
 +
 
 +
В каталоге ''gamedata\scripts\'' Создадим файл '''bind_mteleport.script''' с логикой работы нашего телепорта.
 +
<lua>
 +
-- ************************************************
 +
-- **                    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
 +
 
 +
</lua>
 +
 
 +
Для постоянного обновления нужно прицепить функцию 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''' и в конце файла добавляем следующие строки описывающие конкретный телепорт:
 +
 
 +
<ini>[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</ini>
 +
 
 +
Параметры нашего телепорта:
 +
 
 +
* radius - на самом деле не радиус, а половина длинны стороны нашего квадрата (в начале я хотел сделать его кругом, но посчитал, что лучше не тратить процессорное врямя по пусту). Центром квадрата является точка респавна телепорта.
 +
 
 +
* z_radius - высота нашего телепорта.
 +
 
 +
* poz_x, poz_y, poz_z - координаты точки телепортации.
 +
 
 +
* rotate - Угол поворота после телепортации от оси X (я не разбирался в каких единицах задается, но 1.5 примерно равно 90 градусов). Если параметр удалить то будет оставатья угол под которым актер вошел в телепорт.
 +
 
 +
=== Использование ===
 +
Теперь с помощью create создадим наш телепорт:
 +
Пример:
 +
 
 +
<lua> 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)</lua>
 +
 
 +
Создаст телепорт возле выхода из бункера Сидоровича.
 +
Наш телепорт перебрасывает игрока на вышку блокпоста (перед выходом с уровня).
 +
 
 +
Все! Вот [http://www.imp.webhost.ru/stalker/ тут] вы можете взять готовый мод с двумя телепортами.
 +
 
 +
==Авторы==
 +
 
 +
Статья создана:
 +
 
 +
* [[Участник:Imp|Imp]]
 +
 
 +
[[Категория:Скрипты]]

Текущая версия на 21:41, 26 июля 2013

Создаем телепорт

Теория этого дела

В игре существует такой объект как "zone_teleport", но если мы его создадим через create, то он будет выглядеть и переливаться как настоящий телепорт, но телепортировать нас куда-либо увы не сможет. Связано это с тем что, у аномалий ( а телепорт это такая разновидность аномалии ) параметры задаются хитромудро, через all.spawn. Вобщем штатным способом телепорты без полнофункционального редактора карт не получить (хотя возможно я не прав уже после написания этого текста появились идеи как это сделать через all.spawn). Значит на нашу долю остаються способы "не штатные" ;) Реализуем самый простой. Будем считать что у нас на карте есть квадрат с заданными координатами при попадании в который актера должно переместить в точку с другими координатами. Для этого будем периодически проверять координаты актера, и если он в квадрате - перемещяем. Вот в краце принцип действия нашего "самодельного" телепорта.

Реализация

В каталоге gamedata\scripts\ Создадим файл bind_mteleport.script с логикой работы нашего телепорта.

 
-- ************************************************
-- **                    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
 
 

Для постоянного обновления нужно прицепить функцию 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 и в конце файла добавляем следующие строки описывающие конкретный телепорт:

[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

Параметры нашего телепорта:

  • radius - на самом деле не радиус, а половина длинны стороны нашего квадрата (в начале я хотел сделать его кругом, но посчитал, что лучше не тратить процессорное врямя по пусту). Центром квадрата является точка респавна телепорта.
  • z_radius - высота нашего телепорта.
  • poz_x, poz_y, poz_z - координаты точки телепортации.
  • rotate - Угол поворота после телепортации от оси X (я не разбирался в каких единицах задается, но 1.5 примерно равно 90 градусов). Если параметр удалить то будет оставатья угол под которым актер вошел в телепорт.

Использование

Теперь с помощью create создадим наш телепорт: Пример:

	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)

Создаст телепорт возле выхода из бункера Сидоровича. Наш телепорт перебрасывает игрока на вышку блокпоста (перед выходом с уровня).

Все! Вот тут вы можете взять готовый мод с двумя телепортами.

Авторы

Статья создана:

Другие места
LANGUAGE