1896 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			1896 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
 | 
						|
local ini_eff = ini_file("plugins\\actor_effects.ltx")
 | 
						|
local snd_cam = sound_object([[interface\inv_camera]])
 | 
						|
 | 
						|
local device = device
 | 
						|
local string = string
 | 
						|
local math = math
 | 
						|
 | 
						|
local last_slot = 0
 | 
						|
local last_det = 0
 | 
						|
local weapon_hidden = 0
 | 
						|
local cam_dist = 0
 | 
						|
local can_shoot = true
 | 
						|
 | 
						|
local RENDERER = get_console_cmd(0,"renderer")
 | 
						|
local STATIC_LIGHT = 'renderer_r1'
 | 
						|
local IS_R1 = (RENDERER == STATIC_LIGHT)
 | 
						|
local STATIC_VINGETTE = false -- for +R2 - if true, it will draw vingette instead of relying on r2_mask_control
 | 
						|
local STATIC_MASK = true -- For R1 - if true, it will ignore distortion shader and use old mask overlay
 | 
						|
 | 
						|
local detector_was_active = false
 | 
						|
 | 
						|
local allow_states = {
 | 
						|
	[0] = true, -- Idle
 | 
						|
	[4] = true, -- Bore
 | 
						|
	[9] = true  -- Empty
 | 
						|
}
 | 
						|
	
 | 
						|
local opt = {}
 | 
						|
function init_settings()
 | 
						|
	local n = 0
 | 
						|
	local tbl = {}
 | 
						|
	
 | 
						|
	opt.radiation_ppe_threshold = ini_eff:r_float_ex("settings","radiation_ppe_threshold") or 0.45
 | 
						|
	opt.cam_dist = ini_eff:r_float_ex("settings","cam_dist") or 4
 | 
						|
	
 | 
						|
	opt.speed = {}
 | 
						|
	n = ini_eff:line_count("settings_speed")
 | 
						|
	for i=0,n-1 do
 | 
						|
		local result, id, value	= ini_eff:r_line_ex("settings_speed",i,"","")
 | 
						|
		if id and value then
 | 
						|
			opt.speed[id] = tonumber(value)
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	opt.health = {}
 | 
						|
	opt.health.level1 = ini_eff:r_float_ex("settings_health","level1")
 | 
						|
	opt.health.level2 = ini_eff:r_float_ex("settings_health","level2")
 | 
						|
	opt.health.little_delta = ini_eff:r_float_ex("settings_health","little_delta")
 | 
						|
	opt.health.little_ppe = ini_eff:r_string_ex("settings_health","little_ppe")  or "amk_shoot.ppe"
 | 
						|
	opt.health.middle_delta = ini_eff:r_float_ex("settings_health","middle_delta")
 | 
						|
	opt.health.middle_anm = parse_list(ini_eff,"settings_health","middle_anm")
 | 
						|
	opt.health.middle_snd = parse_list(ini_eff,"settings_health","middle_snd")
 | 
						|
	opt.health.huge_delta = ini_eff:r_float_ex("settings_health","huge_delta")
 | 
						|
	opt.health.huge_ppe = ini_eff:r_string_ex("settings_health","huge_ppe") or "total_recall.ppe"
 | 
						|
	opt.health.huge_anm = parse_list(ini_eff,"settings_health","huge_anm")
 | 
						|
	opt.health.huge_snd = parse_list(ini_eff,"settings_health","huge_snd")
 | 
						|
	opt.health.drop_wnp_prob = ini_eff:r_float_ex("settings_health","drop_wnp_prob")
 | 
						|
	opt.health.no_drop_wnp = parse_list(ini_eff,"settings_health","no_drop_wnp",true)
 | 
						|
	opt.health.injury_snd = {}
 | 
						|
	local injury_snd = parse_list(ini_eff,"settings_health","injury_snd")
 | 
						|
	for i=1,#injury_snd do
 | 
						|
		for k,v in string.gmatch(injury_snd[i], "([%w_%-%s%.]+)=([%w_%-%s%.]+)") do
 | 
						|
			opt.health.injury_snd[k] = tonumber(v)
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	opt.helmets = {}
 | 
						|
	n = ini_eff:line_count("settings_helm")
 | 
						|
	for i=0,n-1 do
 | 
						|
		local result, id, value	= ini_eff:r_line_ex("settings_helm",i,"","")
 | 
						|
		if id and value then
 | 
						|
			empty_table(tbl)
 | 
						|
			tbl = parse_list(ini_eff,"settings_helm",id)
 | 
						|
			
 | 
						|
			opt.helmets[id] = {}
 | 
						|
			opt.helmets[id].hud = tbl[1] or "hud_gas"
 | 
						|
			opt.helmets[id].breakable = (tbl[2] == "true") and true or false
 | 
						|
			opt.helmets[id].blurs = tbl[3] and tonumber(tbl[3]) or 2.5
 | 
						|
			opt.helmets[id].respi = (tbl[4] == "true") and true or false
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	opt.helmets_vingette = {}
 | 
						|
	n = ini_eff:line_count("settings_helm_vingette")
 | 
						|
	for i=0,n-1 do
 | 
						|
		local result, id, value	= ini_eff:r_line_ex("settings_helm_vingette",i,"","")
 | 
						|
		if id and value then
 | 
						|
			opt.helmets_vingette[id] = tonumber(value)
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	opt.helmets_reflect = {}
 | 
						|
	n = ini_eff:line_count("settings_helm_reflection")
 | 
						|
	for i=0,n-1 do
 | 
						|
		local result, id, value	= ini_eff:r_line_ex("settings_helm_reflection",i,"","")
 | 
						|
		if id then
 | 
						|
			opt.helmets_reflect[id] = true
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	opt.helmets_con = {}
 | 
						|
	n = ini_eff:line_count("settings_helm_con")
 | 
						|
	for i=0,n-1 do
 | 
						|
		local result, id, value	= ini_eff:r_line_ex("settings_helm_con",i,"","")
 | 
						|
		if id and value then
 | 
						|
			empty_table(tbl)
 | 
						|
			tbl = parse_list(ini_eff,"settings_helm_con",id)
 | 
						|
			
 | 
						|
			opt.helmets_con[id] = {}
 | 
						|
			opt.helmets_con[id].con = tbl[1] and tonumber(tbl[1]) or 0
 | 
						|
			opt.helmets_con[id].hud = tbl[2]
 | 
						|
			opt.helmets_con[id].fx = tbl[3] and tonumber(tbl[3]) or 0
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
function init_main_settings()
 | 
						|
	opt.enable_animations          = ui_options.get("video/player/animations")
 | 
						|
	opt.enable_shoot_effects       = ui_options.get("video/player/shoot_effects")
 | 
						|
	opt.enable_mask_hud            = ui_options.get("video/player/mask_hud")
 | 
						|
	opt.enable_breathing_sound     = ui_options.get("sound/environment/breathing_sound")
 | 
						|
	opt.enable_breathing_fog       = ui_options.get("video/player/breathing_fog")
 | 
						|
	opt.enable_radiation_effect    = ui_options.get("video/player/radiation_effect")
 | 
						|
	opt.enable_blood_splash        = ui_options.get("video/player/blood_splash")
 | 
						|
	opt.enable_bleed_effect        = ui_options.get("video/player/bleed_effect")
 | 
						|
	opt.enable_hit_impact_effect   = true --axr_main.config:r_value("mm_fx_options","enable_hit_impact_effect",1,true)
 | 
						|
	opt.enable_item_swap_animation = ui_options.get("video/player/item_swap_animation")
 | 
						|
	opt.enable_visor_reflection    = ui_options.get("video/player/visor_reflection")
 | 
						|
end
 | 
						|
 | 
						|
local wpn_fx = {}
 | 
						|
local function parse_anims(sec)
 | 
						|
	local sec_p = ini_sys:r_string_ex(sec,"parent_section") or sec
 | 
						|
	
 | 
						|
	if wpn_fx[sec_p] and (sec ~= sec_p) then
 | 
						|
		wpn_fx[sec] = wpn_fx[sec_p]
 | 
						|
		
 | 
						|
	elseif ini_eff:section_exist(sec_p) then
 | 
						|
		local tbl = {}
 | 
						|
		
 | 
						|
		-- parse strength
 | 
						|
		tbl.s = {}
 | 
						|
		local s = ini_eff:r_string_ex(sec_p,"s")
 | 
						|
		local _s = str_explode(s,",")
 | 
						|
		for i=1,#_s do
 | 
						|
			tbl.s[#tbl.s + 1] = tonumber(_s[i])
 | 
						|
		end
 | 
						|
		
 | 
						|
		-- parse strength randomizer
 | 
						|
		tbl.r = ini_eff:r_float_ex(sec_p,"r")
 | 
						|
		
 | 
						|
		-- parse anm
 | 
						|
		tbl.e = {}
 | 
						|
		local e = ini_eff:r_string_ex(sec_p,"e")
 | 
						|
		local _e = str_explode(e,",")
 | 
						|
		for i=1,#_e do
 | 
						|
			local __e = str_explode(_e[i],":")
 | 
						|
			for j=1,#__e do
 | 
						|
				__e[j] = tonumber(__e[j])
 | 
						|
			end
 | 
						|
			tbl.e[#tbl.e + 1] = __e
 | 
						|
		end
 | 
						|
		
 | 
						|
		-- parse ppe
 | 
						|
		tbl.p = {}
 | 
						|
		local p = ini_eff:r_string_ex(sec_p,"p")
 | 
						|
		if p and p ~= "" then
 | 
						|
			for k,v in string.gmatch(p, "([%w_%-%s%.]+)=([%w_%-%s%.]+)") do
 | 
						|
				tbl.p[k] = tonumber(v)
 | 
						|
			end
 | 
						|
		end
 | 
						|
		
 | 
						|
		if (not wpn_fx[sec_p]) and (sec ~= sec_p) then
 | 
						|
			wpn_fx[sec_p] = tbl
 | 
						|
		end
 | 
						|
		
 | 
						|
		wpn_fx[sec] = tbl
 | 
						|
		--utils_data.print_table(wpn_fx[sec])
 | 
						|
		
 | 
						|
	else
 | 
						|
		wpn_fx[sec] = true
 | 
						|
		--printf("not recoil effect for [%s]", sec)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
--------------------------------------------------------------
 | 
						|
-- Trigger
 | 
						|
--------------------------------------------------------------
 | 
						|
local torch_anm_state = 0
 | 
						|
local torch_anm_start = 0
 | 
						|
local torch_anm_time = 0
 | 
						|
local torch_anm_state_dbg = 0
 | 
						|
local mc_anm_state = 0
 | 
						|
local mc_anm_start = 0
 | 
						|
local mc_anm_time_1 = 0
 | 
						|
local mc_anm_time_2 = 0
 | 
						|
local mc_anm_state_dbg = 0
 | 
						|
local torch_anm_sec = "anim_headlamp"
 | 
						|
local mc_anm_sec = "anim_mask_clean"
 | 
						|
local snd_headlamp = sound_object('interface\\inv_torch')
 | 
						|
local snd_gasmask = sound_object('interface\\inv_mask_clean_3')
 | 
						|
local hqt_hide_anm_speed = 3.5 -- Weapon hide speed
 | 
						|
local hqt_grenade_slot = 4
 | 
						|
local hqt_last_slot
 | 
						|
local hqt_state = 0
 | 
						|
local hide_hand_speed = 1.5
 | 
						|
 | 
						|
function allow_animation()
 | 
						|
	return (torch_anm_state == 0 and mc_anm_state == 0 and hqt_state == 0 and game.hud_motion_allowed() and (not game.only_movekeys_allowed()) and actor_menu.get_last_mode() == 0 and (not IsMoveState("mcClimb")))
 | 
						|
end
 | 
						|
 | 
						|
local lowered_anm_kinds = {
 | 
						|
	["w_sniper"] 	= true,
 | 
						|
	["w_rifle"] 	= true,
 | 
						|
	["w_smg"]	    = true,
 | 
						|
	["w_shotgun"] 	= true,
 | 
						|
}
 | 
						|
 | 
						|
local lowered_anm_classes = {
 | 
						|
	["WP_VAL"] 		= true,
 | 
						|
	["WP_AK74"] 	= true,
 | 
						|
	["WP_LR300"] 	= true,
 | 
						|
	["WP_BM16"] 	= true,
 | 
						|
	["WP_SVD"] 		= true,
 | 
						|
	["WP_SVU"]		= true,
 | 
						|
	["WP_GROZA"] 	= true,
 | 
						|
	["WP_ASHTG"] 	= true,
 | 
						|
	["WP_ASHTG"] 	= true,
 | 
						|
	["WP_SHOTG"] 	= true,
 | 
						|
	["WP_RG6"] 		= true,
 | 
						|
	["WP_RPG7"] 	= true,
 | 
						|
	["D_PDA"]		= true,
 | 
						|
}
 | 
						|
 | 
						|
function Hit_TorchToggle()
 | 
						|
 | 
						|
	-- Check if headlamp is equipped. No need for battery check
 | 
						|
	if (not allow_animation()) or (not item_device.can_toggle_torch()) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	local weapon_zoomed = axr_main.weapon_is_zoomed and (not (IsPistol(db.actor:active_item(),nil)) or db.actor:active_detector())
 | 
						|
	local det_active = db.actor:active_detector() or nil
 | 
						|
	local det_hide_time = 0
 | 
						|
	local new_speed = 0
 | 
						|
	local anm_name = "script\\headlamp.anm"
 | 
						|
	local anm_additional_length = 0.45
 | 
						|
	
 | 
						|
	if (db.actor:active_item()) then
 | 
						|
		local itm = db.actor:active_item()
 | 
						|
		local hud = ini_sys:r_string_ex(itm:section(),"hud") or "hud_base"
 | 
						|
		local name = ini_sys:r_string_ex(hud,"gasmask_anm")
 | 
						|
		if (name) then
 | 
						|
			anm_name = name
 | 
						|
		else
 | 
						|
			local kind = ini_sys:r_string_ex(itm:section(),"kind") or nil
 | 
						|
			local class = ini_sys:r_string_ex(itm:section(),"class") or nil
 | 
						|
			if ((kind and lowered_anm_kinds[kind]) or (class and lowered_anm_classes[class])) then
 | 
						|
				anm_name = "script\\lower.anm"
 | 
						|
				anm_additional_length = 0.8
 | 
						|
			end
 | 
						|
		end
 | 
						|
		
 | 
						|
		if (not det_active and weapon_zoomed) then
 | 
						|
			if (get_console():get_bool("wpn_aim_toggle")) then
 | 
						|
				level.press_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
			else
 | 
						|
				level.release_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (det_active) then
 | 
						|
		if (weapon_zoomed) then
 | 
						|
			det_active:switch_state(2)
 | 
						|
			det_hide_time = (det_active:play_hud_motion("anm_zoom_hide_fast", true, 3, 1, 0) / 1000)
 | 
						|
			
 | 
						|
			if (get_console():get_bool("wpn_aim_toggle")) then
 | 
						|
				level.press_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
			else
 | 
						|
				level.release_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
			end
 | 
						|
		else
 | 
						|
			det_hide_time = (det_active:play_hud_motion("anm_hide_fast", true, 3, 2, 0) / 1000) + 0.1
 | 
						|
		end
 | 
						|
		
 | 
						|
		if (det_hide_time == 0) then 
 | 
						|
			det_hide_time = (det_active:play_hud_motion("anm_hide", true, 3, 3.5, 0) / 1000) + 0.1
 | 
						|
		end
 | 
						|
		
 | 
						|
		game.play_hud_anm(anm_name, 0, 0.25, 1, false)
 | 
						|
	end
 | 
						|
	
 | 
						|
	local function torch_toggle_anim_fast()
 | 
						|
		local time_g = time_global()
 | 
						|
		
 | 
						|
		if (torch_anm_state == 1) then
 | 
						|
			game.play_hud_motion(1, torch_anm_sec, "anm_switch", true, 0.75)
 | 
						|
			level.add_cam_effector("camera_effects\\headlamp\\headlamp.anm", 7539, false, "", 0, false)
 | 
						|
			torch_anm_start = time_g
 | 
						|
			torch_anm_state = 2
 | 
						|
			
 | 
						|
		elseif (torch_anm_state == 2) and (time_g > torch_anm_start + torch_anm_time - 350) then
 | 
						|
			snd_headlamp:play(db.actor,0,sound_object.s2d)
 | 
						|
			item_device.toggle_torch()
 | 
						|
			torch_anm_state = 3
 | 
						|
			
 | 
						|
		elseif (torch_anm_state == 3) and (time_g > torch_anm_start + torch_anm_time + 1) then
 | 
						|
			torch_anm_state = 0
 | 
						|
			torch_anm_start = 0
 | 
						|
			torch_anm_state_dbg = 0
 | 
						|
			game.only_allow_movekeys(false)
 | 
						|
			game.set_actor_allow_ladder(true)
 | 
						|
			RemoveTimeEvent(0, "play_torch_toggle")
 | 
						|
		end
 | 
						|
		
 | 
						|
		if DEV_DEBUG and (torch_anm_state_dbg ~= torch_anm_state) then
 | 
						|
			torch_anm_state_dbg = torch_anm_state
 | 
						|
			--printf("- Torch animation | state reached: %s - time: %s", torch_anm_state, time_g)
 | 
						|
		end
 | 
						|
		
 | 
						|
		return false
 | 
						|
	end
 | 
						|
	
 | 
						|
	local function torch_toggle_anim()
 | 
						|
		local time_g = time_global()
 | 
						|
		
 | 
						|
		if (torch_anm_state == 1) then
 | 
						|
			if (det_active) then
 | 
						|
				det_active:switch_state(3)
 | 
						|
				db.actor:force_hide_detector()
 | 
						|
			else
 | 
						|
				game.play_hud_anm(anm_name, 0, 1, 1, false)
 | 
						|
			end
 | 
						|
				
 | 
						|
			game.play_hud_motion(1, mc_anm_sec, "anm_hide_hand", true, hide_hand_speed)
 | 
						|
			new_speed = game.set_hud_anm_time(anm_name, ((torch_anm_time + mc_anm_time_1) / 1000) + anm_additional_length)
 | 
						|
			torch_anm_start = time_g
 | 
						|
			torch_anm_state = 2
 | 
						|
			
 | 
						|
		elseif (torch_anm_state == 2) and (time_g > torch_anm_start + mc_anm_time_1 - 10) then
 | 
						|
			game.play_hud_motion(1, torch_anm_sec, "anm_switch", true, 1)
 | 
						|
			level.add_cam_effector("camera_effects\\headlamp\\headlamp.anm", 7539, false, "", 0, false)
 | 
						|
			torch_anm_state = 3
 | 
						|
			
 | 
						|
		elseif (torch_anm_state == 3) and (time_g > torch_anm_start + mc_anm_time_1 + torch_anm_time - 550) then
 | 
						|
			snd_headlamp:play(db.actor,0,sound_object.s2d)
 | 
						|
			item_device.toggle_torch()
 | 
						|
			torch_anm_state = 4
 | 
						|
			
 | 
						|
		elseif (torch_anm_state == 4) and (time_g > torch_anm_start + mc_anm_time_1 + torch_anm_time + 15) then
 | 
						|
			if (new_speed) then game.play_hud_anm(anm_name, 2, new_speed, 1, false, true) end
 | 
						|
			if (det_active) then db.actor:show_detector(true) end
 | 
						|
			torch_anm_state = 5
 | 
						|
			
 | 
						|
		elseif (torch_anm_state == 5) and (time_g > torch_anm_start + mc_anm_time_1 + torch_anm_time + (anm_additional_length * 1000 + 100)) then
 | 
						|
			torch_anm_state = 0
 | 
						|
			torch_anm_start = 0
 | 
						|
			torch_anm_state_dbg = 0
 | 
						|
			game.only_allow_movekeys(false)
 | 
						|
			game.set_actor_allow_ladder(true)
 | 
						|
			RemoveTimeEvent(0, "play_torch_toggle")
 | 
						|
		end
 | 
						|
		
 | 
						|
		if DEV_DEBUG and (torch_anm_state_dbg ~= torch_anm_state) then
 | 
						|
			torch_anm_state_dbg = torch_anm_state
 | 
						|
			--printf("- Torch animation | state reached: %s - time: %s", torch_anm_state, time_g)
 | 
						|
		end
 | 
						|
		
 | 
						|
		return false
 | 
						|
	end
 | 
						|
	
 | 
						|
	torch_anm_state = 1
 | 
						|
	game.only_allow_movekeys(true)
 | 
						|
	game.set_actor_allow_ladder(false)
 | 
						|
	
 | 
						|
	if (not db.actor:active_item() and not det_active) then
 | 
						|
		CreateTimeEvent(0, "play_torch_toggle", det_hide_time, torch_toggle_anim_fast)
 | 
						|
	else
 | 
						|
		CreateTimeEvent(0, "play_torch_toggle", det_hide_time, torch_toggle_anim)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
function Hit_MaskCleaning()
 | 
						|
	
 | 
						|
	-- Check if mask overlay is ON
 | 
						|
	if (not allow_animation()) or (not is_mask_on()) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	local weapon_zoomed = axr_main.weapon_is_zoomed and (not (IsPistol(db.actor:active_item(),nil)) or db.actor:active_detector())
 | 
						|
	local det_active = db.actor:active_detector() or nil
 | 
						|
	local det_hide_time = 0
 | 
						|
	local new_speed = 0
 | 
						|
	local anm_name = "script\\gasmask.anm"
 | 
						|
	local anm_additional_length = 0.45
 | 
						|
	
 | 
						|
	if (db.actor:active_item()) then
 | 
						|
		local itm = db.actor:active_item()
 | 
						|
		local hud = ini_sys:r_string_ex(itm:section(),"hud") or "hud_base"
 | 
						|
		local name = ini_sys:r_string_ex(hud,"gasmask_anm")
 | 
						|
		if (name) then
 | 
						|
			anm_name = name
 | 
						|
		else
 | 
						|
			local kind = ini_sys:r_string_ex(itm:section(),"kind") or nil
 | 
						|
			local class = ini_sys:r_string_ex(itm:section(),"class") or nil
 | 
						|
			if ((kind and lowered_anm_kinds[kind]) or (class and lowered_anm_classes[class])) then
 | 
						|
				anm_name = "script\\lower.anm"
 | 
						|
				anm_additional_length = 0.75
 | 
						|
			end
 | 
						|
		end
 | 
						|
		
 | 
						|
		if (not det_active and weapon_zoomed) then
 | 
						|
			if (get_console():get_bool("wpn_aim_toggle")) then
 | 
						|
				level.press_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
			else
 | 
						|
				level.release_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (det_active) then
 | 
						|
		if (weapon_zoomed) then
 | 
						|
			det_active:switch_state(2)
 | 
						|
			det_hide_time = (det_active:play_hud_motion("anm_zoom_hide_fast", true, 3, 1, 0) / 1000)
 | 
						|
			
 | 
						|
			if (get_console():get_bool("wpn_aim_toggle")) then
 | 
						|
				level.press_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
			else
 | 
						|
				level.release_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
			end
 | 
						|
		else
 | 
						|
			det_hide_time = (det_active:play_hud_motion("anm_hide_fast", true, 3, 2, 0) / 1000) + 0.1
 | 
						|
		end
 | 
						|
		
 | 
						|
		if (det_hide_time == 0) then 
 | 
						|
			det_hide_time = (det_active:play_hud_motion("anm_hide", true, 3, 3.5, 0) / 1000) + 0.1
 | 
						|
		end
 | 
						|
		
 | 
						|
		game.play_hud_anm(anm_name, 0, 0.25, 1, false)
 | 
						|
	end
 | 
						|
	
 | 
						|
	local function mask_cleaning_anim_fast()
 | 
						|
		local time_g = time_global()
 | 
						|
		
 | 
						|
		if (mc_anm_state == 1) then
 | 
						|
			game.play_hud_motion(1, mc_anm_sec, "anm_wipe", false, 1)
 | 
						|
			snd_gasmask:play(db.actor,0,sound_object.s2d)
 | 
						|
			level.add_cam_effector("camera_effects\\weapon\\gasmask_swipe1.anm", 7538, false, "", 0, false)
 | 
						|
			mc_anm_start = time_g
 | 
						|
			mc_anm_state = 2
 | 
						|
			
 | 
						|
		elseif (mc_anm_state == 2) and (time_g > mc_anm_start + mc_anm_time_2 - 400) then
 | 
						|
			level_environment.droplets_reset()
 | 
						|
			mc_anm_state = 3
 | 
						|
			
 | 
						|
		elseif (mc_anm_state == 3) and (time_g > mc_anm_start + mc_anm_time_2 + 1) then
 | 
						|
			mc_anm_state = 0
 | 
						|
			mc_anm_start = 0
 | 
						|
			mc_anm_state_dbg = 0
 | 
						|
			game.only_allow_movekeys(false)
 | 
						|
			game.set_actor_allow_ladder(true)
 | 
						|
			RemoveTimeEvent(0, "play_mask_cleaning")
 | 
						|
			
 | 
						|
		end
 | 
						|
		
 | 
						|
		if DEV_DEBUG and (mc_anm_state_dbg ~= mc_anm_state) then
 | 
						|
			mc_anm_state_dbg = mc_anm_state
 | 
						|
			--printf("- Gasmask wipe animation | state reached: %s - time: %s", mc_anm_state, time_g)
 | 
						|
		end
 | 
						|
		
 | 
						|
		return false
 | 
						|
	end
 | 
						|
	
 | 
						|
	local function mask_cleaning_anim()
 | 
						|
		local time_g = time_global()
 | 
						|
		
 | 
						|
		if (mc_anm_state == 1) then
 | 
						|
			if (det_active) then
 | 
						|
				det_active:switch_state(3)
 | 
						|
				db.actor:force_hide_detector()
 | 
						|
			else
 | 
						|
				game.play_hud_anm(anm_name, 0, 1, 1, false)
 | 
						|
			end
 | 
						|
			
 | 
						|
			game.play_hud_motion(1, mc_anm_sec, "anm_hide_hand", true, hide_hand_speed)
 | 
						|
			new_speed = game.set_hud_anm_time(anm_name, ((mc_anm_time_1 + mc_anm_time_2) / 1000) + anm_additional_length)
 | 
						|
			mc_anm_start = time_g
 | 
						|
			mc_anm_state = 2
 | 
						|
			
 | 
						|
		elseif (mc_anm_state == 2) and (time_g > mc_anm_start + mc_anm_time_1 - 10) then
 | 
						|
			game.play_hud_motion(1, mc_anm_sec, "anm_wipe", false, 1)
 | 
						|
			snd_gasmask:play(db.actor,0,sound_object.s2d)
 | 
						|
			level.add_cam_effector("camera_effects\\weapon\\gasmask_swipe1.anm", 7538, false, "", 0, false)
 | 
						|
			mc_anm_state = 3
 | 
						|
			
 | 
						|
		elseif (mc_anm_state == 3) and (time_g > mc_anm_start + mc_anm_time_1 + mc_anm_time_2 - 400) then
 | 
						|
			level_environment.droplets_reset()
 | 
						|
			mc_anm_state = 4
 | 
						|
			
 | 
						|
		elseif (mc_anm_state == 4) and (time_g > mc_anm_start + mc_anm_time_1 + mc_anm_time_2 + 15) then
 | 
						|
			if (new_speed) then game.play_hud_anm(anm_name, 2, new_speed, 1, false, true) end
 | 
						|
			if (det_active) then db.actor:show_detector(true) end
 | 
						|
			mc_anm_state = 5
 | 
						|
			
 | 
						|
		elseif (mc_anm_state == 5) and (time_g > mc_anm_start + mc_anm_time_1 + mc_anm_time_2 + (anm_additional_length * 1000 + 100)) then
 | 
						|
			mc_anm_state = 0
 | 
						|
			mc_anm_start = 0
 | 
						|
			mc_anm_state_dbg = 0
 | 
						|
			game.only_allow_movekeys(false)
 | 
						|
			game.set_actor_allow_ladder(true)
 | 
						|
			RemoveTimeEvent(0, "play_mask_cleaning")
 | 
						|
		end
 | 
						|
		
 | 
						|
		if DEV_DEBUG and (mc_anm_state_dbg ~= mc_anm_state) then
 | 
						|
			mc_anm_state_dbg = mc_anm_state
 | 
						|
			--printf("- Gasmask wipe animation | state reached: %s - time: %s", mc_anm_state, time_g)
 | 
						|
		end
 | 
						|
		
 | 
						|
		return false
 | 
						|
	end
 | 
						|
	
 | 
						|
	mc_anm_state = 1
 | 
						|
	game.only_allow_movekeys(true)
 | 
						|
	game.set_actor_allow_ladder(false)
 | 
						|
	
 | 
						|
	if (not db.actor:active_item() and not det_active) then
 | 
						|
		CreateTimeEvent(0, "play_mask_cleaning", det_hide_time, mask_cleaning_anim_fast)
 | 
						|
	else
 | 
						|
		CreateTimeEvent(0, "play_mask_cleaning", det_hide_time, mask_cleaning_anim)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
function Hit_GrenadeQuickthrow() -- Rezy
 | 
						|
	if (not allow_animation())
 | 
						|
	or (not db.actor:item_in_slot(hqt_grenade_slot))
 | 
						|
	or db.actor:get_current_holder() ~= nil
 | 
						|
	then 
 | 
						|
		return 
 | 
						|
	end
 | 
						|
	
 | 
						|
	local weapon_zoomed = axr_main.weapon_is_zoomed and (not (IsPistol(db.actor:active_item(),nil)) or db.actor:active_detector())
 | 
						|
	local firekey = bind_to_dik(key_bindings.kWPN_FIRE)
 | 
						|
	local switch_delay = 0
 | 
						|
	local wpn
 | 
						|
	local det_active = db.actor:active_detector() or nil
 | 
						|
	
 | 
						|
	hqt_last_slot = db.actor:active_slot()
 | 
						|
	
 | 
						|
	if (weapon_zoomed) then
 | 
						|
		if (get_console():get_bool("wpn_aim_toggle")) then
 | 
						|
			level.press_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
		else
 | 
						|
			level.release_action(bind_to_dik(key_bindings.kWPN_ZOOM))
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (hqt_last_slot == hqt_grenade_slot) then
 | 
						|
		level.press_action(firekey)
 | 
						|
		return
 | 
						|
	elseif (hqt_last_slot ~= 0) then
 | 
						|
		wpn = db.actor:active_item()
 | 
						|
		if wpn then
 | 
						|
			local state = wpn:get_state()
 | 
						|
			if (state ~= 0 and state ~= 1 and state ~= 2) then return end
 | 
						|
			switch_delay = (wpn:play_hud_motion("anm_hide", true, 3, hqt_hide_anm_speed, 0) / 1000)
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (det_active) then
 | 
						|
		local det_hide_time = (det_active:play_hud_motion("anm_hide_fast", true, 3, 2, 0) / 1000)
 | 
						|
		
 | 
						|
		if (det_hide_time == 0) then det_hide_time = (det_active:play_hud_motion("anm_hide", true, 3, hqt_hide_anm_speed, 0) / 1000) end
 | 
						|
		
 | 
						|
		if (det_hide_time > switch_delay) then switch_delay = det_hide_time end
 | 
						|
	end
 | 
						|
	
 | 
						|
	local function switch_to_throw()
 | 
						|
		
 | 
						|
		local grn = db.actor:item_in_slot(hqt_grenade_slot)
 | 
						|
		if (not grn) then
 | 
						|
			game.only_allow_movekeys(false)
 | 
						|
			game.set_actor_allow_ladder(true)
 | 
						|
			hqt_state = 0
 | 
						|
			if (db.actor:active_slot() ~= hqt_last_slot) then
 | 
						|
				db.actor:activate_slot(hqt_last_slot)
 | 
						|
			end
 | 
						|
			return true
 | 
						|
		end
 | 
						|
		
 | 
						|
		if hqt_state == 1 then
 | 
						|
			if det_active then 
 | 
						|
				det_active:switch_state(3)
 | 
						|
				db.actor:force_hide_detector()
 | 
						|
			end
 | 
						|
			db.actor:activate_slot(hqt_grenade_slot)
 | 
						|
			if wpn then wpn:switch_state(3) end
 | 
						|
			hqt_state = 2	
 | 
						|
		elseif hqt_state == 2 and db.actor:active_slot() == hqt_grenade_slot then
 | 
						|
			grn:switch_state(0)
 | 
						|
			hqt_state = 3
 | 
						|
		elseif hqt_state == 3 and grn:get_state() == 0 then
 | 
						|
			level.press_action(firekey)
 | 
						|
			hqt_state = 4
 | 
						|
		elseif hqt_state == 4 and (grn:get_state() == 1 or grn:get_state() == 2) then
 | 
						|
			grn:switch_state(3)
 | 
						|
			hqt_state = 5
 | 
						|
		elseif hqt_state == 5 then
 | 
						|
			if (db.actor:active_slot() ~= hqt_last_slot) then
 | 
						|
				db.actor:activate_slot(hqt_last_slot)
 | 
						|
				if grn then grn:switch_state(3) end
 | 
						|
			end
 | 
						|
			
 | 
						|
			if (det_active) then
 | 
						|
				db.actor:show_detector(true)
 | 
						|
				det_active:switch_state(1)
 | 
						|
			end
 | 
						|
			
 | 
						|
			game.only_allow_movekeys(false)
 | 
						|
			game.set_actor_allow_ladder(true)
 | 
						|
			hqt_state = 0
 | 
						|
			return true 
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	hqt_state = 1
 | 
						|
	
 | 
						|
	game.only_allow_movekeys(true)
 | 
						|
	game.set_actor_allow_ladder(false)
 | 
						|
	
 | 
						|
	CreateTimeEvent(0, "switch_to_throw", switch_delay, switch_to_throw)
 | 
						|
end
 | 
						|
 | 
						|
-- This should fix being stuck if a burer attacks you during grenade quickthrow 
 | 
						|
local function burer_on_before_weapon_drop(burer,wpn,flags)
 | 
						|
	if (hqt_state ~= 0) then
 | 
						|
		flags.ret_value = false 
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
--------------------------------------------------------------
 | 
						|
-- Update
 | 
						|
--------------------------------------------------------------
 | 
						|
local swap_last_id = nil
 | 
						|
local swap_last_det_st = nil
 | 
						|
local swap_last_wep_st = nil
 | 
						|
local weapon_classes = {
 | 
						|
	["D_PDA"]		= "low",
 | 
						|
	["II_BOLT"]		= "low",
 | 
						|
	["WP_KNIFE"] 	= "low",
 | 
						|
	["WP_BINOC"] 	= "low",
 | 
						|
	["G_F1"] 		= "low",
 | 
						|
	["G_F1_S"]		= "low",
 | 
						|
	["G_RGD5_S"] 	= "low",
 | 
						|
	["WP_PM"] 		= "low",
 | 
						|
	["WP_HPSA"] 	= "low",
 | 
						|
	["WP_USP45"] 	= "low",
 | 
						|
	["WP_VAL"] 		= "med",
 | 
						|
	["WP_AK74"] 	= "med",
 | 
						|
	["WP_LR300"] 	= "med",
 | 
						|
	["WP_BM16"] 	= "med",
 | 
						|
	["WP_SVD"] 		= "med",
 | 
						|
	["WP_SVU"]		= "med",
 | 
						|
	["WP_GROZA"] 	= "med",
 | 
						|
	["WP_ASHTG"] 	= "med",
 | 
						|
	["WP_ASHTG"] 	= "med",
 | 
						|
	["WP_SHOTG"] 	= "med",
 | 
						|
	["WP_RG6"] 		= "strong",
 | 
						|
	["WP_RPG7"] 	= "strong"
 | 
						|
}
 | 
						|
function Update_ItemSwap(actor)
 | 
						|
	if (not opt.enable_item_swap_animation) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	--
 | 
						|
	local detector = actor:active_detector()
 | 
						|
	if detector then
 | 
						|
		local det_state = detector:get_state()
 | 
						|
		if (not swap_last_det_st) then swap_last_det_st = det_state end
 | 
						|
		if (det_state ~= swap_last_det_st) then
 | 
						|
			if (det_state ==1) or (det_state == 2) then
 | 
						|
				local rand = math.random(1,4)
 | 
						|
				level.add_cam_effector("camera_effects\\switch\\low" .. rand .. ".anm", 23233, false, '', 0, false)
 | 
						|
			end
 | 
						|
			swap_last_det_st = det_state
 | 
						|
		end
 | 
						|
	end
 | 
						|
	--
 | 
						|
	
 | 
						|
	local wpn = actor:active_item()
 | 
						|
	if wpn then
 | 
						|
		local wpn_id = wpn:id()
 | 
						|
		if (not swap_last_id) then swap_last_id = wpn_id end
 | 
						|
		
 | 
						|
		--local se_wpn = alife_object(wpn_id)
 | 
						|
		local wpn_class = ini_sys:r_string(wpn:section(), "class")
 | 
						|
		
 | 
						|
		if weapon_classes[wpn_class] then
 | 
						|
			local effect_type = weapon_classes[wpn_class]
 | 
						|
			local state = wpn:get_state()
 | 
						|
			if not swap_last_wep_st then swap_last_wep_st = state end
 | 
						|
			if state ~= swap_last_wep_st then
 | 
						|
				if (state == 1) or (state == 2) then
 | 
						|
					local rand = math.random(1,4)
 | 
						|
					level.add_cam_effector("camera_effects\\switch\\" .. effect_type .. rand .. ".anm", 23232, false, '', 0, false)
 | 
						|
				end
 | 
						|
				swap_last_wep_st = state
 | 
						|
			end
 | 
						|
			swap_last_id = wpn_id
 | 
						|
		end
 | 
						|
	else
 | 
						|
		swap_last_id = 0
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local function actor_on_weapon_lower(wpn)
 | 
						|
	if wpn then
 | 
						|
		local rand = math.random(1,4)
 | 
						|
		level.add_cam_effector("camera_effects\\switch\\low" .. rand .. ".anm", 23231, false, '')
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local function actor_on_weapon_raise(wpn)
 | 
						|
	if wpn then
 | 
						|
		local rand = math.random(1,4)
 | 
						|
		level.add_cam_effector("camera_effects\\switch\\low" .. rand .. ".anm", 23231, false, '')
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local time_disabled = 0
 | 
						|
local animation_start = false
 | 
						|
local item_in_use = {}
 | 
						|
local item_not_in_use = true
 | 
						|
function Update_Animations(actor)
 | 
						|
	if item_not_in_use then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	local in_use = 0
 | 
						|
	for tg_m, t in pairs(item_in_use) do
 | 
						|
		in_use = in_use + 1
 | 
						|
		local remov = true
 | 
						|
		local tg = time_global() - tonumber(tg_m)
 | 
						|
		
 | 
						|
		-- time frame of an action has been reached -> excute then clear action
 | 
						|
		for milli, action in pairs(t) do
 | 
						|
			remov = false
 | 
						|
			if (tg > milli) then
 | 
						|
				assert(loadstring(action))()
 | 
						|
				item_in_use[tg_m][milli] = nil
 | 
						|
				--actor:give_game_news(tostring(tg), action, "ui_iconsTotal_grouping", 0, 5000, 0)
 | 
						|
			end
 | 
						|
		end
 | 
						|
		
 | 
						|
		-- no action is left? -> clear the fx from the table
 | 
						|
		if remov then
 | 
						|
			in_use = in_use - 1
 | 
						|
			item_in_use[tg_m] = nil
 | 
						|
		end
 | 
						|
	end
 | 
						|
	item_not_in_use = (in_use == 0)
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
local rad_removed
 | 
						|
function Update_Rad(actor)
 | 
						|
	if (not opt.enable_radiation_effect) then
 | 
						|
		if (not rad_removed) then
 | 
						|
			rad_removed = true
 | 
						|
			level.remove_pp_effector(2020)
 | 
						|
		end
 | 
						|
		return
 | 
						|
	end
 | 
						|
	rad_removed = false
 | 
						|
	
 | 
						|
	local radiation = actor.radiation
 | 
						|
	if (radiation > 0) then
 | 
						|
		if (radiation > opt.radiation_ppe_threshold) then
 | 
						|
			level.add_pp_effector("radiation.ppe", 2020, true)
 | 
						|
		else
 | 
						|
			level.remove_pp_effector(2020)
 | 
						|
		end
 | 
						|
		level.set_pp_effector_factor(2020, radiation)
 | 
						|
		if (math.random() < radiation) then
 | 
						|
			radiation = (radiation > 0.5) and (math.random() < radiation/1.3) and "click3" or math.random(8)
 | 
						|
			local snd = sound_object("detectors\\geiger_" .. radiation)
 | 
						|
			snd:play(actor, 0, sound_object.s2d)
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
local curr_hud
 | 
						|
local helm_con
 | 
						|
local helm_fog = 0
 | 
						|
local helm_hud_pre = ""
 | 
						|
local helm_curr
 | 
						|
local helm_off = false
 | 
						|
local helm_respi_state = false
 | 
						|
local helm_removed
 | 
						|
local helm_fx = {0.0,0.0,0.0,0.0} -- Shaders
 | 
						|
local helm_fx_old = {false,false,false,false}
 | 
						|
local helm_r1_vingette = "hud_vingette"
 | 
						|
function Update_Mask(actor)
 | 
						|
	if (not opt.enable_mask_hud) then
 | 
						|
		if (not helm_removed) then
 | 
						|
			helm_removed = true
 | 
						|
			exec_console_cmd("r2_mask_control 0.0,0.0,0.0,0.0")
 | 
						|
			HUD_mask(false, false, false)
 | 
						|
		end
 | 
						|
		return
 | 
						|
	end
 | 
						|
	helm_removed = false
 | 
						|
 | 
						|
	helm_fx[1] = 0.0
 | 
						|
	helm_fx[2] = 0.0
 | 
						|
	helm_fx[3] = 0.0
 | 
						|
	helm_fx[4] = 0.0
 | 
						|
	local helm_hud, helm_name, helm_respi
 | 
						|
	
 | 
						|
	-- Get helmet hud info
 | 
						|
	local helmet = actor:alive() and (actor:item_in_slot(12) or actor:get_current_outfit())
 | 
						|
	if helmet and (not helm_off) then
 | 
						|
		local sec = helmet:section()
 | 
						|
		if opt.helmets[sec] then
 | 
						|
			helm_con = "blue1"
 | 
						|
			
 | 
						|
			if (opt.helmets[sec].breakable) then
 | 
						|
				local cond = helmet:condition()
 | 
						|
				for i=1,10 do
 | 
						|
					local idx = "_" .. tostring(i)
 | 
						|
					if (opt.helmets_con[idx].con < cond) then
 | 
						|
						helm_con = opt.helmets_con[idx].hud
 | 
						|
						helm_fx[1] = opt.helmets_con[idx].fx
 | 
						|
						break
 | 
						|
					end
 | 
						|
				end
 | 
						|
			end
 | 
						|
			helm_hud_pre = STATIC_MASK and opt.helmets[sec].hud or "hud_gas"
 | 
						|
			helm_fog = opt.helmets[sec].blurs
 | 
						|
			helm_hud = helm_hud_pre .. "_" .. helm_con
 | 
						|
			helm_respi = opt.helmets[sec].respi
 | 
						|
			helm_name = helmet:name()
 | 
						|
			
 | 
						|
			helm_fx[2] = opt.helmets_vingette[helm_hud_pre] or 0.0
 | 
						|
			helm_fx[3] = opt.enable_visor_reflection and opt.helmets_reflect[helm_hud_pre] and 1.0 or 0.0
 | 
						|
			helm_fx[4] = 1.0
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	-- Set mask HUD on/off
 | 
						|
	if helm_off then
 | 
						|
		helm_fx[1] = 0.0
 | 
						|
		helm_fx[2] = 0.0
 | 
						|
		helm_fx[3] = 0.0
 | 
						|
		helm_fx[4] = 0.0
 | 
						|
		HUD_mask(false, false, false)
 | 
						|
	else
 | 
						|
		HUD_mask(helm_hud, helm_name, helm_respi)
 | 
						|
	end
 | 
						|
	
 | 
						|
	-- Set distortion, vingette, reflection effect for +R2
 | 
						|
	if (not IS_R1) and ((helm_fx[1] ~= helm_fx_old[1]) or (helm_fx[2] ~= helm_fx_old[2]) or (helm_fx[3] ~= helm_fx_old[3]) or (helm_fx[4] ~= helm_fx_old[4])) then
 | 
						|
		helm_fx_old[1] = helm_fx[1]
 | 
						|
		helm_fx_old[2] = helm_fx[2]
 | 
						|
		helm_fx_old[3] = helm_fx[3]
 | 
						|
		helm_fx_old[4] = helm_fx[4]
 | 
						|
		exec_console_cmd("r2_mask_control " .. tostring(helm_fx[1]) .. "," .. tostring(helm_fx[2]) .. "," .. tostring(helm_fx[3]) .. "," .. tostring(helm_fx[4]))
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
local fog_removed
 | 
						|
function Update_Fog(actor)
 | 
						|
	if (not opt.enable_breathing_fog) then
 | 
						|
		if (not fog_removed) then
 | 
						|
			fog_removed = true
 | 
						|
			HUD_fog(false)
 | 
						|
		end
 | 
						|
		return
 | 
						|
	end
 | 
						|
	fog_removed = false
 | 
						|
	
 | 
						|
	if curr_hud and (helm_fog > 0) and not string.find(curr_hud,"_red3") then
 | 
						|
		local stretchy = 0.65/(math.floor(device().height/device().width*1000)/1000)
 | 
						|
		if (stretchy < 1) then
 | 
						|
			stretchy = 1
 | 
						|
		end
 | 
						|
		local rect = {x = 0, y = -(stretchy-1)*300, w = 1024, h = 768*stretchy}
 | 
						|
		HUD_fog(true, actor, rect)
 | 
						|
	else
 | 
						|
		HUD_fog(false)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local health_play = 0
 | 
						|
local snd_tg = 0
 | 
						|
local actor_speed = {x=0, y=0, z=0}
 | 
						|
local actor_speed_time = 0
 | 
						|
function Update_Breathing(actor)
 | 
						|
	if (not opt.enable_breathing_sound) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	--local cam_dist = actor:bone_position("bip01_head"):distance_to_sqr(device().cam_pos)
 | 
						|
	local pos = actor:position()
 | 
						|
	local speed = (pos.x - actor_speed.x)^2 + (pos.y - actor_speed.y)^2 + (pos.z - actor_speed.z)^2
 | 
						|
	actor_speed.x = pos.x
 | 
						|
	actor_speed.y = pos.y
 | 
						|
	actor_speed.z = pos.z
 | 
						|
 | 
						|
	if (speed > opt.speed.mini) then
 | 
						|
		actor_speed_time = actor_speed_time + opt.speed.inc
 | 
						|
	elseif actor_speed_time > opt.speed.dec then
 | 
						|
		actor_speed_time = actor_speed_time - opt.speed.dec
 | 
						|
	end
 | 
						|
	actor_speed_time = math.min(32, actor_speed_time + actor.bleeding * opt.speed.k_bleed)
 | 
						|
 | 
						|
	if is_respi_on() then
 | 
						|
		play_sound_breath_mask(actor)
 | 
						|
	else
 | 
						|
		play_sound_breath(actor)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
local bleed_set = false
 | 
						|
local bleed_rad_eff = false
 | 
						|
local bleed_1_tg = 0
 | 
						|
local bleed_2 = false
 | 
						|
local bleed_removed
 | 
						|
function Update_Bleeding(actor)
 | 
						|
	if (not opt.enable_bleed_effect) then
 | 
						|
		if (not bleed_removed) then
 | 
						|
			bleed_removed = true
 | 
						|
			level.remove_pp_effector(2012)
 | 
						|
			level.remove_pp_effector(2013)
 | 
						|
			level.remove_pp_effector(2015)
 | 
						|
		end
 | 
						|
		return
 | 
						|
	end
 | 
						|
	bleed_removed = false
 | 
						|
	
 | 
						|
	if (actor.health < 0.21) and (bleed_set ~= true) then
 | 
						|
		level.add_pp_effector("alcohol.ppe",2012,true)
 | 
						|
		bleed_set = true
 | 
						|
	end
 | 
						|
	if (actor.health > 0.20) and (bleed_set ~= false) then
 | 
						|
		level.remove_pp_effector(2012)
 | 
						|
		bleed_set = false
 | 
						|
	end
 | 
						|
	if (actor.radiation > 0.3) and (bleed_rad_eff ~= true) then
 | 
						|
		level.add_pp_effector("alcohol.ppe",2013,true)
 | 
						|
		bleed_rad_eff = true
 | 
						|
	end
 | 
						|
	if (actor.radiation == 0) and (bleed_rad_eff ~= false) then
 | 
						|
		level.remove_pp_effector(2013)
 | 
						|
		bleed_rad_eff = false
 | 
						|
	end
 | 
						|
	if (actor.bleeding > 0.5) and (actor.health < 0.2) and bleed_1_tg < time_global() then
 | 
						|
		level.add_pp_effector("deimos1.ppe",2014,false)
 | 
						|
		bleed_1_tg = time_global() + math.random(4000,10000)
 | 
						|
	end
 | 
						|
	if (actor.bleeding > 0.5) and (actor.power < 0.25) and (bleed_2 ~= true) then
 | 
						|
		level.add_cam_effector("camera_effects\\pripyat_horror.anm",1001,false, "")
 | 
						|
		level.add_pp_effector("snd_shock.ppe",2015,true)
 | 
						|
		bleed_2 = true
 | 
						|
	end
 | 
						|
	if (actor.bleeding < 0.2) or (actor.power > 0.7) and (bleed_2 ~= false) then
 | 
						|
		level.remove_pp_effector(2015)
 | 
						|
		bleed_2 = false
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
local actor_last_health = 0
 | 
						|
local blood_tg = 0
 | 
						|
local blood_tg_b = 0
 | 
						|
local blood_state = "no"
 | 
						|
local blood_count = 0
 | 
						|
function Update_Blood(actor)
 | 
						|
	local hud = get_hud()
 | 
						|
	if opt.enable_blood_splash and actor:alive() and (not ui_disabled) then
 | 
						|
		local current_health = math.floor(actor.health*100)
 | 
						|
		local tg = time_global()
 | 
						|
		if (tg > blood_tg) then
 | 
						|
			if (blood_state == "stopit") then
 | 
						|
				if hud:GetCustomStatic("hud_blood" .. blood_count) then
 | 
						|
					hud:RemoveCustomStatic("hud_blood" .. blood_count)
 | 
						|
				end
 | 
						|
				blood_count = blood_count - 1
 | 
						|
				if (blood_count == 0) then
 | 
						|
					blood_state = "no"
 | 
						|
				end
 | 
						|
				blood_tg = time_global()+110
 | 
						|
			else
 | 
						|
				if (actor_last_health ~= 0) and (actor_last_health > current_health) and (actor.radiation < 0.12) then
 | 
						|
					if (current_health < math.random(100)) then
 | 
						|
						blood_state = "yes"
 | 
						|
					end
 | 
						|
					level.add_pp_effector("bloody.ppe",2010,false)
 | 
						|
				end
 | 
						|
				if (blood_state == "yes") then
 | 
						|
					blood_tg = time_global() + math.random(500,2000)
 | 
						|
				else
 | 
						|
					blood_tg = time_global() + math.random(2000,5000)
 | 
						|
				end
 | 
						|
				actor_last_health = current_health
 | 
						|
			end
 | 
						|
		end			
 | 
						|
		if (tg > blood_tg_b) and (blood_state == "yes") then
 | 
						|
			blood_tg_b = time_global() + 130
 | 
						|
			blood_count = blood_count + 1
 | 
						|
			hud:AddCustomStatic("hud_blood" .. blood_count)
 | 
						|
			if (blood_count == 4) then
 | 
						|
				blood_state = "stopit"
 | 
						|
			end
 | 
						|
		end
 | 
						|
	else
 | 
						|
		for i=1,4 do
 | 
						|
			if hud:GetCustomStatic("hud_blood" .. i) then
 | 
						|
				hud:RemoveCustomStatic("hud_blood" .. i)
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
local prev_health = 0
 | 
						|
local impact_snd, impact_cam
 | 
						|
local impact_removed
 | 
						|
function Update_Impact(actor)
 | 
						|
	if (not opt.enable_hit_impact_effect) then
 | 
						|
		if (not impact_removed) then
 | 
						|
			impact_removed = true
 | 
						|
			level.remove_pp_effector(2011)
 | 
						|
			level.remove_pp_effector(2016)
 | 
						|
		end
 | 
						|
		return
 | 
						|
	end
 | 
						|
	impact_removed = false
 | 
						|
	
 | 
						|
	if (prev_health > (actor.health + 0.05)) then
 | 
						|
		level.add_pp_effector(opt.health.little_ppe ,2011, false)
 | 
						|
		level.set_pp_effector_factor(2011,(prev_health - actor.health)*100)
 | 
						|
		if (prev_health > (actor.health + 0.2)) then
 | 
						|
			if (prev_health > (actor.health + 0.5)) then
 | 
						|
				level.add_pp_effector(opt.health.huge_ppe, 2016, false)
 | 
						|
				level.set_pp_effector_factor(2016,(prev_health - actor.health)*100)
 | 
						|
				impact_cam = opt.health.huge_anm
 | 
						|
				impact_snd = opt.health.huge_snd
 | 
						|
			else
 | 
						|
				impact_cam = opt.health.middle_anm
 | 
						|
				impact_snd = opt.health.middle_snd
 | 
						|
			end
 | 
						|
			
 | 
						|
			-- play impact cam effect
 | 
						|
			if (#impact_cam > 0) and (not shott) then
 | 
						|
				level.add_cam_effector("camera_effects\\" .. impact_cam[math.random(#impact_cam)] .. ".anm", 999, false, "", 0, false)
 | 
						|
			end
 | 
						|
			
 | 
						|
			-- play impact sound effect
 | 
						|
			if (#impact_snd > 0) then
 | 
						|
				local snd_obj = sound_object("actor\\" .. impact_snd[math.random(#impact_snd)])
 | 
						|
				snd_obj:play(actor,0,sound_object.s2d)
 | 
						|
			end
 | 
						|
			
 | 
						|
			-- drop player's active item
 | 
						|
			if (math.random() < (prev_health - actor.health)/2.5) then
 | 
						|
				local active_item = actor:active_item()
 | 
						|
				if active_item and (not opt.health.no_drop_wnp[active_item:section()]) then
 | 
						|
					actor:drop_item(active_item)
 | 
						|
				end
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	prev_health = actor.health
 | 
						|
end
 | 
						|
 | 
						|
--[[
 | 
						|
local ammo_current = -1
 | 
						|
function Update_Shooting(actor)
 | 
						|
	if (not opt.enable_shoot_effects) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	local active_item = actor:active_item()
 | 
						|
	local wpn = utils_item.item_is_fa(active_item) and active_item
 | 
						|
	if wpn then
 | 
						|
		local sec = wpn:section()
 | 
						|
		
 | 
						|
		if (not wpn_fx[sec]) then
 | 
						|
			parse_anims(sec)
 | 
						|
		end
 | 
						|
		
 | 
						|
		if (wpn_fx[sec] == true) then
 | 
						|
			return
 | 
						|
		end
 | 
						|
		
 | 
						|
		local ammo_in_mag =  wpn:get_ammo_in_magazine()
 | 
						|
		if (ammo_current ~= ammo_in_mag) and (wpn:get_state() == 5) then
 | 
						|
			shoot_effect(sec)
 | 
						|
			ammo_current = ammo_in_mag
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
--]]
 | 
						|
 | 
						|
function Update_Shooting(obj, wpn, ammo_elapsed, grenade_elapsed, ammo_type, grenade_type)
 | 
						|
	if (obj:id() ~= AC_ID) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (not opt.enable_shoot_effects) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	local wpn_obj = utils_item.item_is_fa(wpn) and wpn
 | 
						|
	if wpn_obj then
 | 
						|
		local sec = wpn_obj:section()
 | 
						|
		
 | 
						|
		if (not wpn_fx[sec]) then
 | 
						|
			parse_anims(sec)
 | 
						|
		end
 | 
						|
		
 | 
						|
		if (wpn_fx[sec] == true) then
 | 
						|
			return
 | 
						|
		end
 | 
						|
		
 | 
						|
		shoot_effect(sec)
 | 
						|
		
 | 
						|
		--printf("Shooting effect played for [%s]", sec)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
 | 
						|
local bar_hp_check = true
 | 
						|
local bar_hp_old = true
 | 
						|
local bar_hp_new = true
 | 
						|
local bar_hp_first = true
 | 
						|
local bar_hp_trigger = 0.95
 | 
						|
function Update_HealthHUD(actor)
 | 
						|
	-- Autohide disabled
 | 
						|
	if (not autohide) then
 | 
						|
		if bar_hp_check then
 | 
						|
			bar_hp_check = false
 | 
						|
			local maingameui = ActorMenu.get_maingame()
 | 
						|
			if (maingameui and maingameui.m_ui_hud_states) then
 | 
						|
				maingameui.m_ui_hud_states.m_ui_health_bar_show = true
 | 
						|
			end
 | 
						|
		end
 | 
						|
		return
 | 
						|
		
 | 
						|
	elseif bar_hp_first then
 | 
						|
		bar_hp_first = false
 | 
						|
		local maingameui = ActorMenu.get_maingame()
 | 
						|
		if (maingameui and maingameui.m_ui_hud_states) then
 | 
						|
			maingameui.m_ui_hud_states.m_ui_health_bar_show = true
 | 
						|
		end
 | 
						|
		
 | 
						|
	else
 | 
						|
		bar_hp_new = true --(actor.health < bar_hp_trigger)
 | 
						|
		if (bar_hp_old ~= bar_hp_new) then
 | 
						|
			local maingameui = ActorMenu.get_maingame()
 | 
						|
			if (maingameui and maingameui.m_ui_hud_states) then
 | 
						|
				maingameui.m_ui_hud_states.m_ui_health_bar_show = bar_hp_new
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local bar_pwr_check = true
 | 
						|
local bar_pwr_old = true
 | 
						|
local bar_pwr_new = true
 | 
						|
local bar_pwr_first = true
 | 
						|
local bar_pwr_trigger = 0.95
 | 
						|
function Update_StaminaHUD(actor)
 | 
						|
	-- Autohide disabled
 | 
						|
	if (not autohide) then
 | 
						|
		if bar_pwr_check then
 | 
						|
			bar_pwr_check = false
 | 
						|
			local maingameui = ActorMenu.get_maingame()
 | 
						|
			if (maingameui and maingameui.m_ui_hud_states) then
 | 
						|
				maingameui.m_ui_hud_states.m_ui_stamina_bar_show = true
 | 
						|
			end
 | 
						|
		end
 | 
						|
		return
 | 
						|
		
 | 
						|
	elseif bar_pwr_first then
 | 
						|
		bar_pwr_first = false
 | 
						|
		local maingameui = ActorMenu.get_maingame()
 | 
						|
		if (maingameui and maingameui.m_ui_hud_states) then
 | 
						|
			maingameui.m_ui_hud_states.m_ui_stamina_bar_show = true
 | 
						|
		end
 | 
						|
		
 | 
						|
	else
 | 
						|
		bar_pwr_new = (actor.power < bar_pwr_trigger)
 | 
						|
		if (bar_pwr_old ~= bar_pwr_new) then
 | 
						|
			bar_pwr_old = bar_pwr_new
 | 
						|
			local maingameui = ActorMenu.get_maingame()
 | 
						|
			if (maingameui and maingameui.m_ui_hud_states) then
 | 
						|
				maingameui.m_ui_hud_states.m_ui_stamina_bar_show = bar_pwr_new
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
--------------------------------------------------------------
 | 
						|
-- HUD
 | 
						|
--------------------------------------------------------------
 | 
						|
local fogs
 | 
						|
local fog_val = 0 -- level of fogging from 0 to 1
 | 
						|
local fog_tg = 0 -- last update time
 | 
						|
local fog_cycle = 0 -- start time of the last breath cycle (exhale)
 | 
						|
local fog_last_phase = 0
 | 
						|
local zbias = Frect():set(0,0,1024,1024)
 | 
						|
function HUD_fog(enabled, actor, rect)
 | 
						|
	local hud = get_hud()
 | 
						|
	
 | 
						|
	-- Gather breathing fog textures for the first time if they not defined
 | 
						|
	if (not fogs) then
 | 
						|
		fogs = {}
 | 
						|
		for i=1,4 do
 | 
						|
			local pht = {}
 | 
						|
			for ii = 1,10 do
 | 
						|
				local static = "hud_blur" .. i .. "_" .. ii
 | 
						|
				hud:AddCustomStatic(static)
 | 
						|
				pht[ii] = hud:GetCustomStatic(static):wnd()
 | 
						|
			end
 | 
						|
			fogs[i] = pht
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	-- Gather breathing fog for the first time if it's not defined
 | 
						|
	if (not enabled) then
 | 
						|
		for i,t in ipairs(fogs) do
 | 
						|
			for ii,st in ipairs(t) do
 | 
						|
				st:SetWndRect(Frect():set(0,0,0,0))
 | 
						|
			end
 | 
						|
		end
 | 
						|
		fog_val = 0
 | 
						|
		fog_cycle = time_global()
 | 
						|
		fog_last_phase = 0
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	-- Cycles depending on the power of breathing: 0->1->0 0->1->2->4->5->0 0->1->2->3->4->5->0 5->4->3->4->5 4->3->4
 | 
						|
	local power = actor.power
 | 
						|
	local period = 1.0 + (power * power * 1.0) -- current respiratory rate from 30 to 120 cycles per minute
 | 
						|
	local expirt = 0.3
 | 
						|
	local delta = (time_global() - fog_tg)/1000 -- delta in seconds
 | 
						|
	local phase = (time_global() - fog_cycle)/1000 -- phase of the respiratory cycle in seconds.
 | 
						|
	fog_tg = time_global()
 | 
						|
	if phase > period then
 | 
						|
		phase = phase%period
 | 
						|
		fog_cycle = fog_tg-phase*1000
 | 
						|
	end
 | 
						|
	if (fog_last_phase > phase) then
 | 
						|
		fog_last_phase = 0
 | 
						|
	end
 | 
						|
	local blurdelta = delta * -0.7 -- ventilation operation
 | 
						|
	if (fog_last_phase < expirt) and (phase < expirt) then
 | 
						|
		blurdelta = blurdelta + (phase - fog_last_phase)*helm_fog
 | 
						|
	elseif (fog_last_phase < expirt) then
 | 
						|
		blurdelta = blurdelta + (expirt - fog_last_phase)*helm_fog
 | 
						|
	end
 | 
						|
	fog_last_phase = phase
 | 
						|
	fog_val = fog_val + blurdelta
 | 
						|
	if (fog_val > 0.999) then
 | 
						|
		fog_val = 0.999
 | 
						|
	elseif (fog_val < 0) then
 | 
						|
		fog_val = 0
 | 
						|
	end
 | 
						|
	local tm = math.floor(fog_val*3)
 | 
						|
	local tmn = (tm+1)
 | 
						|
	local v = fog_val*3-math.floor(fog_val*3)
 | 
						|
	v = 1-v
 | 
						|
	local v1 = 1-v
 | 
						|
	local n1 = math.ceil(v*10)
 | 
						|
	local n2 = math.ceil(v1*10)
 | 
						|
	for i=1,4 do
 | 
						|
		for ii=1,10 do
 | 
						|
			if (i == tm and ii == n1) then
 | 
						|
				fogs[tm][n1]:SetWndRect(Frect():set(rect.x, rect.y, rect.w, rect.h))
 | 
						|
				fogs[tm][n1]:SetTextureRect(Frect():set(zbias.x1/4, zbias.y1/4, zbias.x2/4, zbias.y2/4))
 | 
						|
			elseif (i == tmn and ii == n2) then
 | 
						|
				fogs[tmn][n2]:SetWndRect(Frect():set(rect.x, rect.y, rect.w, rect.h))
 | 
						|
				fogs[tmn][n2]:SetTextureRect(Frect():set(zbias.x1/4, zbias.y1/4, zbias.x2/4, zbias.y2/4))
 | 
						|
			else
 | 
						|
				fogs[i][ii]:SetWndRect(Frect():set(0,0,0,0))
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
local mask_first_try = true
 | 
						|
function HUD_mask(helm_hud, helm_name, helm_respi)
 | 
						|
	local hud = get_hud()
 | 
						|
	local actor_pos = db.actor:bone_position("bip01_head")
 | 
						|
	
 | 
						|
	if (not helm_hud) or (cam_dist > opt.cam_dist) then
 | 
						|
		if IS_R1 then -- Distortion/Mask UI
 | 
						|
			local wchud = hud:GetCustomStatic(curr_hud)
 | 
						|
			if wchud then
 | 
						|
				hud:RemoveCustomStatic(curr_hud)
 | 
						|
			end
 | 
						|
		end
 | 
						|
		
 | 
						|
		if (IS_R1 and (not STATIC_MASK)) or STATIC_VINGETTE then -- Vingette
 | 
						|
			local wchud = hud:GetCustomStatic(helm_r1_vingette)
 | 
						|
			if wchud then
 | 
						|
				hud:RemoveCustomStatic(helm_r1_vingette)
 | 
						|
			end
 | 
						|
		end
 | 
						|
		curr_hud = nil
 | 
						|
		mask_first_try = true
 | 
						|
		helm_respi_state = false
 | 
						|
	
 | 
						|
	elseif (helm_hud ~= curr_hud) then
 | 
						|
		if IS_R1 then -- Distortion/Mask UI
 | 
						|
			if curr_hud then
 | 
						|
				hud:RemoveCustomStatic(curr_hud)
 | 
						|
			end
 | 
						|
			
 | 
						|
			hud:AddCustomStatic(helm_hud)
 | 
						|
		end
 | 
						|
		
 | 
						|
		if (IS_R1 and (not STATIC_MASK)) or STATIC_VINGETTE then -- Vingette
 | 
						|
			local wchud = hud:GetCustomStatic(helm_r1_vingette)
 | 
						|
			if (not wchud) then
 | 
						|
				hud:AddCustomStatic(helm_r1_vingette)
 | 
						|
			end
 | 
						|
		end
 | 
						|
		
 | 
						|
		if string.find(helm_hud, helm_hud_pre) then
 | 
						|
			if (not mask_first_try) and (helm_con ~= "blue2") and (helm_con ~= "blue1") and (helm_name == helm_curr) then
 | 
						|
				local snd_obj = sound_object("material\\glass\\glass_fall03hl")
 | 
						|
				snd_obj:play(db.actor,0,sound_object.s2d)
 | 
						|
			end
 | 
						|
			if mask_first_try then
 | 
						|
				mask_first_try = false
 | 
						|
			end
 | 
						|
		end
 | 
						|
		
 | 
						|
		helm_curr = helm_name
 | 
						|
		curr_hud = helm_hud
 | 
						|
		helm_respi_state = helm_respi
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
--------------------------------------------------------------
 | 
						|
-- Utilities
 | 
						|
--------------------------------------------------------------
 | 
						|
function play_item_fx(name)
 | 
						|
	if (not opt.enable_animations) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (not ini_eff:section_exist(tostring(name) or 'INVALID_ARG')) then
 | 
						|
		printf("~WARNING actor_effects.play_item_fx | item animation [%s] doesn't exist!", name)
 | 
						|
		return 
 | 
						|
		
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (time_global() > time_disabled) and animation_start then
 | 
						|
		local tg = tostring(time_global())
 | 
						|
		item_not_in_use = false
 | 
						|
		item_in_use[tg] = {}
 | 
						|
		
 | 
						|
		local n = ini_eff:line_count(name)
 | 
						|
		for i=0,n-1 do
 | 
						|
			local result, id, value	= ini_eff:r_line_ex(name,i,"","")
 | 
						|
			id = id and tonumber(id)
 | 
						|
			if id and value then
 | 
						|
				item_in_use[tg][id] = value
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
function play_continuous_effect(period)
 | 
						|
 | 
						|
	--if (not opt.enable_animations) then return end
 | 
						|
 | 
						|
	local tot = 0
 | 
						|
	local one_p = 5600 --3801
 | 
						|
	local num = math.ceil(period/one_p)
 | 
						|
		
 | 
						|
	if (time_global() > time_disabled) then
 | 
						|
		local tg = tostring(time_global())
 | 
						|
		item_not_in_use = false
 | 
						|
		item_in_use[tg] = {}
 | 
						|
		item_in_use[tg][0] = "actor_effects.use_weapon(0)"
 | 
						|
		item_in_use[tg][1] = "xr_effects.disable_ui_inventory(db.actor, nil)"
 | 
						|
		item_in_use[tg][2] = "xr_effects.disable_ui_lite_with_imput(db.actor, nil)"
 | 
						|
		item_in_use[tg][550] = "level.add_cam_effector('camera_effects\\\\item_use.anm', 8053, false,'')"
 | 
						|
		tot = 550
 | 
						|
		for i=1,num-1 do
 | 
						|
			tot = tot + one_p
 | 
						|
			item_in_use[tg][tot] = "level.add_cam_effector('camera_effects\\\\item_use.anm', 8053, false,'')"
 | 
						|
		end
 | 
						|
		tot = tot + one_p
 | 
						|
		item_in_use[tg][tot] = "xr_effects.enable_ui_lite(db.actor, nil)"
 | 
						|
		item_in_use[tg][tot + 1399] = "xr_effects.enable_imput(db.actor, nil)"
 | 
						|
		item_in_use[tg][tot + 1999] = "actor_effects.use_weapon(1)"
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local breath_sound = 0
 | 
						|
local gas_play = 0
 | 
						|
function play_sound_breath_mask(actor)
 | 
						|
	local tg = time_global()
 | 
						|
	if (tg > snd_tg) then
 | 
						|
		gas_play = gas_play + 1
 | 
						|
		if (gas_play > 8) then
 | 
						|
			gas_play = 1
 | 
						|
		end
 | 
						|
		breath_sound = sound_object("actor\\gas_breath_" .. tostring((actor.health > 0.2) and math.ceil((1.01 - actor.power)*3 + actor_speed_time/8) or 8) .. "_" .. gas_play)
 | 
						|
		snd_tg = tg + breath_sound:length()*1.25
 | 
						|
		breath_sound:play(actor, 0, sound_object.s2d)
 | 
						|
		breath_sound.volume = (cam_dist > opt.cam_dist) and 0 or (1 - cam_dist/opt.cam_dist) * 0.5
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local run_play = 0
 | 
						|
function play_sound_breath(actor)
 | 
						|
	local tg = time_global()
 | 
						|
	local health = actor.health
 | 
						|
 | 
						|
	if (tg < snd_tg) or (health < 0) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
 | 
						|
	if (health > opt.health.level2) then
 | 
						|
		if (actor_speed_time > opt.speed.time_mini) or (actor.power < opt.speed.stamina) or (run_play == 1) then
 | 
						|
			run_play = run_play + 1
 | 
						|
			if (run_play > 2) then
 | 
						|
				run_play = 1
 | 
						|
			end
 | 
						|
			breath_sound = sound_object("actor\\run_" .. math.ceil(3*actor_speed_time/44) .. "_" .. run_play)
 | 
						|
			breath_sound:play(actor, 0, sound_object.s2d)
 | 
						|
			breath_sound.volume = (cam_dist > opt.cam_dist) and 0 or (1 - cam_dist/opt.cam_dist)
 | 
						|
			snd_tg = tg+breath_sound:length()*1.15
 | 
						|
		else
 | 
						|
			run_play = 2
 | 
						|
		end
 | 
						|
		return
 | 
						|
	end
 | 
						|
 | 
						|
	if (health <= opt.health.level1) then
 | 
						|
		health = 1
 | 
						|
		if (math.random() < 0.1) then
 | 
						|
			health_play = 0
 | 
						|
		else
 | 
						|
			health_play = health_play + 1
 | 
						|
			if (health_play > 4) then
 | 
						|
				health_play = 1
 | 
						|
			end
 | 
						|
		end
 | 
						|
	else
 | 
						|
		health = 2
 | 
						|
		health_play = health_play+1
 | 
						|
		if (health_play > 4) then
 | 
						|
			health_play = 1
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	snd_tg = tg + (opt.health.injury_snd["_"..health.."_"..health_play] or 4000)
 | 
						|
	breath_sound = sound_object("actor\\health_" .. health .. "_" .. health_play)
 | 
						|
	breath_sound:play(actor, 0, sound_object.s2d)
 | 
						|
	breath_sound.volume = (cam_dist > opt.cam_dist) and 0 or (1 - cam_dist/opt.cam_dist)
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
local shotc = 1
 | 
						|
local shott = 0
 | 
						|
local fov_r = 1
 | 
						|
function shoot_effect(sect)
 | 
						|
	--printf("-SHOOT")
 | 
						|
 | 
						|
	if shott and (shott < time_global()) then
 | 
						|
		shotc = 1
 | 
						|
		shott = nil
 | 
						|
	end
 | 
						|
 | 
						|
	local anims = {}
 | 
						|
	local s = wpn_fx[sect].s
 | 
						|
	local sc = #s
 | 
						|
 | 
						|
	if sc > 1 then
 | 
						|
		if wpn_fx[sect].r == 1 then
 | 
						|
			s = s[math.random(#s)]
 | 
						|
		elseif wpn_fx[sect].r == 2 then
 | 
						|
			if shotc == 1 then
 | 
						|
				s = s[1]
 | 
						|
			else
 | 
						|
				s = s[math.random(2,#s)]
 | 
						|
			end
 | 
						|
		else
 | 
						|
			sc = shotc <= sc and shotc or (sc > 2 and math.random(sc-1,sc)) or sc
 | 
						|
			s = s[sc]
 | 
						|
		end
 | 
						|
	else
 | 
						|
		s = s[1]
 | 
						|
	end
 | 
						|
--	local cnt, r = math.modf(s*fov_r)
 | 
						|
--	if r ~=0 then
 | 
						|
--		s = math.max(1, cnt - 1)
 | 
						|
--	end
 | 
						|
	for i,v in pairs(wpn_fx[sect].e) do
 | 
						|
		local cnt,r = math.modf(v[1]*fov_r)
 | 
						|
		if r ~= 0 and cnt > 4 then --fmb
 | 
						|
			cnt = cnt-cnt*math.random(0,r*100)/100 --fmb
 | 
						|
			cnt,r = math.modf(cnt)
 | 
						|
		end
 | 
						|
 | 
						|
		if r ~= 0 and math.random() < r then
 | 
						|
			cnt = cnt+1
 | 
						|
		end
 | 
						|
 | 
						|
		if cnt > 0 then
 | 
						|
			table.insert(anims,{e = i,d = v[2] or math.random(0,1),c = cnt})
 | 
						|
		end
 | 
						|
	end
 | 
						|
	for i,a in ipairs(anims) do
 | 
						|
		local n = string.format([[shoot\s%s_e%s_%s.anm]],s,a.e,a.d)
 | 
						|
		for ii=1,a.c do
 | 
						|
			level.add_cam_effector(n,math.random(5000,8000),false,"")
 | 
						|
		end
 | 
						|
	end
 | 
						|
	for k,v in pairs(wpn_fx[sect].p) do
 | 
						|
		local eid = math.random(5000,8000)
 | 
						|
		level.add_pp_effector(string.format([[shoot\%s_s%s.ppe]],k,s), eid, false)
 | 
						|
		if v > 0 then
 | 
						|
			level.set_pp_effector_factor(eid,v)
 | 
						|
		end
 | 
						|
	end
 | 
						|
	shotc = shotc+1
 | 
						|
	shott = time_global()+100
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
function switch_helm()
 | 
						|
	helm_off = not helm_off
 | 
						|
end
 | 
						|
 | 
						|
function is_respi_on()
 | 
						|
	return helm_respi_state
 | 
						|
end
 | 
						|
 | 
						|
function is_mask_on()
 | 
						|
	return curr_hud
 | 
						|
end
 | 
						|
 | 
						|
function is_animations_on()
 | 
						|
	return opt.enable_animations
 | 
						|
end
 | 
						|
 | 
						|
function set_animations(state)
 | 
						|
	opt.enable_animations = state and true or false
 | 
						|
end
 | 
						|
 | 
						|
function clear_mask_hud()
 | 
						|
	HUD_mask(false, false, false)
 | 
						|
end
 | 
						|
 | 
						|
function reset_idle_anim(wpn, empty)
 | 
						|
	if wpn then 
 | 
						|
		wpn:switch_state(0)
 | 
						|
	end
 | 
						|
	
 | 
						|
	-- TODO: rebind keys
 | 
						|
	can_shoot = true
 | 
						|
	return true 
 | 
						|
end
 | 
						|
 | 
						|
function actor_can_shoot(state)
 | 
						|
	can_shoot = state
 | 
						|
end
 | 
						|
 | 
						|
function disable_effects_timer(n)
 | 
						|
	time_disabled = time_global() + n
 | 
						|
end
 | 
						|
 | 
						|
function use_helmet()
 | 
						|
	switch_helm()
 | 
						|
end
 | 
						|
 | 
						|
function use_weapon(f)
 | 
						|
	local hidden = weapon_hidden
 | 
						|
	weapon_hidden = weapon_hidden + f * 2 - 1
 | 
						|
	if weapon_hidden == 0 then
 | 
						|
		db.actor:restore_weapon()
 | 
						|
	elseif hidden == 0 then
 | 
						|
		db.actor:hide_weapon()
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
function toggle_active_slot(f)
 | 
						|
	if (f == 0) then
 | 
						|
		last_slot = db.actor:active_slot()
 | 
						|
		db.actor:activate_slot(0)
 | 
						|
	else
 | 
						|
		db.actor:activate_slot(last_slot)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
function toggle_hud_autohide(state)
 | 
						|
	autohide = state
 | 
						|
	bar_hp_check = true
 | 
						|
	bar_pwr_check = true
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
--------------------------------------------------------------
 | 
						|
-- Callbacks
 | 
						|
--------------------------------------------------------------
 | 
						|
local tg_acon = 0
 | 
						|
local tg_acon_step = 180
 | 
						|
local tg_hud = 50
 | 
						|
local tg_hud_step = 120
 | 
						|
local tg_bleed = 100
 | 
						|
local tg_bleed_step = 400
 | 
						|
local function actor_on_update()
 | 
						|
	local actor = db.actor
 | 
						|
	if (not actor) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
	
 | 
						|
	local tg = time_global()
 | 
						|
	cam_dist = actor:bone_position("bip01_head"):distance_to_sqr(device().cam_pos)
 | 
						|
	
 | 
						|
	if (tg > tg_bleed) then
 | 
						|
		tg_bleed = tg + tg_bleed_step
 | 
						|
		Update_Bleeding(actor)
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (tg > tg_acon) then
 | 
						|
		tg_acon = tg + tg_acon_step
 | 
						|
	
 | 
						|
		Update_Breathing(actor)
 | 
						|
		Update_Rad(actor)
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (tg > tg_hud) then
 | 
						|
		tg_hud = tg + tg_hud_step
 | 
						|
		Update_Blood(actor)
 | 
						|
		Update_Mask(actor)
 | 
						|
	end
 | 
						|
	
 | 
						|
	Update_Fog(actor)
 | 
						|
	
 | 
						|
	Update_Impact(actor)
 | 
						|
	Update_ItemSwap(actor)
 | 
						|
	Update_Animations(actor)
 | 
						|
	--Update_Shooting(actor)
 | 
						|
	Update_HealthHUD(actor)
 | 
						|
	Update_StaminaHUD(actor)
 | 
						|
end
 | 
						|
 | 
						|
local function on_key_release(key)
 | 
						|
	animation_start = true
 | 
						|
	local bind = dik_to_bind(key)
 | 
						|
	
 | 
						|
	-- Clean Mask
 | 
						|
	if (bind == key_bindings.kCAM_ZOOM_IN) then
 | 
						|
		Hit_MaskCleaning()
 | 
						|
		
 | 
						|
	-- Toggle Torch
 | 
						|
	elseif (bind == key_bindings.kTORCH) then
 | 
						|
		Hit_TorchToggle()
 | 
						|
		
 | 
						|
	-- Grenade Quickthrow
 | 
						|
	elseif (bind == key_bindings.kCUSTOM19) then
 | 
						|
		Hit_GrenadeQuickthrow()
 | 
						|
		
 | 
						|
	-- Toggle HUD
 | 
						|
	elseif (bind == key_bindings.kCUSTOM6) then
 | 
						|
		local val = not (get_console_cmd(1,"hud_draw"))
 | 
						|
		local toggl = val and "on" or "off"
 | 
						|
		exec_console_cmd("hud_draw " .. toggl)
 | 
						|
	
 | 
						|
	-- Toggle item animations
 | 
						|
	elseif (bind == key_bindings.kCAM_ZOOM_OUT) then
 | 
						|
		local old_state = opt.enable_animations and true or false
 | 
						|
		local new_state = not old_state
 | 
						|
		
 | 
						|
		ui_options.set("video/player/animations", new_state)
 | 
						|
		opt.enable_animations = new_state
 | 
						|
		
 | 
						|
		if new_state then
 | 
						|
			xr_sound.set_sound_play(AC_ID, "pda_tips")
 | 
						|
		else
 | 
						|
			xr_sound.set_sound_play(AC_ID, "pda_alarm")
 | 
						|
		end
 | 
						|
		
 | 
						|
		local str = new_state and "st_toggle_animation_on" or "st_toggle_animation_off"
 | 
						|
		actor_menu.set_msg(2, game.translate_string(str))
 | 
						|
		
 | 
						|
	-- Screenshot
 | 
						|
	elseif (bind == key_bindings.kSCREENSHOT) then
 | 
						|
		snd_cam:play(db.actor,0,sound_object.s2d)
 | 
						|
		
 | 
						|
	-- PDA Map
 | 
						|
	elseif (bind == key_bindings.kCUSTOM20) then
 | 
						|
		local pda_menu = ActorMenu.get_pda_menu()
 | 
						|
		local pda3d = get_console_cmd(1,"g_3d_pda")
 | 
						|
		if not (pda_menu:IsShown()) and db.actor:item_in_slot(8) then
 | 
						|
			if (pda3d) then
 | 
						|
				db.actor:activate_slot(8)
 | 
						|
			else
 | 
						|
				pda_menu:ShowDialog(true)
 | 
						|
			end
 | 
						|
			
 | 
						|
			pda_menu:SetActiveSubdialog("eptTasks")
 | 
						|
		elseif (pda_menu:IsShown()) then
 | 
						|
			if (pda3d) then
 | 
						|
				db.actor:activate_slot(0)
 | 
						|
			else
 | 
						|
				pda_menu:HideDialog()
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local ruck_last_outfit = -1
 | 
						|
local ruck_last_helmet = -1
 | 
						|
local ruck_last_backpack = -1
 | 
						|
local function actor_item_to_ruck(obj)
 | 
						|
	local id = obj:id()
 | 
						|
	local play_anm = false
 | 
						|
	
 | 
						|
	if (id == ruck_last_outfit) then
 | 
						|
		ruck_last_outfit = -1
 | 
						|
		play_anm = true
 | 
						|
	elseif (id == ruck_last_helmet) then
 | 
						|
		ruck_last_helmet = -1
 | 
						|
		play_anm = true
 | 
						|
	elseif (id == ruck_last_backpack) then
 | 
						|
		ruck_last_backpack = -1
 | 
						|
		play_anm = true
 | 
						|
	end
 | 
						|
	
 | 
						|
	if play_anm and (not has_alife_info("BAR_ARENA_FIGHT")) then
 | 
						|
		if IsOutfit(obj) then
 | 
						|
			play_item_fx("outfit")
 | 
						|
		elseif IsHeadgear(obj) then
 | 
						|
			play_item_fx("helm")
 | 
						|
		elseif IsItem("backpack", nil, obj) then
 | 
						|
			play_item_fx("outfit")
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local function actor_item_to_slot(obj)
 | 
						|
	if (not has_alife_info("BAR_ARENA_FIGHT")) then
 | 
						|
		if IsOutfit(obj) then
 | 
						|
			ruck_last_backpack = obj:id()
 | 
						|
			play_item_fx("outfit")
 | 
						|
		elseif IsHeadgear(obj) then
 | 
						|
			ruck_last_backpack = obj:id()
 | 
						|
			play_item_fx("helm")
 | 
						|
		elseif IsItem("backpack", nil, obj) then
 | 
						|
			ruck_last_backpack = obj:id()
 | 
						|
			play_item_fx("outfit")
 | 
						|
		elseif opt.enable_animations then
 | 
						|
			local rand = math.random(1,4)
 | 
						|
			level.add_cam_effector("camera_effects\\switch\\low" .. rand .. ".anm", 23234, false,'', 0, false)
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local function actor_on_item_use(obj)
 | 
						|
	play_item_fx(obj:section())
 | 
						|
end
 | 
						|
 | 
						|
local last_wpn_snd_empty = {nil, "$no_sound", 1}
 | 
						|
local tg_snd_empty = 0
 | 
						|
local critical_wpn_con = 0.014
 | 
						|
local delay_snd_empty = 300 -- ms
 | 
						|
local function actor_on_weapon_before_fire(flags)
 | 
						|
	local tg = time_global()
 | 
						|
 | 
						|
	local obj_wpn = db.actor:active_item()
 | 
						|
	if obj_wpn and IsWeapon(obj_wpn) and (not IsMelee(obj_wpn)) then
 | 
						|
		local con = obj_wpn:condition()
 | 
						|
		if (con <= critical_wpn_con) then
 | 
						|
			local sec = obj_wpn:section()
 | 
						|
			
 | 
						|
			-- Cache
 | 
						|
			if (sec ~= last_wpn_snd_empty[1]) then
 | 
						|
				-- Reset
 | 
						|
				last_wpn_snd_empty[1] = sec
 | 
						|
				last_wpn_snd_empty[2] = "$no_sound"
 | 
						|
				last_wpn_snd_empty[3] = 1
 | 
						|
				
 | 
						|
				-- Get empty sound
 | 
						|
				local snd = ini_sys:r_string_ex(sec,"snd_empty")
 | 
						|
				if snd and (snd ~= "") then
 | 
						|
					snd = str_explode(snd,",")
 | 
						|
					last_wpn_snd_empty[2] = snd[1]
 | 
						|
					last_wpn_snd_empty[3] = snd[2] or 1
 | 
						|
				end
 | 
						|
			end
 | 
						|
			
 | 
						|
			-- Play empty clip sound
 | 
						|
			if (last_wpn_snd_empty[2] ~= "$no_sound") and (tg > tg_snd_empty) then
 | 
						|
				utils_obj.play_sound( last_wpn_snd_empty[2], last_wpn_snd_empty[3] or 1 )
 | 
						|
				tg_snd_empty = tg + delay_snd_empty
 | 
						|
			end
 | 
						|
			
 | 
						|
			-- Don't shoot
 | 
						|
			flags.ret_value = false
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	if (not can_shoot) then
 | 
						|
		flags.ret_value = false
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local function actor_on_first_update()
 | 
						|
	-- Enable mini-map
 | 
						|
	minimap_enabled = ui_options.get("video/hud/show_minimap")
 | 
						|
	local maingameui = ActorMenu.get_maingame()
 | 
						|
	if (maingameui and maingameui.UIZoneMap) then
 | 
						|
		maingameui.UIZoneMap.disabled = not minimap_enabled
 | 
						|
		maingameui.UIMotionIcon:Show(maingameui.UIZoneMap.disabled == false)
 | 
						|
	end
 | 
						|
	
 | 
						|
	init_main_settings()
 | 
						|
	--disable_effects_timer(5000)
 | 
						|
	if db.actor then
 | 
						|
		ruck_last_outfit = db.actor:item_in_slot(7) and db.actor:item_in_slot(7):id() or -1
 | 
						|
		ruck_last_helmet = db.actor:item_in_slot(12) and db.actor:item_in_slot(12):id() or -1
 | 
						|
		ruck_last_backpack = db.actor:item_in_slot(13) and db.actor:item_in_slot(13):id() or -1
 | 
						|
		
 | 
						|
		if (detector_was_active) then
 | 
						|
			db.actor:show_detector()
 | 
						|
		end
 | 
						|
	end
 | 
						|
	
 | 
						|
	--utils_data.print_table(opt)
 | 
						|
	
 | 
						|
	--Animation stuff
 | 
						|
	game.only_allow_movekeys(false)
 | 
						|
	game.set_actor_allow_ladder(true)
 | 
						|
	game.stop_all_hud_anms()
 | 
						|
	game.stop_hud_motion()
 | 
						|
	
 | 
						|
	mc_anm_time_1 = game.get_motion_length(mc_anm_sec, "anm_hide_hand", hide_hand_speed)
 | 
						|
	mc_anm_time_2 = game.get_motion_length(mc_anm_sec, "anm_wipe", 1)
 | 
						|
	torch_anm_time = game.get_motion_length(torch_anm_sec, "anm_switch", 1)
 | 
						|
end
 | 
						|
 | 
						|
local function save_state(m_data)
 | 
						|
 | 
						|
	if (not db.actor) then
 | 
						|
		return
 | 
						|
	end
 | 
						|
 | 
						|
	m_data.detector_was_active = db.actor:active_detector() and true or false
 | 
						|
end
 | 
						|
 | 
						|
local function load_state(m_data)
 | 
						|
	
 | 
						|
	detector_was_active = m_data.detector_was_active
 | 
						|
end
 | 
						|
 | 
						|
function on_game_start()
 | 
						|
	init_settings()
 | 
						|
 | 
						|
	RegisterScriptCallback("on_key_release",on_key_release)
 | 
						|
	RegisterScriptCallback("actor_item_to_slot",actor_item_to_slot)
 | 
						|
	RegisterScriptCallback("actor_item_to_ruck",actor_item_to_ruck)
 | 
						|
	RegisterScriptCallback("actor_on_item_drop",actor_item_to_ruck)
 | 
						|
	RegisterScriptCallback("actor_on_item_use",actor_on_item_use)
 | 
						|
	RegisterScriptCallback("actor_on_weapon_before_fire",actor_on_weapon_before_fire)
 | 
						|
	RegisterScriptCallback("actor_on_weapon_lower",actor_on_weapon_lower)
 | 
						|
	RegisterScriptCallback("actor_on_weapon_raise",actor_on_weapon_raise)
 | 
						|
	RegisterScriptCallback("actor_on_update",actor_on_update)
 | 
						|
	RegisterScriptCallback("actor_on_first_update",actor_on_first_update)
 | 
						|
	RegisterScriptCallback("actor_on_weapon_fired",Update_Shooting)
 | 
						|
	RegisterScriptCallback("burer_on_before_weapon_drop",burer_on_before_weapon_drop)
 | 
						|
	RegisterScriptCallback("on_option_change",init_main_settings)
 | 
						|
	RegisterScriptCallback("save_state",save_state)
 | 
						|
	RegisterScriptCallback("load_state",load_state)
 | 
						|
end 
 |