Divergent/mods/Body Health System Realisti.../gamedata/scripts/zzzz_weapon_sway.script

439 lines
15 KiB
Plaintext

------------------------------- mcm stuff --------------------------------------
local weapon_sway_enable = weapon_sway_mcm.get_config("weapon_sway_feature")
local aim_anm = weapon_sway_mcm.get_config("animation_type")
local max_effect_power = weapon_sway_mcm.get_config("max_effect_power")
local sway_keybind = weapon_sway_mcm.get_config("sway_keybind")
local power_stand = weapon_sway_mcm.get_config("power_stand")
local power_crouch = weapon_sway_mcm.get_config("power_crouch")
local power_low_crouch = weapon_sway_mcm.get_config("power_low_crouch")
local power_stand_scoped = weapon_sway_mcm.get_config("power_stand_scoped")
local power_crouch_scoped = weapon_sway_mcm.get_config("power_crouch_scoped")
local power_low_crouch_scoped = weapon_sway_mcm.get_config("power_low_crouch_scoped")
local weapon_mount_feature = weapon_sway_mcm.get_config("weapon_mount_feature")
local weapon_mounted_power = weapon_sway_mcm.get_config("weapon_mounted_power")
local y_axis_mounted_distance = weapon_sway_mcm.get_config("y_axis_mounted_distance")
local weapon_handling_mult = weapon_sway_mcm.get_config("handling_mult")
local weight_factor = weapon_sway_mcm.get_config("weight_factor")
local max_power_weight = weapon_sway_mcm.get_config("max_power_weight")
local hold_breath_feature = weapon_sway_mcm.get_config("hold_breath_feature")
local enable_breath_sound = weapon_sway_mcm.get_config("enable_breath_sound")
local breath_restore_mult = weapon_sway_mcm.get_config("breath_restore_mult")
local max_hold_breath_time = weapon_sway_mcm.get_config("max_hold_breath_time")
local hold_breath_mult = weapon_sway_mcm.get_config("hold_breath_mult")
local release_breath_mult = weapon_sway_mcm.get_config("release_breath_mult")
local weapon_sway_debug = weapon_sway_mcm.get_config("debugx")
------------------------------- mcm patch --------------------------------------
local bhs_patch = 1
local effects_mult = zzz_player_injuries.effects_mult -- If you changed this in BHS script - you need to change it here too
-- demonized's and Raven's magic, i dont even know how it works
if zzz_player_injuries then
zzz_player_injuries.RegisterScriptCallback = function(k, func)
if not (k == "actor_on_weapon_zoom_in") then
_G.RegisterScriptCallback(k, func)
end
end
end
------------------------------- main ----------------------------------
local zoom_flag = false
local holding_breath = false
local breath_held_for = 0
function weapon_sway()
local wpn = db.actor:active_item()
if not (wpn and IsWeapon(wpn)) then return end
if (IsMelee(wpn)) then return end
local wpn_sec = wpn:section()
if not wpn_sec then return end
local wpn_scoped = wpn:weapon_is_scope()
local handling = utils_ui.prop_handling(wpn, wpn_sec)
-- anm power mults
local body_mult = get_body_state_power(wpn, wpn_scoped) or 1 -- power based on body state
local extra_mult = wpn_scoped and 0.02 or 0.1 -- reduce scoped anm power
local mount_mult = wpn_mounted() and weapon_mounted_power or 1 -- weapon mounted
local handling_mult = handling and ((2.5 - 0.02 * handling * 100)^weapon_handling_mult) or 1 -- handling
local weight = get_weight_power(wpn_sec) and clamp(get_weight_power(wpn_sec) * weight_factor, 0.01, max_power_weight) or 1 -- weight factor
local breath_mult = holding_breath and hold_breath_mult or 1 + breath_held_for * release_breath_mult -- breath mult
-- Summary power
local cam_power = body_mult * weight * extra_mult * mount_mult * breath_mult * handling_mult
cam_power = clamp(cam_power, 0, max_effect_power)
-- Play anim or Change its power
if level.check_cam_effector(99215) then
level.set_cam_effector_factor(99215, cam_power)
else
level.add_cam_effector("weapon_sway\\sway_" .. aim_anm .. ".anm", 99215, true, "", 0, true, cam_power)
end
-- dbg
if not weapon_sway_debug then return end
actor_menu.set_msg(1, strformat("weight_mult: %s | handling_mult: %s | Total Power: %s", r(weight), r(handling_mult), r(cam_power)))
end
function weapon_sway_remove()
level.remove_cam_effector(99215)
end
----------------------- manage breath ------------------------
-- start holding breath
local press_tg = 0
function on_key_press(key)
if not weapon_sway_enable then return end
if not hold_breath_feature then return end
-- when we aiming and press "hold breath" button
if not (zoom_flag and key == sway_keybind) then return end
-- set "holding_breath" to TRUE
holding_breath = true
local tg = time_global()
if tg < press_tg then return end
press_tg = tg + 2000 -- against people who trying their best to break it ;]
-- and play hold sound
breath_snd_hold()
end
-- increase/decrease breath hold
local breath_tmr = 0
function breath_update()
local tg = time_global()
if tg < breath_tmr then return end
breath_tmr = tg + 250
-- increase "breath_held_for" if hold, decrease "breath_held_for" otherwise
breath_held_for = holding_breath and breath_held_for + 0.25 or breath_held_for - 0.25 * breath_restore_mult
breath_held_for = clamp(breath_held_for, 0, max_hold_breath_time)
-- end holding breath if reached max time
if breath_held_for < max_hold_breath_time then return end
-- to give at least 1 sec if someone tries to spam it xd
breath_held_for = breath_held_for - 1
-- set "holding_breath" to FALSE
holding_breath = false
-- and play release sound
breath_snd_release()
end
-- end holding breath on key
function on_key_release(key)
if not (zoom_flag and holding_breath and key == sway_keybind) then return end
-- set "holding_breath" to FALSE
holding_breath = false
-- if breath was held for more than 3 seconds - play release sound
if breath_held_for > 3 then
breath_snd_release()
end
end
function breath_snd_hold()
if not enable_breath_sound then return end
local snd_hold = sound_object("weapon_sway\\hold_1")
snd_hold:play_no_feedback(db.actor, sound_object.s2d, 0, VEC_ZERO, 1.0, 1.0)
end
function breath_snd_release()
if not enable_breath_sound then return end
local snd_release = sound_object("weapon_sway\\release_1")
snd_release:play_no_feedback(db.actor, sound_object.s2d, 0, VEC_ZERO, 1.0, 1.0)
end
----------------------- power mults ------------------------
function get_body_state_power(wpn, scope)
local body_state = get_body_state()
if not body_state then return end
local body_mult = 1
body_mult = scope and power_stand_scoped or power_stand
if body_state == "crouch" then
body_mult = scope and power_crouch_scoped or power_crouch
elseif body_state == "low_crouch" then
body_mult = scope and power_low_crouch_scoped or power_low_crouch
end
return body_mult
end
function wpn_mounted()
if not weapon_mount_feature then return end
local rp_diff = get_rp_diff()
return rp_diff > 0.1
end
function get_weight_power(wpn_sec)
if not ini_sys:section_exist(wpn_sec, "inv_weight") then return end
return ini_sys:r_float_ex(wpn_sec, "inv_weight")
end
----------------------- utils ------------------------
function get_body_state()
local crouch = IsMoveState('mcCrouch')
local accel = IsMoveState('mcAccel')
local body_st = "stand"
if crouch then
if accel then
body_st = "low_crouch"
else
body_st = "crouch"
end
end
return body_st
end
function ray_pick_dir(add_x, add_y, add_z, range)
local pos = device().cam_pos
local dir = device().cam_dir
local vec_x = dir.x + add_x
local vec_y = dir.y + add_y
local vec_z = dir.z + add_z
vec_x = clamp( r(vec_x), -1, 1)
vec_y = clamp( r(vec_y), -1, 1)
vec_z = clamp( r(vec_z), -1, 1)
-- dbg
if weapon_sway_debug then
printf("--------------------")
printf("dir: %s", dir)
printf("edited dir: x: %s, y: %s, z: %s", vec_x, vec_y, vec_z)
end
local pick = ray_pick()
pick:set_position(pos)
pick:set_direction(vector():set(vec_x, vec_y, vec_z))
pick:set_flags(2)
pick:set_range(range)
pick:query()
local distance = pick:get_distance()
return distance
end
function normal_ray_pick()
local pos = device().cam_pos
local dir = device().cam_dir
local pick = ray_pick()
pick:set_position(pos)
pick:set_direction(dir)
pick:set_flags(2)
pick:set_range(0.85)
pick:query()
local distance = pick:get_distance()
return distance
end
function get_rp_diff()
local default_raycast = normal_ray_pick()
local x = 0
local y = y_axis_mounted_distance
local z = 0
local range = 0.85
local custom_raycast = r(ray_pick_dir(x, y, z, range))
local diff = custom_raycast - default_raycast
return diff
end
function r(val)
return round_idp(val, 2)
end
----------------------- BHS compatibility ------------------------
if bhs_patch and zzz_player_injuries then
function bhs_sway_func()
local wpn = db.actor:active_item()
if not (wpn and IsWeapon(wpn)) then return end
if (IsMelee(wpn)) then return end
local wpn_sec = wpn:section()
if not wpn_sec then return end
local wpn_scoped = wpn:weapon_is_scope()
local handling = utils_ui.prop_handling(wpn, wpn_sec)
local body_state = get_body_state()
local left_arm = (zzz_player_injuries.health.rightarm + zzz_player_injuries.timedhp.rightarm) * effects_mult
left_arm = left_arm >=1 and left_arm or 0.75
local right_arm = (zzz_player_injuries.health.leftarm + zzz_player_injuries.timedhp.leftarm) * effects_mult
right_arm = right_arm >=1 and right_arm or 0.75
local arms_sum = left_arm + right_arm
local max_arms_sum = (zzz_player_injuries.maxhp.rightarm + zzz_player_injuries.maxhp.leftarm) * effects_mult
-- anm power mults
local bhs_cam_power = 1
local body_mult = get_body_state_power(wpn, wpn_scoped) or 1 -- power based on body state
local extra_mult = wpn_scoped and 0.02 or 0.1 -- reduce scoped anm power
local mount_mult = wpn_mounted() and weapon_mounted_power or 1 -- weapon mounted
local handling_mult = handling and ((2.5 - 0.02 * handling * 100)^weapon_handling_mult) or 1 -- handling
local weight = get_weight_power(wpn_sec) and clamp(get_weight_power(wpn_sec) * weight_factor, 0.01, max_power_weight) or 1 -- weight factor
local breath_mult = holding_breath and hold_breath_mult or 1 + breath_held_for * release_breath_mult -- breath mult
-- Summary Weapon Sway power
local cam_power = body_mult * weight * extra_mult * mount_mult * breath_mult * handling_mult
cam_power = clamp(cam_power, 0, max_effect_power)
-- BHS
if arms_sum < (max_arms_sum * (zzz_player_injuries_mcm.get_config("arm_penalty_minimum_hp") * 0.05)) then
if (left_arm < right_arm / 1.5) or (right_arm < left_arm / 1.5) then
bhs_cam_power = 1.15 * weight / arms_sum
bhs_cam_power = (body_state == "crouch") and (0.8 * weight / arms_sum) or bhs_cam_power
bhs_cam_power = (body_state == "low_crouch") and (0.4 * weight / arms_sum) or bhs_cam_power
else
bhs_cam_power = 0.8 * weight / arms_sum
bhs_cam_power = (body_state == "crouch") and (0.55 * weight / arms_sum) or bhs_cam_power
bhs_cam_power = (body_state == "low_crouch") and (0.3 * weight / arms_sum) or bhs_cam_power
end
-- Summary BHS power
bhs_cam_power = clamp((bhs_cam_power * mount_mult * breath_mult * handling_mult), 0, 3)
bhs_cam_power = bhs_cam_power * (zzz_player_injuries_mcm.get_config("arm_animation_power"))
local cam_power_scope = bhs_cam_power * 0.2
if wpn:weapon_is_scope() then
bhs_cam_power = cam_power_scope
end
-- Play anim or Change its power
if level.check_cam_effector(99215) then
level.set_cam_effector_factor(99215, bhs_cam_power)
else
level.add_cam_effector("weapon_sway\\sway_" .. aim_anm .. ".anm", 99215, true, "", 0, true, bhs_cam_power)
end
-- Weapon Sway
elseif weapon_sway_enable then
-- Play anim or Change its power
if level.check_cam_effector(99215) then
level.set_cam_effector_factor(99215, cam_power)
else
level.add_cam_effector("weapon_sway\\sway_" .. aim_anm .. ".anm", 99215, true, "", 0, true, cam_power)
end
end
-- dbg
if not weapon_sway_debug then return end
news_manager.send_tip(db.actor, string.format("y-axis diff: %s", ( get_rp_diff() )), 0, nil, 1500)
if not hold_breath_feature then return end
news_manager.send_tip(db.actor, string.format("Breath being held for: %s", breath_held_for), 0, nil, 1500)
end
end
----------------------- cb ------------------------
function actor_on_weapon_zoom_in(wpn)
zoom_flag = true
end
function actor_on_weapon_zoom_out(wpn)
weapon_sway_remove()
zoom_flag = false
if not (holding_breath) then return end
holding_breath = false
-- if breath was held for more than 3 seconds - play release sound
if breath_held_for > 3 then
breath_snd_release()
end
end
local tg_act = 0
function main_update()
local tg = time_global()
if tg < tg_act then return end
tg_act = tg + 250
if weapon_sway_enable and zoom_flag then
if bhs_patch and zzz_player_injuries and bhs_sway_func then
bhs_sway_func()
else
weapon_sway()
end
end
-- dbg
if not weapon_sway_debug then return end
news_manager.send_tip(db.actor, string.format("y-axis diff: %s", ( get_rp_diff() )), 0, nil, 1500)
if not hold_breath_feature then return end
news_manager.send_tip(db.actor, string.format("Breath being held for: %s", breath_held_for), 0, nil, 1500)
end
function on_option_change()
weapon_sway_enable = weapon_sway_mcm.get_config("weapon_sway_feature")
aim_anm = weapon_sway_mcm.get_config("animation_type")
max_effect_power = weapon_sway_mcm.get_config("max_effect_power")
sway_keybind = weapon_sway_mcm.get_config("sway_keybind")
power_stand = weapon_sway_mcm.get_config("power_stand")
power_crouch = weapon_sway_mcm.get_config("power_crouch")
power_low_crouch = weapon_sway_mcm.get_config("power_low_crouch")
power_stand_scoped = weapon_sway_mcm.get_config("power_stand_scoped")
power_crouch_scoped = weapon_sway_mcm.get_config("power_crouch_scoped")
power_low_crouch_scoped = weapon_sway_mcm.get_config("power_low_crouch_scoped")
weapon_mount_feature = weapon_sway_mcm.get_config("weapon_mount_feature")
weapon_mounted_power = weapon_sway_mcm.get_config("weapon_mounted_power")
y_axis_mounted_distance = weapon_sway_mcm.get_config("y_axis_mounted_distance")
weapon_handling_mult = weapon_sway_mcm.get_config("handling_mult")
weight_factor = weapon_sway_mcm.get_config("weight_factor")
max_power_weight = weapon_sway_mcm.get_config("max_power_weight")
hold_breath_feature = weapon_sway_mcm.get_config("hold_breath_feature")
enable_breath_sound = weapon_sway_mcm.get_config("enable_breath_sound")
breath_restore_mult = weapon_sway_mcm.get_config("breath_restore_mult")
max_hold_breath_time = weapon_sway_mcm.get_config("max_hold_breath_time")
hold_breath_mult = weapon_sway_mcm.get_config("hold_breath_mult")
release_breath_mult = weapon_sway_mcm.get_config("release_breath_mult")
weapon_sway_debug = weapon_sway_mcm.get_config("debugx")
end
function on_game_start()
RegisterScriptCallback("on_key_press", on_key_press)
RegisterScriptCallback("actor_on_update", breath_update)
RegisterScriptCallback("on_key_release", on_key_release)
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_update", main_update)
RegisterScriptCallback("on_option_change", on_option_change)
end