401 lines
13 KiB
Plaintext
401 lines
13 KiB
Plaintext
------------------------------------------------------------------------------
|
|
---------------------------------- Arms -------------------------------------
|
|
------------------------------------------------------------------------------
|
|
local aim_anm = {"earthquake_1","earthquake_2"}
|
|
local mcm_arms_penalty = zzz_player_injuries_mcm.get_config("arm_opt")
|
|
local mcm_arms_min_hp = zzz_player_injuries_mcm.get_config("arm_pen_min_hp")
|
|
local mcm_arms_cam_pwr = zzz_player_injuries_mcm.get_config("arm_anm_pwr")
|
|
|
|
function shaking_hands()
|
|
|
|
if not mcm_arms_penalty then return end
|
|
|
|
local activeslot = db.actor:active_slot()
|
|
if not (activeslot == 2 or activeslot == 3 or activeslot == 1) then return end
|
|
|
|
local item_in_slot = db.actor:item_in_slot(activeslot)
|
|
if not (item_in_slot) then return end
|
|
|
|
local cam_power = 0
|
|
|
|
local weight = item_in_slot:weight()
|
|
local body_state = get_body_state()
|
|
local body_state_mult = (body_state == "crouch" and 0.75) or (body_state == "low_crouch" and 0.5) or 1
|
|
|
|
local health, timedhp, maxhp = zzz_player_injuries.health, zzz_player_injuries.timedhp, zzz_player_injuries.maxhp
|
|
|
|
local max_left_arm, max_right_arm = maxhp.rightarm, maxhp.leftarm
|
|
local left_arm, right_arm = health.rightarm + timedhp.rightarm, health.leftarm + timedhp.leftarm
|
|
|
|
local arms_ratio = (left_arm + right_arm) / (max_left_arm + max_right_arm)
|
|
|
|
if arms_ratio >= (mcm_arms_min_hp / 100) then
|
|
return
|
|
end
|
|
|
|
-- lower penalty if both arms almost equally damaged (except when both have low hp)
|
|
if (left_arm / right_arm) > 0.6 and (right_arm / left_arm) > 0.6 then
|
|
cam_power = 0.08 * weight / arms_ratio
|
|
else
|
|
cam_power = 0.12 * weight / arms_ratio
|
|
end
|
|
|
|
cam_power = cam_power * body_state_mult
|
|
cam_power = clamp(cam_power, 0, 3)
|
|
cam_power = cam_power * mcm_arms_cam_pwr
|
|
|
|
if item_in_slot:weapon_is_scope() then
|
|
cam_power = cam_power * 0.2
|
|
end
|
|
|
|
-- play anm
|
|
level.add_cam_effector("camera_effects\\" .. aim_anm[math.random(#aim_anm)] .. ".anm", 9921, true, "", 0, true, cam_power)
|
|
end
|
|
|
|
function actor_on_weapon_zoom_in()
|
|
shaking_hands()
|
|
end
|
|
|
|
function actor_on_weapon_zoom_out()
|
|
level.remove_cam_effector(9921)
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
---------------------------------- Legs --------------------------------------
|
|
------------------------------------------------------------------------------
|
|
local rightleg_anm = {"med1","med4"}
|
|
local leftleg_anm = {"med2","med3"}
|
|
local bothlegs_anm = {"strong1","strong2","strong4"}
|
|
|
|
local limp_flag
|
|
|
|
local mcm_legs_penalty = zzz_player_injuries_mcm.get_config("leg_opt")
|
|
local mcm_legs_min_hp = zzz_player_injuries_mcm.get_config("leg_pen_min_hp")
|
|
local mcm_legs_anm_pwr = zzz_player_injuries_mcm.get_config("leg_anm_pwr")
|
|
local mcm_legs_dmg_min_hp = zzz_player_injuries_mcm.get_config("leg_dmg_min_hp")
|
|
local mcm_legs_new_voice = zzz_player_injuries_mcm.get_config("new_voice_sounds")
|
|
|
|
local legs_speed_tmr = 0
|
|
function limp_speed_slow()
|
|
if not mcm_legs_penalty then return end
|
|
|
|
local tg = time_global()
|
|
if legs_speed_tmr > tg then return end
|
|
legs_speed_tmr = tg + 2000
|
|
|
|
local health, timedhp, maxhp = zzz_player_injuries.health, zzz_player_injuries.timedhp, zzz_player_injuries.maxhp
|
|
|
|
local legs_summ = health.leftleg + timedhp.leftleg + health.rightleg + timedhp.rightleg
|
|
local max_legs_summ = maxhp.leftleg + maxhp.rightleg
|
|
|
|
local legs_ratio = legs_summ / max_legs_summ
|
|
|
|
if legs_ratio >= (mcm_legs_min_hp / 100) then
|
|
speed.remove_speed("bhs_speed_run")
|
|
return
|
|
end
|
|
|
|
local val = normalize(legs_summ, -1, max_legs_summ)
|
|
speed.add_speed("bhs_speed_run", val, false, true)
|
|
end
|
|
|
|
local legs_limp_tmr = 0
|
|
function legs_limp_set()
|
|
if not mcm_legs_penalty then return end
|
|
|
|
local tg = time_global()
|
|
if legs_limp_tmr > tg then return end
|
|
legs_limp_tmr = tg + 2000
|
|
|
|
local health, timedhp, maxhp = zzz_player_injuries.health, zzz_player_injuries.timedhp, zzz_player_injuries.maxhp
|
|
|
|
local right_leg, left_leg = health.leftleg + timedhp.leftleg, health.rightleg + timedhp.rightleg -- right is left
|
|
local legs_summ = right_leg + left_leg
|
|
|
|
local max_right_leg, max_left_leg = maxhp.leftleg, maxhp.rightleg
|
|
local max_legs_summ = max_right_leg + max_left_leg
|
|
|
|
local legs_ratio = legs_summ / max_legs_summ
|
|
|
|
if legs_ratio >= (mcm_legs_min_hp / 100) then
|
|
limp_flag = nil
|
|
return
|
|
end
|
|
|
|
if (right_leg == left_leg) and (legs_summ < max_legs_summ) then
|
|
limp_flag = "both"
|
|
elseif (left_leg < max_left_leg) and (left_leg < right_leg) then
|
|
limp_flag = "left"
|
|
elseif (right_leg < max_right_leg) and (right_leg < left_leg) then
|
|
limp_flag = "right"
|
|
end
|
|
|
|
end
|
|
|
|
local legs_anm_tmr = 0
|
|
function legs_limp_animation()
|
|
if not mcm_legs_penalty then return end
|
|
if not limp_flag then return end
|
|
|
|
local tg = time_global() -- sprint is tearing animations apart, the only way is to increase delay for it
|
|
if legs_anm_tmr > tg then return end
|
|
local add_time = IsMoveState("mcSprint") and 1000 or 500
|
|
legs_anm_tmr = tg + add_time
|
|
|
|
local health, timedhp, maxhp = zzz_player_injuries.health, zzz_player_injuries.timedhp, zzz_player_injuries.maxhp
|
|
|
|
local right_leg, left_leg = health.leftleg + timedhp.leftleg, health.rightleg + timedhp.rightleg
|
|
local max_right_leg, max_left_leg = maxhp.leftleg, maxhp.rightleg
|
|
|
|
if limp_flag == "right" then
|
|
local val = normalize(right_leg, max_right_leg, 0) * mcm_legs_anm_pwr * 3
|
|
level.add_cam_effector("camera_effects\\switch\\" .. rightleg_anm[math.random(#rightleg_anm)] .. ".anm", 99251, false, "", 0, false, val)
|
|
elseif limp_flag == "left" then
|
|
local val = normalize(left_leg, max_left_leg, 0) * mcm_legs_anm_pwr * 3
|
|
level.add_cam_effector("camera_effects\\switch\\" .. leftleg_anm[math.random(#leftleg_anm)] .. ".anm", 99261, false, "", 0, false, val)
|
|
elseif limp_flag == "both" then
|
|
local val = normalize( left_leg + right_leg, max_left_leg + max_right_leg, 0 ) * mcm_legs_anm_pwr * 3
|
|
level.add_cam_effector("camera_effects\\switch\\" .. bothlegs_anm[math.random(#bothlegs_anm)] .. ".anm", 99271, false, "", 0, false, val)
|
|
end
|
|
|
|
end
|
|
|
|
local legs_dmg_tmr = 0
|
|
function legs_limp_damage()
|
|
if not mcm_legs_penalty then return end
|
|
if not IsMoveState("mcSprint") then return end
|
|
|
|
local tg = time_global()
|
|
if legs_dmg_tmr > tg then return end
|
|
legs_dmg_tmr = tg + 2500
|
|
|
|
local health, timedhp, maxhp = zzz_player_injuries.health, zzz_player_injuries.timedhp, zzz_player_injuries.maxhp
|
|
|
|
local right_leg, left_leg = health.leftleg + timedhp.leftleg, health.rightleg + timedhp.rightleg
|
|
local max_right_leg, max_left_leg = maxhp.leftleg, maxhp.rightleg
|
|
|
|
local right_leg_pwr = (right_leg / max_right_leg) < (mcm_legs_dmg_min_hp / 100) and 0.04 or 0
|
|
local left_leg_pwr = (left_leg / max_left_leg) < (mcm_legs_dmg_min_hp / 100) and 0.04 or 0
|
|
|
|
-- return if legs hp higher than mcm setting
|
|
local hit_pwr = (right_leg_pwr + left_leg_pwr) / 2
|
|
if hit_pwr <= 0 then return end
|
|
|
|
-- return if chance didn't proc
|
|
local legs_ratio = (right_leg + left_leg) / (max_right_leg + max_left_leg)
|
|
local chance = (1 - legs_ratio) * 0.5
|
|
if chance < math.random() then return end
|
|
|
|
local file
|
|
if mcm_legs_new_voice then
|
|
local helmet = db.actor:item_in_slot(12) or db.actor:get_current_outfit()
|
|
file = "bhs\\" .. (helmet and "m_" or "") .. "pain_" .. math.random(1, 13)
|
|
else
|
|
file = "actor\\pain_" .. math.random(1, 8)
|
|
end
|
|
|
|
file_to_say = sound_object(file)
|
|
file_to_say:play(db.actor, 0, sound_object.s2d)
|
|
|
|
level.add_pp_effector("blur_bhs.ppe", math.random(655808, 655820), false)
|
|
|
|
db.actor:set_health_ex(db.actor.health - hit_pwr)
|
|
end
|
|
|
|
function actor_on_footstep()
|
|
legs_limp_animation()
|
|
legs_limp_damage()
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
--------------------------------- Torso --------------------------------------
|
|
------------------------------------------------------------------------------
|
|
local mcm_torso_penalty = zzz_player_injuries_mcm.get_config("torso_opt")
|
|
|
|
local torso_tmr = 0
|
|
function torso_penalty()
|
|
if not mcm_torso_penalty then return end
|
|
|
|
local tg = time_global()
|
|
if torso_tmr > tg then return end
|
|
torso_tmr = tg + 1000
|
|
|
|
local torso = zzz_player_injuries.health.torso + zzz_player_injuries.timedhp.torso
|
|
local max_torso = zzz_player_injuries.maxhp.torso
|
|
|
|
local torso_ratio = torso / max_torso
|
|
local cap_health = normalize(torso_ratio, -2, 1)
|
|
|
|
if db.actor.health > cap_health then
|
|
db.actor.health = cap_health
|
|
end
|
|
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
--------------------------------- Head --------------------------------------
|
|
------------------------------------------------------------------------------
|
|
-- zzz_player_injuries.hit_on_update starts it
|
|
local mcm_head_penalty = zzz_player_injuries_mcm.get_config("head_opt")
|
|
local mcm_head_min_dmg = zzz_player_injuries_mcm.get_config("head_pen_min_hp")
|
|
local mcm_head_anm_pwr = zzz_player_injuries_mcm.get_config("head_anm_pwr")
|
|
head_tbl = {}
|
|
|
|
function head_concussion_start(damage)
|
|
if not mcm_head_penalty then return end
|
|
if damage < mcm_head_min_dmg then return end
|
|
|
|
-- new hit during stage 2, override
|
|
if head_tbl.stage and head_tbl.stage == 2 then
|
|
empty_table(head_tbl)
|
|
end
|
|
|
|
-- stage 1
|
|
if (not head_tbl.stage) then
|
|
head_tbl.stage = 1
|
|
head_tbl.damage = damage
|
|
|
|
local eff_pwr = (head_tbl.damage / zzz_player_injuries.maxhp.head) * mcm_head_anm_pwr
|
|
level.add_pp_effector("concussion_bhs.ppe", 99123, false)
|
|
level.set_pp_effector_factor(99123, (eff_pwr))
|
|
|
|
head_snd_off()
|
|
|
|
CreateTimeEvent("bhs_conc_e", "bhs_conc_a", 10, head_concussion_mid)
|
|
end
|
|
|
|
end
|
|
|
|
function head_concussion_mid()
|
|
-- set stage 2
|
|
head_tbl.stage = 2
|
|
|
|
head_snd_on()
|
|
|
|
local snd = sound_object("bhs\\tinnitusx")
|
|
snd:play_no_feedback(db.actor, sound_object.s2d, 0, VEC_ZERO, 1.0, 1.0)
|
|
snd.volume = 2
|
|
|
|
return true
|
|
end
|
|
|
|
local head_tmr = 0
|
|
function head_concussion_update()
|
|
-- stage 2
|
|
if not (head_tbl.stage and head_tbl.stage == 2) then return end
|
|
|
|
local tg = time_global()
|
|
if head_tmr > tg then return end
|
|
head_tmr = tg + 15000
|
|
|
|
-- reduce passive damage over time (5 damage effect needs 2.5 mins)
|
|
head_tbl.damage = head_tbl.damage - 0.5
|
|
|
|
-- remove effect if "damage" drops below zero
|
|
if head_tbl.damage <= 0 then
|
|
empty_table(head_tbl)
|
|
exec_console_cmd("cam_inert 0")
|
|
return
|
|
end
|
|
|
|
-- remove effect if head was healed to full (timedhp on head does not count)
|
|
local head, max_head = zzz_player_injuries.health.head, zzz_player_injuries.maxhp.head
|
|
if head >= max_head then
|
|
empty_table(head_tbl)
|
|
exec_console_cmd("cam_inert 0")
|
|
return
|
|
end
|
|
|
|
-- play ppe and anm
|
|
local eff_pwr = (head_tbl.damage / zzz_player_injuries.maxhp.head) * mcm_head_anm_pwr
|
|
if eff_pwr > math.random() then
|
|
level.add_cam_effector("camera_effects\\wake_up.anm", 96872, false, "", 0, true, eff_pwr)
|
|
end
|
|
|
|
level.add_pp_effector("concussion_post_bhs.ppe", 99133, false)
|
|
level.set_pp_effector_factor(99133, eff_pwr)
|
|
|
|
-- cam_inert xd
|
|
exec_console_cmd("cam_inert " .. eff_pwr)
|
|
|
|
end
|
|
|
|
function head_snd_off()
|
|
_G.amb_vol = math.max(get_console_cmd(2, "snd_volume_eff"), _G.amb_vol or 0)
|
|
exec_console_cmd("snd_volume_eff 0.01")
|
|
head_tbl.vol = _G.amb_vol
|
|
end
|
|
|
|
function head_snd_on()
|
|
exec_console_cmd("snd_volume_eff ".. (head_tbl.vol or tostring(_G.amb_vol)))
|
|
_G.amb_vol = 0
|
|
head_tbl.vol = 0
|
|
end
|
|
|
|
function actor_on_first_update()
|
|
-- for reloading during stage 1
|
|
if head_tbl.stage and head_tbl.stage == 1 then
|
|
head_tbl.stage = 2
|
|
head_snd_on()
|
|
end
|
|
exec_console_cmd("cam_inert 0")
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------
|
|
function get_body_state()
|
|
if not IsMoveState("mcCrouch") then
|
|
return "stand"
|
|
end
|
|
|
|
return IsMoveState("mcAccel") and "low_crouch" or "crouch"
|
|
end
|
|
|
|
function actor_on_update()
|
|
limp_speed_slow()
|
|
legs_limp_set()
|
|
torso_penalty()
|
|
head_concussion_update()
|
|
end
|
|
|
|
function on_option_change()
|
|
mcm_arms_penalty = zzz_player_injuries_mcm.get_config("arm_opt")
|
|
mcm_arms_min_hp = zzz_player_injuries_mcm.get_config("arm_pen_min_hp")
|
|
mcm_arms_cam_pwr = zzz_player_injuries_mcm.get_config("arm_anm_pwr")
|
|
|
|
mcm_legs_penalty = zzz_player_injuries_mcm.get_config("leg_opt")
|
|
mcm_legs_min_hp = zzz_player_injuries_mcm.get_config("leg_pen_min_hp")
|
|
mcm_legs_anm_pwr = zzz_player_injuries_mcm.get_config("leg_anm_pwr")
|
|
mcm_legs_dmg_min_hp = zzz_player_injuries_mcm.get_config("leg_dmg_min_hp")
|
|
mcm_legs_new_voice = zzz_player_injuries_mcm.get_config("new_voice_sounds")
|
|
|
|
mcm_torso_penalty = zzz_player_injuries_mcm.get_config("torso_opt")
|
|
|
|
mcm_head_penalty = zzz_player_injuries_mcm.get_config("head_opt")
|
|
mcm_head_min_dmg = zzz_player_injuries_mcm.get_config("head_pen_min_hp")
|
|
mcm_head_anm_pwr = zzz_player_injuries_mcm.get_config("head_anm_pwr")
|
|
end
|
|
|
|
function save_state(m_data)
|
|
m_data.bhs_head_tbl = head_tbl
|
|
end
|
|
|
|
function load_state(m_data)
|
|
head_tbl = m_data.bhs_head_tbl or {}
|
|
end
|
|
|
|
function on_game_start()
|
|
RegisterScriptCallback("actor_on_weapon_zoom_in", actor_on_weapon_zoom_in)
|
|
RegisterScriptCallback("actor_on_weapon_zoom_out", actor_on_weapon_zoom_out)
|
|
RegisterScriptCallback("actor_on_footstep", actor_on_footstep)
|
|
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
|
|
RegisterScriptCallback("actor_on_update", actor_on_update)
|
|
RegisterScriptCallback("on_option_change", on_option_change)
|
|
RegisterScriptCallback("save_state", save_state)
|
|
RegisterScriptCallback("load_state", load_state)
|
|
end |