Сповіщення
Очистити все

SoC. Співн телепортів через скрипт


Ранг:
Майстер
Роль:
Гість
Записи:
752
Приєднався:
7 місяців тому
 

Створюємо телепорт

Теорія цієї справи

У грі існує такий об'єкт як "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 ( ) 
	- Задаємо координати
	ax = x
	ay = y
	az = z
 
	-- Сама телепортація 
	db.actor: set_actor_position ( a )
 
	
	- Звуковий супровід local snd_obj = xr_sound.get_safe_sound_object ( [ [ affects \ tinnitus3a ] ] ) 
	snd_obj : play_no_feedback _
 
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 ( sx, acter_poz.x ) < v.parametrs.radius   and 
			    abs_comp ( sz, acter_poz.z ) < v.parametrs.radius   and 
			    abs_comp ( sy, 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 ( ) 
	ax = -244.55 
	ay = -19.46 
	az = -125.42 
	obj = alife ( ) :create ( "m_teleport_1" ,a, 12829 , 8 , 65535 )

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


   
Цитата