-- ----------------------------------------------------------------------------------------------------
-- Общие функции
-- ----------------------------------------------------------------------------------------------------

function disable_ui_elements(actor, npc, p)
		local i, v = 0, 0
		for i, v in pairs(p) do
				if v == "all" then
						db.actor:hide_weapon()
						level.disable_input()
						--level.hide_indicators()
			level.hide_indicators_safe()
						break
				elseif v == "weapon" then
						db.actor:hide_weapon()
				elseif v == "input" then
						level.disable_input()
				elseif v == "hud" then
						--level.hide_indicators()
			level.hide_indicators_safe()
				end
		end
		--printf("xr_effects <disable_ui_elements>")
end

function enable_ui_elements(actor, npc, p)
		local i, v = 0, 0
		for i, v in pairs(p) do
				if v == "all" then
						level.show_indicators()
						level.enable_input()
						db.actor:restore_weapon()
						break
				elseif v == "hud" then
						level.show_indicators()
				elseif v == "input" then
						level.enable_input()
				elseif v == "weapon" then
						db.actor:restore_weapon()
				end
		end
	--printf("xr_effects <enable_ui_elements>")
end

function disable_ui(actor, npc)
	if db.actor:is_talking() then
		db.actor:stop_talk()
	end
--	get_console():execute("hud_crosshair 0")
--	get_console():execute("hud_weapon 0")
    level.show_weapon(false)
	level.disable_input()
	level.hide_indicators_safe()
	local hud = get_hud()
	hud:HideActorMenu()
	hud:HidePdaMenu()
end

function enable_ui(actor, npc)
--	get_console():execute("hud_crosshair 1")
--	get_console():execute("hud_weapon 1")
    level.show_weapon(true)
    level.enable_input()
    level.show_indicators()
end

local cam_effector_playing_object_id = nil

function run_cam_effector(actor, npc, p)
		if p[1] then
				local loop, num = false, (1000 + math.random(100))

				if p[2] and type(p[2]) == "number" and p[2] > 0 then
						num = p[2]
				end

				if p[3] and p[3] == "true" then
						loop = true
				end

				--level.add_pp_effector(p[1] .. ".ppe", num, loop)
			level.add_cam_effector("camera_effects\\" .. p[1] .. ".anm", num, loop, "xr_effects.cam_effector_callback")
		cam_effector_playing_object_id = npc:id()
		end
end

function stop_cam_effector(actor, npc, p)
		if p[1] and type(p[1]) == "number" and p[1] > 0 then
				level.remove_cam_effector(p[1])
		end
end

function run_cam_effector_global(actor, npc, p)
	local num = 1000 + math.random(100)
	if p[2] and type(p[2]) == "number" and p[2] > 0 then
		 num = p[2]
	end
	level.add_cam_effector2("camera_effects\\" .. p[1] .. ".anm", num, false, "xr_effects.cam_effector_callback")
	cam_effector_playing_object_id = npc:id()
end

function cam_effector_callback()
	if cam_effector_playing_object_id == nil then
		printf("cam_eff:callback1!")
		return
	end
	local st   = db.storage[cam_effector_playing_object_id]
	if st == nil or st.active_scheme == nil then
		printf("cam_eff:callback2!")
		return
	end

	if st[st.active_scheme].signals == nil then
		printf("cam_eff:callback3!")
		return
	end
	st[st.active_scheme].signals["cameff_end"] = true
end

function run_postprocess(actor, npc, p)
		if p[1] then
				local loop, num = false, (2000 + math.random(100))

				if p[2] and type(p[2]) == "number" and p[2] > 0 then
						num = p[2]
				end

				if p[3] and p[3] == "true" then
						loop = true
				end

				level.add_pp_effector(p[1] .. ".ppe", num, loop)
		end
end

function stop_postprocess(actor, npc, p)
		if p[1] and type(p[1]) == "number" and p[1] > 0 then
				level.remove_pp_effector(p[1])
		end
end

function run_tutorial(actor, npc, p)
	game.start_tutorial(p[1])
end
function run_tutorial_if_newbie(actor, npc, p)
	if has_alife_info("esc_trader_newbie") then
		game.start_tutorial(p[1])
	end
end

function teleport_actor(actor, npc, p)
	local point = patrol(p[1])
	local look = patrol(p[2])

	db.actor:set_actor_position(point:point(0))
	local dir = look:point(0):sub(point:point(0))
	db.actor:set_actor_direction(-dir:getH())
end
-----------------------------------------------------------------------------
local drop_point, drop_object = 0, 0
local function drop_object_item(item)
		drop_object:drop_item_and_teleport(item, drop_point)
end

function drop_actor_inventory(actor, npc, p)
		if p[1] then
				drop_point  = patrol(p[1]):point(0)
				drop_object = actor
				actor:inventory_for_each(drop_object_item)
		end
end


-- FIXME: drop_npc_inventory doesn't work
function drop_npc_inventory(actor, npc, p)
		if p[1] then
				drop_point  = patrol(p[1]):point(0)
				drop_object = npc
				npc:inventory_for_each(drop_object_item)
		end
end

function drop_npc_item(actor, npc, p)
		if p[1] then
				local item = npc:object(p[1])
				if item then
				npc:drop_item(item)
		end
		end
end

function drop_npc_items(actor, npc, p)
		local item = 0
	for i, v in pairs(p) do
				item = npc:object(v)
				if item then
				npc:drop_item(item)
				end
		end
end

function give_items(actor, npc, p)
		local pos, lv_id, gv_id, npc_id = npc:position(), npc:level_vertex_id(), npc:game_vertex_id(), npc:id()
	for i, v in pairs(p) do
				alife():create(v, pos, lv_id, gv_id, npc_id)
		end
end

function play_particle_on_path(actor, npc, p)
		local name = p[1]
		local path = p[2]
		local point_prob = p[3]
		if name == nil or path == nil then
				return
		end

		if point_prob == nil then
				point_prob = 100
		end

		local path = patrol(path)
		local count = path:count()
		for a = 0,count-1,1 do
				local particle = particles_object(name)
				if math.random(100) <= point_prob then
						particle:play_at_pos(path:point(a))
				end
		end
end


-----------------------------------------------------------------------------
--[[
send_tip(news_id:sender:sender_id)
		1. news_id
		2. sender*
		3. sender_id*
		* - not necessary
--]]
function send_tip(actor, npc, p)
		news_manager.send_tip(actor, p[1], nil, p[2], nil, p[3])
end

--[[
Дать сталкеру небольшой пинок. Например чтоб скинуть его с возвышения.
параметры: actor, npc, p[direction,bone,power,impulse,reverse=false]
		1. direction - если строка, то считается, что это имя пути и в сторону
				первой точки производится толчек. Если же это число, то оно
				рассматривается как story_id персонажа от которого должен поступить хит.
		2. bone - строка. Имя кости, по которой наносится удар.
		3. power - сила удара
		4. impulse - импульс
		5. reverse (true/false) - изменение направления удара. по умолчанию false
--]]
function hit_npc(actor, npc, p)
	local h = hit()
	local rev = p[5] and p[5] == 'true'
	h.draftsman = npc
	h.type = hit.wound
	if type(p[1]) == 'number' then
		local hitter = level_object_by_sid(p[1])
		if not hitter then return end
			if rev then
					h.draftsman = hitter
				h.direction = hitter:position():sub(npc:position())
			else
				h.direction = npc:position():sub(hitter:position())
			end
	else
			if rev then
					h.draftsman = nil
				h.direction = npc:position():sub(patrol(p[1]):point(0))
			else
				h.direction = patrol(p[1]):point(0):sub(npc:position())
			end
	end
	h:bone(p[2])
	h.power = p[3]
	h.impulse = p[4]
	printf("HIT EFFECT: (%s, %s,%d,%d) health(%s)", npc:name(), p[2], h.power, h.impulse, npc.health)
	npc:hit(h)
end

--[[
Дать обьекту, заданному story_id, хит.
параметры: actor, npc, p[sid,bone,power,impulse,hit_src=npc:position()]
		1. sid - story_id обьекта, по которому наносится хит.
		2. bone - строка. Имя кости, по которой наносится удар.
		3. power - сила удара
		4. impulse - импульс
		5. hit_src - если число, то рассматривается как story_id обьекта, со стороны
				которого наносится хит (он же является и инициатором хита), иначе это
				точка (waypoint), из которой по объекту наносится хит.
				Если не задано, то берется позиция обьекта, из которого была вызвана
				данная функция.
--]]
function hit_obj(actor, npc, p)
	local h = hit()
	local obj = level_object_by_sid(p[1])
	local sid = nil

	if not obj then
--    abort("HIT_OBJ [%s]. Target object does not exist", npc:name())
		return
	end

	h:bone(p[2])
	h.power = p[3]
	h.impulse = p[4]

	if p[5] then
			sid = tonumber(p[5])
			if sid then
					sid = level_object_by_sid(sid)
					if sid then
							h.direction = vector():sub(sid:position(), obj:position())
					end
			end
			if not sid then
					h.direction = vector():sub(patrol(p[5]):point(0), obj:position())
			end
	else
			h.direction = vector():sub(npc:position(), obj:position())
	end

	h.draftsman = sid or npc
	h.type = hit.wound
	obj:hit(h)
end

function hit_obj_chemical(actor, npc, p)
	local h = hit()
	local obj = level_object_by_sid(p[1])
	local sid = nil

	if not obj then
--    abort("HIT_OBJ [%s]. Target object does not exist", npc:name())
		return
	end

	h:bone(p[2])
	h.power = p[3]
	h.impulse = p[4]

	if p[5] then
			sid = tonumber(p[5])
			if sid then
					sid = level_object_by_sid(sid)
					if sid then
							h.direction = vector():sub(sid:position(), obj:position())
					end
			end
			if not sid then
					h.direction = vector():sub(patrol(p[5]):point(0), obj:position())
			end
	else
			h.direction = vector():sub(npc:position(), obj:position())
	end

	h.draftsman = sid or npc
	h.type = hit.chemical_burn
	obj:hit(h)
end

function hit_obj_fire_wound(actor, npc, p)
	local h = hit()
	local obj = level_object_by_sid(p[1])
	local sid = nil

	if not obj then
--    abort("HIT_OBJ [%s]. Target object does not exist", npc:name())
		return
	end

	h:bone(p[2])
	h.power = p[3]
	h.impulse = p[4]

	if p[5] then
			sid = tonumber(p[5])
			if sid then
					sid = level_object_by_sid(sid)
					if sid then
							h.direction = vector():sub(sid:position(), obj:position())
					end
			end
			if not sid then
					h.direction = vector():sub(patrol(p[5]):point(0), obj:position())
			end
	else
			h.direction = vector():sub(npc:position(), obj:position())
	end

	h.draftsman = sid or npc
	h.type = hit.fire_wound
	obj:hit(h)
end

--[[
Дать сталкеру небольшой пинок после смерти. Аналогично предыдущему, только направление хита теперь
вычисляется через убийцу. Поэтому параметра direction нет.
параметры: actor, npc, p[bone,power,impulse]
FIXME: killer:position() isn't working
--]]
function hit_by_killer(actor, npc, p)
	if not npc then return end
	local t = db.storage[npc:id()].death
	if t == nil or t.killer == -1 then return end
	local killer = db.storage[t.killer]
	if killer == nil then return end
	local p1, p2
	p1 = npc:position()
	p2 = killer:position()
	local h = hit()
	h.draftsman = npc
	h.type = hit.wound
	h.direction = utils.vector_copy_by_val(p1):sub(p2)
	h.bone = p[1]
	h.power = p[2]
	h.impulse = p[3]
	npc:hit(h)
end


function hit_npc_from_actor(actor, npc, p)
	local h = hit()
	local sid = nil
	h.draftsman = actor
	h.type = hit.wound

	if p and p[1] then
			sid = tonumber(p[1])
			if sid then
					sid = level_object_by_sid(sid)
					if sid then
							h.direction = actor:position():sub(sid:position())
					end
			end
			if not sid then
			h.direction = actor:position():sub(npc:position())
		end
	else
		sid = npc
	end

	h:bone("bip01_spine")
	h.power = 0.001
	h.impulse = 0.001
	sid:hit(h)
end

function hit_actor(actor, npc, p)
	local h = hit()
	h.direction = vector():set(0,0,0)
	h.draftsman = actor
	h.type = hit.shock
	h:bone("bip01_spine")
	h.power = (p and p[1] and tonumber(p[1])) or 0.001
	h.impulse = 0.001
	actor:hit(h)
end

function restore_health(actor, npc)
	--printf("HEALTH RESTORE")
	npc.health = 1
end

function sniper_fire_mode(actor, npc, p)
	if p[1] == "true" then
		--printf("SNIPER FIRE MODE ON")
		npc:sniper_fire_mode(true)
	else
		--printf("SNIPER FIRE MODE OFF")
		npc:sniper_fire_mode(false)
	end
end

function kill_npc(actor, npc, p)
	--local npc_obj
	--if npc.id ~= nil then
	--  alife():release(npc, true)
	--else
	if p and p[1] then
				npc = level_object_by_sid(tonumber(p[1]))
	end
	if npc ~= nil and npc:alive() then
		npc:kill(npc)
	end
	--end



	--[[printf("HEALTH ==== > 0 [%s][%s]", npc:name(), npc.health)

	local h = hit()
	h.power = 1000
	h.direction = npc:direction()
	h.draftsman = npc
	h.impulse = 1
	h.type = hit.wound
	npc:hit(h)

	printf("HEALTH == [%s]", npc.health)]]--

end


--'------------------------------------------------------
--' Проигрышь звуков
--'------------------------------------------------------
--' играть звук в голове актёра
function play_snd(actor, npc, p)
end

--' играть звук от указанного объекта
function play_snd_from_obj(actor, npc, p)
end

--' играть звук от указанного объекта
function play_snd_now(actor, npc, p)
end



-- прибавить к указанному счётчику актёра 1
function inc_counter(actor, npc, p)
	if p[1] then
		local inc_value = p[2] or 1
		local new_value = xr_logic.pstor_retrieve(actor, p[1], 0) + inc_value
		--printf( "inc_counter '%s'  to value [%s]", p[1], tostring(new_value) )
		xr_logic.pstor_store(actor, p[1], new_value)
	end
end

function dec_counter(actor, npc, p)
	if p[1] then
		--printf( "dec_counter '%s'", p[1] )
		xr_logic.pstor_store(actor, p[1], xr_logic.pstor_retrieve(actor, p[1], 0) - 1)
	end
end

function set_counter(actor, npc, p)
	if p[1] and p[2] then
		--printf( "set_counter '%s'", p[1] )
		xr_logic.pstor_store(actor, p[1], p[2])
	end
end


------------------------------------------------------------------------------------------------------------------------
-- постпроцесс и влияние удара в морду
function actor_punch(npc)
	if db.actor:position():distance_to_sqr(npc:position()) > 4 then
		return
	end

	set_inactivate_input_time(30)
	level.add_cam_effector("camera_effects\\fusker.anm", 999, false, "")

	local active_slot = db.actor:active_slot()
	if active_slot ~= 1 and
		 active_slot ~= 2
	then
		return
	end

	local active_item = db.actor:active_item()
	if active_item then
		db.actor:drop_item(active_item)
	end
end

-- забывание обиды
function clearAbuse(npc)
	printf("CLEAR_ABUSE")
	xr_abuse.clear_abuse(npc)
end


---Выключение динамической лампочки (hanging_lamp)
function turn_off(actor, npc, p)
	local obj = level_object_by_sid(p[1])

	if not obj then
		abort("TURN_OFF [%s]. Target object does not exist", npc:name())
		return
	end
	obj:get_hanging_lamp():turn_off()
end
function turn_off_object(actor, npc)
	npc:get_hanging_lamp():turn_off()
end

---Включение динамической лампочки (hanging_lamp)
function turn_on(actor, npc, p)
	local obj = level_object_by_sid(p[1])

	if not obj then
		abort("TURN_ON [%s]. Target object does not exist", npc:name())
		return
	end
	obj:get_hanging_lamp():turn_on()
end

---Включение и запуск динамической лампочки (hanging_lamp)
function turn_on_and_force(actor, npc, p)
	local obj = level_object_by_sid(p[1])

	if not obj then
		abort("TURN_ON_AND_FORCE. Target object does not exist")
		return
	end
	if p[2] == nil then p[2] = 55 end
	if p[3] == nil then p[3] = 14000 end
	obj:set_const_force(vector():set(0,1,0), p[2], p[3])
	obj:start_particles("weapons\\light_signal", "link")
	obj:get_hanging_lamp():turn_on()
end

---Выключение динамической лампочки и партиклов (hanging_lamp)
function turn_off_and_force(actor, npc, p)
	local obj = level_object_by_sid(p[1])

	if not obj then
		abort("TURN_OFF [%s]. Target object does not exist", npc:name())
		return
	end
	obj:stop_particles("weapons\\light_signal", "link")
	obj:get_hanging_lamp():turn_off()
end


function turn_on_object(actor, npc)
	npc:get_hanging_lamp():turn_on()
end

function turn_off_object(actor, npc)
	npc:get_hanging_lamp():turn_off()
end


-- Вызов этой функции отключит обработчик [combat] боя для персонажа.
-- Используется в случаях, когда все необходимые действия, такие как переключение на другую секцию,
-- уже выполнены, и повторно выполнять их во время боя нельзя (а условия секции [combat] проверяются на каждом
-- апдейте, когда персонаж в бою, если, конечно, не отключены вызовом этой функции).
function disable_combat_handler(actor, npc)
	if db.storage[npc:id()].combat then
		db.storage[npc:id()].combat.enabled = false
	end

	if db.storage[npc:id()].mob_combat then
		db.storage[npc:id()].mob_combat.enabled = false
	end
end

-- Вызов этой функции отключит обработчик [combat_ignore] перехвата боя для персонажа.
function disable_combat_ignore_handler(actor, npc)
	if db.storage[npc:id()].combat_ignore then
		db.storage[npc:id()].combat_ignore.enabled = false
	end
end

-------------------------------------------------------------------------------------
-- Функции для работы с вертолётами
-------------------------------------------------------------------------------------
function heli_set_enemy_actor(actor, npc)
	local st = db.storage[npc:id()]
	if not st.combat.enemy_id and actor:alive() then
		st.combat.enemy_id = actor:id()

		heli_snd.play_snd( st, heli_snd.snd_see_enemy, 1 )
	end
end

function heli_set_enemy(actor, npc, p)
	local st  = db.storage[npc:id()]
	local obj = level_object_by_sid( p[1] )

	if not st.combat.enemy_id and obj:alive() then
		st.combat.enemy_id = obj:id()

		heli_snd.play_snd( st, heli_snd.snd_see_enemy, 1 )
	end
end

function heli_clear_enemy(actor, npc)
		db.storage[npc:id()].combat:forget_enemy()
end

function heli_start_flame(actor, npc)
	bind_heli.heli_start_flame( npc )
end

function heli_die(actor, npc)
	bind_heli.heli_die( npc )
end


--'-----------------------------------------------------------------------------------
--' Функции для работы с погодными эффектами
--'-----------------------------------------------------------------------------------
function update_weather(actor, npc, p)
	if p and p[1] then
		if p[1] == "true" then
			level_weathers.get_weather_manager():select_weather(true)
		elseif p[1] == "false" then
			level_weathers.get_weather_manager():select_weather(false)
		end
	end
end

function start_small_reject(actor, npc)
		level.set_weather_fx("fx_surge_day_3")
	level.add_pp_effector("vibros_p.ppe", 1974, false)
	this.aes_earthshake(npc)
		--'set_postprocess("scripts\\postprocess1.ltx")
end

function start_full_reject(actor, npc)
		level.set_weather_fx("fx_surge_day_3")
		level.remove_pp_effector(1974)
	level.remove_cam_effector(1975)
		--'level.add_pp_effector("vibros.ppe", 1974, false)
		--'set_postprocess("scripts\\postprocess.ltx")
	--'level.add_pp_effector("snd_shock.ppe", 1974, true)
	level.add_cam_effector("camera_effects\\earthquake.anm", 1975, true, "")

end

function stop_full_reject(actor, npc)
	level.remove_pp_effector(1974)
	level.remove_cam_effector(1975)
	--'level.set_weather_fx("marsh")
end

function run_weather_pp(actor,npc, p)
	local weather_fx = p[1]
	if weather_fx == nil then
		weather_fx = "fx_surge_day_3"
	end

	level.set_weather_fx(weather_fx)
	--'level.add_pp_effector("vibros_p.ppe", 1974, false)
end

function game_disconnect(actor, npc)
	local c = get_console()
	c:execute("disconnect")
	c:execute_deferred("main_menu off")
	c:execute_deferred("hide")
end

function game_credits(actor, npc)
	db.gameover_credits_started = true
	game.start_tutorial("credits_seq")
end

function game_over(actor, npc)
	if db.gameover_credits_started ~= true then
		return
	end
	local c = get_console()
--  c:execute("disconnect")
	printf("main_menu on console command is executed")
	c:execute("main_menu on")
end

function after_credits(actor, npc)
	get_console():execute	("main_menu on")
end

function on_tutor_gameover_stop()
	local c = get_console()
--  c:execute("disconnect")
	printf("main_menu on console command is executed")
	c:execute("main_menu on")
end

function on_tutor_gameover_quickload()
	local c = get_console()
	c:execute("load_last_save")
end


-- для смены работы
function get_stalker_for_new_job(actor, npc, p)
	xr_gulag.find_stalker_for_job(npc,p[1])
end
function switch_to_desired_job(actor, npc, p)
	xr_gulag.switch_to_desired_job(npc)
end

function death_hit(actor, npc, p)
		 local draftsman = level_object_by_sid (p[1])
		 local hitted_obj = (p[2] ~= nil and level_object_by_sid (p[2])) or npc
		 if draftsman == nil or hitted_obj == nil then
					return
		 end
		 local h = hit()
		 h.power = 1000
		 h.direction = hitted_obj:direction()
		 h.draftsman = draftsman
		 h.impulse = 1
		 h.type = hit.wound
		 hitted_obj:hit(h)
end


--'-----------------------------------------------------------------------------------
--' Функции для работы с подспауном
--'-----------------------------------------------------------------------------------
function spawn_object(actor, obj, p)
		--' p[1] - секция кого спаунить
		--' p[2] - имя патрульного пути где спа унить.
		local spawn_sect = p[1]
		if spawn_sect == nil then
				abort("Wrong spawn section for 'spawn_object' function %s. For object %s", tostring(spawn_sect), obj:name())
		end

		local path_name = p[2]
		if path_name == nil then
				abort("Wrong path_name for 'spawn_object' function %s. For object %s", tostring(path_name), obj:name())
		end

		if not level.patrol_path_exists(path_name) then
				abort("Path %s doesnt exist. Function 'spawn_object' for object %s ", tostring(path_name), obj:name())
		end

		local ptr = patrol(path_name)

		local index = p[3] or 0

	local yaw = p[4] or 0

	--' printf("Spawning %s at %s, %s", tostring(p[1]), tostring(p[2]), tostring(p[3]))
	local se_obj = alife():create(spawn_sect,
				ptr:point(index),
								ptr:level_vertex_id(0),
								ptr:game_vertex_id(0))
	if IsStalker( nil, se_obj:clsid()) then
			se_obj:o_torso().yaw      = yaw * math.pi / 180
	end
end

function spawn_object_in(actor, obj, p)
		--' p[1] - секция кого спаунить
		--' p[2] - имя обьекта в который спавнить
		local spawn_sect = p[1]
		if spawn_sect == nil then
				abort("Wrong spawn section for 'spawn_object' function %s. For object %s", tostring(spawn_sect), obj:name())
		end

		local target_name = p[2]
		if target_name == nil then
				abort("Wrong target_name for 'spawn_object_in' function %s. For object %s", tostring(target_name), obj:name())
		end
	local box = alife():object(target_name)
	if(box==nil) then
				abort("There is no such object %s", target_name)
	end
	local obj = alife():create(spawn_sect,vector(),0,0,box.id)
end


function spawn_npc_in_zone(actor, obj, p)
		--' p[1] - секция кого спаунить
		--' p[2] - имя зоны в которой спаунить.
		local spawn_sect = p[1]
		if spawn_sect == nil then
				abort("Wrong spawn section for 'spawn_object' function %s. For object %s", tostring(spawn_sect), obj:name())
		end
		local zone_name = p[2]
		if zone_name == nil then
				abort("Wrong zone_name for 'spawn_object' function %s. For object %s", tostring(zone_name), obj:name())
		end
		if db.zone_by_name[zone_name] == nil then
				abort("Zone %s doesnt exist. Function 'spawn_object' for object %s ", tostring(zone_name), obj:name())
		end
		local zone = db.zone_by_name[zone_name]

		--' printf("Spawning %s at %s, %s", tostring(p[1]), tostring(p[2]), tostring(p[3]))
	local spawned_obj = alife():create( spawn_sect,
										zone:position(),
										zone:level_vertex_id(),
										zone:game_vertex_id())
	spawned_obj.sim_forced_online = true
	spawned_obj.squad = 1 or p[3]
		db.script_ids[spawned_obj.id] = zone_name
end

function destroy_object(actor, obj, p)

	local sobj
	if p == nil then

		sobj = alife():object(obj:id())
	else
		if p[1] == nil then
			abort("Wrong parameters in destroy_object function")
		end
			local sid = tonumber(p[1])
		if sid then

			sobj = alife():story_object(sid)
			if sobj == nil then
				abort("Item with story_id %s doesnt exist", tostring(sid))
			end
			else

			local target_position, target_id, target_init = xr_remark.initialize_gulag_target(obj, p[1]..","..p[2])
			sobj = alife():object(target_id)
			end
	end

	if sobj == nil then

		return
	end

	if sobj.squad_id == nil then
		printf("releasing object ["..sobj:name().."]")
			alife():release(sobj, true)
		else

			sim_board.get_sim_board().squads[sobj.squad_id]:remove_npc(sobj.id)
		end
end

function give_actor(actor, npc, p)
	for k,v in pairs(p) do
		alife():create(v,
								db.actor:position(),
				db.actor:level_vertex_id(),
				db.actor:game_vertex_id(),
				db.actor:id())
	end
end

function activate_weapon_slot(actor, npc, p)
		db.actor:activate_slot(p[1])
end

-- Функции для управления мостом.

function bridge_down()
	db.bridge_by_name["red_bridge"]:anim_forward()
end
function bridge_up()
	db.bridge_by_name["red_bridge"]:anim_backward()
end
function bridge_stop()
	db.bridge_by_name["red_bridge"]:anim_stop()
end

function anim_obj_down(actor, npc, p)
	if p[1] ~= nil then
		db.anim_obj_by_name[p[1]]:anim_forward()
	end
end
function anim_obj_up(actor, npc, p)
	if p[1] ~= nil then
		db.anim_obj_by_name[p[1]]:anim_backward()
	end
end
function anim_obj_stop(actor, npc, p)
	if p[1] ~= nil then
		db.anim_obj_by_name[p[1]]:anim_stop()
	end
end

-- Функции для работы с огненными зонами.

function turn_on_fire_zone(actor, npc, p)
	bind_campfire.fire_zones_table[p[1]]:turn_on()
end

function turn_off_fire_zone(actor, npc, p)
	bind_campfire.fire_zones_table[p[1]]:turn_off()
end

--'-----------------------------------------------------------------------------------
--' Функции для отыгрывания звука
--'-----------------------------------------------------------------------------------
function play_sound(actor, obj, p)
		local theme = p[1]
		local faction = p[2]
		local point = sim_board.get_sim_board().smarts_by_names[p[3]]
		if point ~= nil then
			point = point.id
	elseif p[3]~=nil then
		point = p[3]
		end
		xr_sound.set_sound_play(obj:id(), theme, faction, point)
end

function stop_sound(actor, npc)
	xr_sound.stop_sounds_by_id(npc:id())
end

function play_sound_looped(actor, obj, p)
		local theme = p[1]
		xr_sound.play_sound_looped(obj:id(), theme)
end

function stop_sound_looped(actor, obj)
		xr_sound.stop_sound_looped(obj:id())
end

function barrel_explode (actor , npc , p)
	local expl_obj = level_object_by_sid (p[1])
	if expl_obj ~= nil then
		expl_obj:explode(0)
	end
end
-- УДАЛИТЬ    для выставки!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function start_katacomb_empty ()
		local console = get_console()
	console:execute("load katacomb_empty")
end



--'-----------------------------------------------------------------------------------
--' Alife support
--'-----------------------------------------------------------------------------------
function start_sim(actor, obj)
	sim_board.get_sim_board():start_sim()
end

function stop_sim(actor, obj)
	sim_board.get_sim_board():stop_sim()
end

function update_faction_brain(actor, obj, p)
	if p[1] == nil then
		abort("Wrong parameters update_faction_brain")
	end
	local board = sim_board.get_sim_board()
	local player = board.players[p[1]]
	if player == nil then
		abort("Can't find player %s", tostring(p[1]))
	end
	player:faction_brain_update()
end

function create_squad(actor, obj, p)
	if obj ~= nil then
		printf("pl:creating_squad from obj [%s] in section [%s]", tostring(obj:name()), tostring(db.storage[obj:id()].active_section))
	end
	local squad_id = p[1]
	if squad_id == nil then
		abort("Wrong squad identificator [NIL] in create_squad function")
	end
	local smart_name = p[2]
	if smart_name == nil then
		abort("Wrong smart name [NIL] in create_squad function")
	end

	local ltx = sim_board.squad_ltx

	if not ltx:section_exist(squad_id) then
		abort("Wrong squad identificator [%s]. Squad descr doesnt exist.", tostring(squad_id))
	end

	local player_name = utils.cfg_get_string(ltx, squad_id, "faction", self, true, "")

	local board = sim_board.get_sim_board()
	local player = board.players[player_name]
	if player == nil then
		abort("Wrong player_name [%s] for squad [%s]", tostring(player_name), tostring(squad_id))
	end
	local smart = board.smarts_by_names[smart_name]
	if smart == nil then
		abort("Wrong smart_name [%s] for [%s] faction in create_squad function", tostring(smart_name), tostring(player_name))
	end
	--!!!!!!!!!!! Зыс из затычка против вылета, если кто-то пытается спаунить отряд с комьюнити отличным от того которым занят смарт!!!!!!
	if smart.player_name ~= player_name and smart.player_name ~= "none" then
	return
	end

	local squad
	local is_autogenerated_id = utils.cfg_get_bool(ltx, squad_id, "auto_id", self, false, false)

	if is_autogenerated_id then
		squad = board:create_squad(player.player_name, sim_squad_scripted.sim_squad_scripted, smart, nil, squad_id)
	else
		squad = board:create_squad(player.player_name, sim_squad_scripted.sim_squad_scripted, smart, squad_id)
	end

	board:enter_smart(squad, smart.id)

	for k,v in pairs(squad.squad_npc) do
		local obj = alife():object(k)
		board:setup_squad_and_group(obj)
	end

	squad:update()
end

function remove_squad(actor, obj, p)
	local squad_id = p[1]
	if squad_id == nil then
		abort("Wrong squad identificator [NIL] in remove_squad function")
	end

	local board = sim_board.get_sim_board()

	local squad = board.squads[squad_id]
	if squad == nil then
		assert("Wrong squad identificator [%s]. squad doesnt exist", tostring(squad_id))
		return
	end
	board:exit_smart(squad, squad.smart)
	board:remove_squad(squad)
end

function kill_squad(actor, obj, p)
	local squad_id = p[1]
	if squad_id == nil then
		abort("Wrong squad identificator [NIL] in kill_squad function")
	end
	local board = sim_board.get_sim_board()
	local squad = board.squads[squad_id]
	if squad == nil then
		return
	end
	for k,v in pairs(squad.squad_npc) do
		local cl_obj = db.storage[k] and db.storage[k].object
		if cl_obj == nil then
			alife():object(k).health = 0
		else
			cl_obj:kill(cl_obj)
		end
	end
end

function update_squad(actor, obj, p)
		local squad_id = p[1]
		if squad_id == nil then
			abort("Wrong squad identificator [NIL] in remove_squad function")
		end

		local board = sim_board.get_sim_board()

		local squad = board.squads[squad_id]
		if squad == nil then
			assert("Wrong squad identificator [%s]. squad doesnt exist", tostring(squad_id))
			return
	end
	squad:update()
end

function clear_smart_terrain(actor, obj, p)
	local smart_name = p[1]
	if smart_name == nil then
		abort("Wrong squad identificator [NIL] in clear_smart_terrain function")
	end

	local board = sim_board.get_sim_board()
	local smart = board.smarts_by_names[smart_name]

	for k,v in pairs(board.smarts[smart.id].squads) do
		board:exit_smart(v, smart)
		board:remove_squad(v)
	end
end



--' Запрос на установку текущей атаке стейта.
function request_current_squad_stage(actor, obj, p)
	if p[1] == nil then
		abort("Wrong parameters")
	end
	local stage = p[1]

	--' Берем сквад объекта
	local squad = db.storage[obj:id()].squad_obj
	if squad == nil then
		return false
	end

	local current_action = squad.current_action
	if current_action == nil or current_action.name ~= "attack_point" then
		return false
	end

	local smrt = sim_board.get_sim_board().smarts[current_action.dest_smrt_id].smrt
	smrt.combat_manager:request_squad_stage(squad, stage)
end


function set_actor_faction(actor, obj, p)
	if p[1] == nil then
		abort("Wrong parameters")
	end
	sim_board.get_sim_board():set_actor_community(p[1])
end



--'-----------------------------------------------------------------------------------
--' Quest support
--'-----------------------------------------------------------------------------------
function give_task(actor, obj, p)
	if p[1] == nil then
		abort("No parameter in give_task function.")
	end
	task_manager.get_task_manager():give_task(p[1])
end
function give_inited_task(actor, obj, p)
	local task_type = p[1]
	local target_name = p[2]
	local faction_name = p[3]

	if task_type == nil or target_name == nil or faction_name == nil then
		abort("Wrong parameters")
	end

	local tm = task_manager.get_task_manager()
	local target_obj = nil
	if task_type == "storyline" then
		target_obj = target_name
	elseif task_type == "eliminate_smart" then
		target_obj = sim_board.get_sim_board().smarts_by_names[target_name]
	elseif task_type == "capture_smart" then
		target_obj = sim_board.get_sim_board().smarts_by_names[target_name]
	elseif task_type == "defend_smart" then
		target_obj = sim_board.get_sim_board().smarts_by_names[target_name]
	elseif task_type == "eliminate_squad" then
		target_obj = sim_board.get_sim_board().squads[target_name]
	end

	local task = tm:select_task(task_type, target_obj, faction_name)
	task:give_task(faction_name)
	printf("GET INITED TASK type[%s], target[%s]", task_type, target_name)
end
-- Функции для работы с отношениями

function actor_friend(actor, npc)
	printf("_bp: xr_effects: actor_friend(): npc='%s': time=%d", npc:name(), time_global())
	npc:set_relation(game_object.friend, actor)
end

function actor_neutral(actor, npc)
	npc:set_relation(game_object.neutral, actor)
end

function actor_enemy(actor, npc)
	npc:set_relation(game_object.enemy, actor)
end

function set_gulag_enemy_actor( actor, npc, p )
	if p[1] then
		xr_gulag.setGulagEnemy(p[1], actor)
	end
end

function set_gulag_neutral_actor( actor, npc, p )
	if p[1] then
		xr_gulag.setGulagNeutral(p[1], actor)
	end
end

function set_gulag_relation_actor(actor, npc, p)
	if(p[1]) and (p[2]) then
		game_relations.set_gulag_relation_actor(p[1], p[2])
	end
end

function set_squad_neutral_to_actor( actor, npc, p)
	local squad_id = p[1]
	local sim_board = sim_board.get_sim_board()
	local squad = sim_board.squads[squad_id]

	if squad == nil then
		abort("There is no squad with id[%s]", tostring(squad_id))
		return
	end

	for k,v in pairs(squad.squad_npc) do
		local npc_obj = db.storage[k] and db.storage[k].object
		if npc_obj ~= nil then
			npc_obj:set_relation(game_object.neutral, actor)
		end
	end

end

function set_friends(actor, npc, p)
		local npc1
	for i, v in pairs(p) do
		npc1 = level_object_by_sid(v)
		if npc1 and npc1:alive() then
			--printf("_bp: %d:set_friends(%d)", npc:id(), npc1:id())
			npc:set_relation(game_object.friend, npc1)
			npc1:set_relation(game_object.friend, npc)
		end
	end
end

function set_enemies(actor, npc, p)
		local npc1
	for i, v in pairs(p) do
		--printf("_bp: set_enemies(%d)", v)
		npc1 = level_object_by_sid(v)
		if npc1 and npc1:alive() then
			npc:set_relation(game_object.enemy, npc1)
			npc1:set_relation(game_object.enemy, npc)
		end
	end
end

function set_factions_community(actor, npc, p)
	if(p[1]~=nil) and (p[2]~=nil) and (p[3]~=nil) then
		game_relations.set_factions_community(p[1], p[2], p[3])
	end
end

function set_npc_sympathy(actor, npc, p)
	if(p[1]~=nil) then
		game_relations.set_npc_sympathy(npc, p[1])
	end
end

function set_squad_goodwill(actor, npc, p)
	if(p[1]~=nil) and (p[2]~=nil) then
		game_relations.set_squad_goodwill(p[1], p[2])
	end
end

function set_squad_goodwill_to_npc(actor, npc, p)
	if(p[1]~=nil) and (p[2]~=nil) then
		game_relations.set_squad_goodwill_to_npc(npc, p[1], p[2])
	end
end

function set_squad_community_goodwill(actor, npc, p)
	if(p[1]~=nil) and (p[2]~=nil) and (p[3]~=nil) then
		game_relations.set_squad_community_goodwill(p[1], p[2], p[3])
	end
end

function run_cf(cf_name)
	local motion = "camera_effects\\" .. cf_name.. ".anm"
	level.add_cam_effector2(motion, 123, false, "")
end
function purge_arena_items(actor, npc, name)
	printf("purging arena items [%s]", name[1])
	xr_zones.purge_arena_items(name[1])
end



function add_custom_static(actor, npc, p)
	if p[1] ~= nil and p[2] ~= nil then
		get_hud():AddCustomStatic(p[1], true)
		get_hud():GetCustomStatic(p[1]):wnd():SetTextST(p[2])
	else
		abort("Invalid parameters in function add_custom_static!!!")
	end
end

function remove_custom_static(actor, npc, p)
	if p[1] ~= nil then
		get_hud():RemoveCustomStatic(p[1])
	else
		abort("Invalid parameters in function remove_custom_static!!!")
	end
end

function kill_actor(actor, npc)
--  xr_effects.disable_ui_elements(actor, npc, {"all"})
--  level.add_pp_effector("black.ppe", 60508, true)
--  run_string xr_effects.kill_actor()
	db.actor:kill(db.actor)
end

-----------------------------------------------------------------------
--  Treasures support
-----------------------------------------------------------------------
function give_treasure (actor, npc, p)
	if p == nil then abort("Required parameter is [NIL]") end
	for k,v in pairs(p) do
		treasure_manager.give_treasure(v)
	end
end

function quit()
	printf("camera end!!!")
	get_console():execute("quit")
end




-----------------------------------------------------------------------
--  Functions for ARENA
-----------------------------------------------------------------------
function arena_after_fight()
	db.actor:disable_info_portion("arena_first_battle_begin")
	level.add_pp_effector("agr_u_fade.ppe", 1974, false)
	disable_ui()

end
function arena_after_arena()
	get_console():execute("load arena")
end

function arena_camera_begin()
	db.actor:give_info_portion("arena_camera_begin")
	level.add_pp_effector("blink.ppe", 1974, false)
	get_console():execute("r2_dof -0.250000,1.400000,200.000000")

end
function dof_change ()
	get_console():execute("r2_dof 0.1,0.2,0.3")
	level.hide_indicators()
end

local function release_object_item(release_item)
	 alife():release(alife():object(release_item:id()), true)
end

local arena_items =
{
	[1] = {"wpn_sig550","wpn_beretta","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","medkit","medkit","medkit"},
	[2] = {"wpn_sig550","wpn_beretta","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","medkit","medkit","medkit",
			"ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","grenade_f1","grenade_f1","grenade_f1","medkit"},
	[3] = {"wpn_sig550","wpn_beretta","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","medkit","medkit","medkit",
			"ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","grenade_f1","grenade_f1","grenade_f1","medkit"},
	[4] = {"wpn_sig550","wpn_beretta","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","medkit","medkit","medkit",
			"ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","grenade_f1","grenade_f1","grenade_f1","medkit"},
	[5] = {"wpn_sig550","wpn_beretta","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","medkit","medkit","medkit",
		"ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","ammo_9x19_fmj","ammo_5.56x45_ss190","grenade_f1","grenade_f1","grenade_f1","medkit"}
}

function release_actor_inventory1(actor, npc)
		actor:inventory_for_each(release_object_item)
	for k,v in pairs(arena_items[1]) do
			alife():create(v, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), db.actor:id())
	end
end

function release_actor_inventory2(actor, npc)
		actor:inventory_for_each(release_object_item)
	for k,v in pairs(arena_items[2]) do
		alife():create(v, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), db.actor:id())
	end
end

function release_actor_inventory3(actor, npc)
		actor:inventory_for_each(release_object_item)
	for k,v in pairs(arena_items[3]) do
		alife():create(v, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), db.actor:id())
	end
end

function release_actor_inventory4(actor, npc)
		actor:inventory_for_each(release_object_item)
	for k,v in pairs(arena_items[4]) do
		alife():create(v, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), db.actor:id())
	end
end

function release_actor_inventory5(actor, npc)
		actor:inventory_for_each(release_object_item)
	for k,v in pairs(arena_items[5]) do
		alife():create(v, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), db.actor:id())
	end
end

local particles_table = {
						[1] = {particle = particles_object("anomaly2\\teleport_out_00"), sound = sound_object("anomaly\\teleport_incoming")},
						[2] = {particle = particles_object("anomaly2\\teleport_out_00"), sound = sound_object("anomaly\\teleport_incoming")},
						[3] = {particle = particles_object("anomaly2\\teleport_out_00"), sound = sound_object("anomaly\\teleport_incoming")},
						[4] = {particle = particles_object("anomaly2\\teleport_out_00"), sound = sound_object("anomaly\\teleport_incoming")},
						[5] = {particle = particles_object("anomaly2\\teleport_out_00"), sound = sound_object("anomaly\\teleport_incoming")},
						}
function stc_stop_particle_sounds()
	for i=1,5 do
		if particles_table[i].sound:playing() then
			particles_table[i].sound:stop()
		end
	end
end
function add_strelok_health_bar(actor, npc)
	local strelok = level_object_by_sid(1400)
	xr_motivator.cs_strelok_health(strelok)
end
function stc_activate_weapon(actor, npc, p)
	local object = actor:object( p[1] )
	if object ~= nil then
		actor:make_item_active(object)
	end
end
function stc_strelok_particle(actor, npc)
	--level_object_by_sid(1400):start_particles("monsters\\polter_idle","bip01_head")
end

function stc_create_some_csky_stalkers(actor, npc, p)
local patrol_point = patrol(p[1])
	for i = 1,5 do
		local rnd_point = ((patrol_point:count() == 1) and 1) or math.random(0,patrol_point:count() - 1)

		local obj = alife():create( p[2],
						patrol_point:point(rnd_point),
						patrol_point:level_vertex_id(rnd_point),
						patrol_point:game_vertex_id(rnd_point))
		obj.sim_forced_online = true
	end
end

function stc_create_some_monolith_stalkers(actor, npc, p)
	local patrol_path = patrol(p[1])
	local used_points = {}
	for i = 1,patrol_path:count() do
		used_points[i] = i - 1
	end
	for i = 1,p[3] do
		local rnd_point = math.random(1,#used_points)
		local patrol_point = used_points[rnd_point]
		particles_table[i].particle :play_at_pos(patrol_path:point(patrol_point))
		particles_table[i].sound  :play_at_pos(db.actor, patrol_path:point(patrol_point), 0, sound_object.s3d)
		local obj = alife():create( p[2],
						patrol_path:point(patrol_point),
						patrol_path:level_vertex_id(patrol_point),
						patrol_path:game_vertex_id(patrol_point))
		obj.sim_forced_online = true
		obj.squad = 1 or p[4]
		printf("patrol_point is %s", patrol_point)
		table.remove(used_points, rnd_point)
		print_table(used_points)
	end
	stc_boom()
end

function stc_change_tsg(actor, npc, p)
	npc:change_team(p[1], p[2], p[3])
end

function stc_surge(actor, npc)
	level.set_weather_fx("fx_surge_day_3_stancia")
	xr_sound.set_sound_play(db.actor:id(), "blowout_begin")
	level.add_cam_effector("camera_effects\\shell_shock.anm", 20080501, false, "")
	level.add_cam_effector("camera_effects\\earthquake_00.anm", 20080501, true, "")
	level.add_pp_effector("snd_shock.ppe", 20080401, false)
	--level.add_pp_effector("psy_antenna.ppe", 20080407, false)
	level.set_pp_effector_factor(20080401, 0, 1)
end

function stc_boom(actor, npc, p)
	if p and p[1] ~= nil then
		xr_sound.set_sound_play(db.actor:id(), p[1])
	else
		xr_sound.set_sound_play(db.actor:id(), "blowout_begin")
	end
	level.add_cam_effector("camera_effects\\shell_shock.anm", 20080501, false, "")
	level.add_cam_effector("camera_effects\\earthquake_00.anm", 203450545, false, "")
	level.add_pp_effector("snd_shock.ppe", 20080401, false)
	level.set_pp_effector_factor(20080401, 0, 1)
end

function exit_game(actor, npc)
	get_console():execute("quit")
end

function activate_surge(actor, npc, p)
	local time = tonumber(p[1])
	if time~=nil then
		xr_surge_hide.activate_surge(time)
	end
end

function start_surge_on_stancia_2(actor, npc, p)
	local fx = (p and p[1]) or "fx_surge_day_3_stancia"
	level.set_weather_fx(fx)
	xr_sound.set_sound_play(db.actor:id(), "blowout_begin")
	level.add_cam_effector("camera_effects\\earthquake.anm", 203450545, false, "")
	level.add_cam_effector("camera_effects\\shell_shock.anm", 20080701, false, "")
	level.add_pp_effector("snd_shock.ppe", 20080702, false)
	level.set_pp_effector_factor(20080702, 0, 1)
end

function continue_surge_on_stancia_2(actor, npc)
	xr_sound.play_sound_looped(db.actor:id(), "blowout_rumble")
	level.add_pp_effector("blink.ppe", 20080703, false)
	level.add_pp_effector("snd_shock.ppe", 20080704, true)
	level.set_pp_effector_factor(20080704, 0, 10)
	level.add_cam_effector("camera_effects\\earthquake.anm", 20080705, true, "")
end

function enable_level_changer(actor, npc, p)
	if(p[1]~=nil) then
        local obj = level_object_by_sid(tonumber(p[1]))
        if(obj) then
			if db.storage[obj:id()] and db.storage[obj:id()].s_obj then
	            db.storage[obj:id()].s_obj.enabled = true
    	        db.storage[obj:id()].s_obj.hint = "level_changer_invitation"
			else
				return
			end
            obj:enable_level_changer(true)
            level_tasks.add_lchanger_location()
            obj:set_level_changer_invitation("level_changer_invitation")
		end
	end
end

function disable_level_changer(actor, npc, p)
	if(p[1]~=nil) then
        local obj = level_object_by_sid(tonumber(p[1]))
        if(obj) then
			if not(db.storage[obj:id()] and db.storage[obj:id()].s_obj) then
				return
			end
            obj:enable_level_changer(false)
            level_tasks.del_lchanger_mapspot(tonumber(p[1]))
			db.storage[obj:id()].s_obj.enabled = false
            if(p[2]==nil) then
                obj:set_level_changer_invitation("level_changer_disabled")
				db.storage[obj:id()].s_obj.hint = "level_changer_disabled"
            else
                obj:set_level_changer_invitation(p[2])
				db.storage[obj:id()].s_obj.hint = p[2]
            end
        end
	end
end

function change_actor_community(actor, npc, p)
	if(p[1]~=nil) then
		db.actor:set_character_community(p[1], 0, 0)
	end
end

function set_faction_community_to_actor(actor, npc, p)
-- run_string xr_effects.change_actor_community(nil,nil,{"actor_dolg"})
	if(p[1]~=nil) and (p[2]~=nil) then
		local rel = 0
		if(p[2]=="enemy") then
			rel = -3000
		elseif(p[2]=="friend") then
			rel = 1000
		end
		db.actor:set_community_goodwill(p[1], rel)
	end
end

function disable_collision(actor, npc)
	npc:wounded(true)
end
function enable_collision(actor, npc)
	npc:wounded(false)
end

function disable_actor_collision(actor, npc)
	actor:wounded(true)
end
function enable_actor_collision(actor, npc)
	actor:wounded(false)
end

function relocate_actor_inventory_to_box(actor, npc, p)
	local function transfer_object_item(item)
		if item:section() ~= "wpn_binoc" and item:section() ~= "wpn_knife" and item:section() ~= "device_torch" then
			db.actor:transfer_item(item, inv_box_1)
		end
	end
	inv_box_1 = level_object_by_sid (p[1])
	actor:inventory_for_each(transfer_object_item)
end


function set_level_faction_community(actor, npc, p)
	if(p[1]~=nil) and (p[2]~= nil) and (p[3]~= nil) then
		local faction = sim_board.get_sim_board().players[p[1]]
		local goodwill = 0
		if(p[3]=="enemy") then
			goodwill = -3000
		elseif(p[3]=="friend") then
			goodwill = 1000
		end
		for k,v in pairs(faction.squads) do
			local squad_level = alife():level_name(game_graph():vertex(alife():object(v.commander_id).m_game_vertex_id):level_id())
			if(squad_level==p[2]) then
				for kk,vv in pairs(v.squad_npc) do
					local npc = alife():object(vv)
					local tbl = game_relations.temp_goodwill_table
					if(tbl.communities==nil) then
						tbl.communities = {}
					end
					if(tbl.communities[p[1]]==nil) then
						tbl.communities[p[1]] = {}
					end
					tbl.communities[p[1]][npc.id] = goodwill
					if(db.storage[npc.id]~=nil) then
						game_relations.set_level_faction_community(db.storage[npc.id].object)
					end
				end
			end
		end
	end
end

function make_actor_visible_to_npc(actor,npc,p)
	npc:make_object_visible_somewhen(db.actor)
end

function reset_dialog_end_signal(actor, npc, p)
	local st = db.storage[npc:id()]
	if(st.active_scheme==nil) then
		return
	end
	if(st[st.active_scheme].signals==nil) then
		return
	end
		st[st.active_scheme].signals["dialog_end"] = nil
end

function stop_sr_cutscene(actor,npc,p)
	local obj = db.storage[npc:id()]
	if(obj.active_scheme~=nil) then
		obj[obj.active_scheme].signals["cam_effector_stop"] = true
	end
end

function add_map_spot(actor, npc, p)
	if(p[1]==nil) then
		abort("Story id for add map spot function is not set")
	else
		local story_id = tonumber(p[1])
		local id = id_by_sid(story_id)
		if(id==nil) then
			local obj = alife():object(p[1])
			id = obj and obj.id
		end
		if(id~=nil) then
			if(p[2]==nil) then
				p[2] = "primary_task_location"
			end
			if(p[3]==nil) then
				p[3] = "default"
			end
			if level.map_has_object_spot(id, p[2]) == 0 then
				level.map_add_object_spot_ser(id, p[2], p[3])
			end
		else
			abort("Wrong story id or name [%s] for map spot function", tostring(story_id))
		end
	end
end

function remove_map_spot(actor, npc, p)
	if(p[1]==nil) then
		abort("Story id for add map spot function is not set")
	else
		local story_id = tonumber(p[1])
		local id = id_by_sid(story_id)
		if(id==nil) then
			local obj = alife():object(p[1])
			id = obj and obj.id
		end
		if(id~=nil) then
			if(p[2]==nil) then
				p[2] = "primary_task_location"
			end
			if level.map_has_object_spot(id, p[2]) ~= 0 then
				level.map_remove_object_spot(id, p[2])
			end
		else
			abort("Wrong story id or name [%s] for map spot function", tostring(story_id))
		end
	end
end

function enable_anomaly(actor, npc, p)
	if p[1] == nil then
		abort("Story id for enable_anomaly function is not set")
	end

	local obj = level_object_by_sid(p[1])
	if not obj then
		abort("There is no object with story_id %s for enable_anomaly function", tostring(p[1]))
	end
	obj:enable_anomaly()
end

function disable_anomaly(actor, npc, p)
	if p[1] == nil then
		abort("Story id for disable_anomaly function is not set")
	end

	local obj = level_object_by_sid(p[1])
	if not obj then
		abort("There is no object with story_id %s for disable_anomaly function", tostring(p[1]))
	end
	obj:disable_anomaly()
end

-- Function for Marsh cutscene intro start after intro movie

function start_marsh_intro()
	db.actor:give_info_portion("mar_intro_start")
end

function relocate_money_to(actor, npc, p)
	local num = p[2]
	local victim = level_object_by_sid(p[1])
	dialogs.relocate_money(victim, num, "out")
end

function take_money(actor, npc, p)
	local num = p[1]
	if num == "all" or db.actor:money() < num then
		num = db.actor:money()
	end
	db.actor:give_money(-num)
	game_stats.money_quest_update(-num)
	xr_statistic.inc_spent_money_counter(num)
	news_manager.relocate_money(db.actor, "out", num)
end

function launch_signal_rocket(actor, obj, p)
	if p==nil then
		abort("Signal rocket name is not set!")
	end
	if db.signal_light[p[1]] then
		db.signal_light[p[1]]:launch()
	else
		abort("No such signal rocket: [%s] on level", tostring(p[1]))
	end
end

function reset_faction_goodwill(actor, obj, p)
	if db.actor and p[1] then
		local board = sim_board.get_sim_board()
		local faction = board.players[p[1]]
		if faction then
			db.actor:set_community_goodwill(p[1], 0)
		end
	end
end

function add_cs_text(actor, npc, p)
	if p[1] then
			local hud = get_hud()
			local cs_text = hud:GetCustomStatic("text_on_screen_center")
		if cs_text then
				hud:RemoveCustomStatic("text_on_screen_center")
		end
			hud:AddCustomStatic("text_on_screen_center", true)
		cs_text = hud:GetCustomStatic("text_on_screen_center")
				cs_text:wnd():SetTextST(game.translate_string(p[1]))
	end
end

function del_cs_text(actor, npc, p)
		local hud = get_hud()
		cs_text = hud:GetCustomStatic("text_on_screen_center")
	if cs_text then
			hud:RemoveCustomStatic("text_on_screen_center")
	end
end

function autosave_game()
	get_console():execute("save "..user_name().."_autosave")
end