Divergent/mods/Dynamic Viewmodel/gamedata/scripts/lual_viewmodel_droop.script

233 lines
5.3 KiB
Plaintext
Raw Normal View History

function conf(...)
return lual_viewmodel_droop_mcm.get_config(...)
end
function on_game_start()
RegisterScriptCallback("actor_on_update", actor_on_update)
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_weapon_fired", actor_on_weapon_fired)
end
function holding_pda(actor)
local slot = actor:active_slot()
return slot == 8 or slot == 14
end
function IsThrowable(item)
-- why check param manually?
return IsBolt(item) or SYS_GetParam(0, item:section(), "class", "") == "II_BOLT" or IsGrenade(item)
end
-- themrdemonized/xray-monolith
-- src/xrGame/actor_defs.h, line 32
local mcFwd = 1
local mcBack = 2
local mcLStrafe = 4
local mcRStrafe = 8
function print_loud(msg)
news_manager.send_tip(db.actor, msg, nil, nil, 30000)
end
local state = {
smoothed_droop = 0,
visual_droop = {0, 0, 0, 0, 0, 0},
}
_G.droop_state = state
function lerp(v0, v1, t)
t = math.min(t, 1)
return v0 + (v1 - v0) * t
end
local cached_offsets = {}
function isScopedWeapon(wpn)
if not wpn then return false end
local has_scopes_sect = SYS_GetParam(0, wpn:section(), "scopes_sect", "") ~= ""
local has_texture = SYS_GetParam(0, wpn:section(), "scope_texture", "") ~= ""
local cobj = wpn:cast_Weapon()
-- If old scopes system
if has_scopes_sect then
if cobj and cobj:IsScopeAttached() or wpn:weapon_is_scope() then
return true
end
else
-- If there is fixed scope or no scope defined, but also if there is a scope texture, it will use the texture for zoomin and considered a scoped weapon
if (wpn:weapon_scope_status() == 1 or wpn:weapon_scope_status() == 0) and has_texture then
return true
end
-- Usual check
if (cobj and cobj:IsScopeAttached() or wpn:weapon_is_scope()) and has_texture then
return true
end
end
return false
end
function get_cached_offset(sec)
local t = cached_offsets[sec]
if t then
return t
end
local hud_sec = SYS_GetParam(0, sec, "hud")
t = {
(function()
local c = str_explode(
utils_xml.is_widescreen()
and SYS_GetParam(0, hud_sec, "hands_position_16x9")
or SYS_GetParam(0, hud_sec, "hands_position")
or "0,0,0",
","
)
return {
tonumber(c[1]) or 0,
tonumber(c[2]) or 0,
tonumber(c[3]) or 0
}
end)(),
(function()
local c = str_explode(
utils_xml.is_widescreen()
and SYS_GetParam(0, hud_sec, "hands_orientation_16x9")
or SYS_GetParam(0, hud_sec, "hands_orientation")
or "0,0,0",
","
)
return {
tonumber(c[1]) or 0,
tonumber(c[2]) or 0,
tonumber(c[3]) or 0
}
end)()
}
cached_offsets[sec] = t
return t
end
local ads = false
local ads_scoped = false
local droop_recovery_ads = 0
local droop_recovery_fire = 0
function target_droop(target, actor)
local rate = ads and conf("droop_rate_ads") or conf("droop_rate")
if ads_scoped or actor:active_detector() then
rate = (1 / 0.4) * 8
end
state.smoothed_droop = lerp(state.smoothed_droop, target, math.min(device().time_delta * rate / 1000, 1))
state.visual_droop[1] = conf("yaw") * state.smoothed_droop
state.visual_droop[2] = conf("pitch") * state.smoothed_droop
state.visual_droop[3] = conf("roll") * state.smoothed_droop
state.visual_droop[4] = conf("right") * state.smoothed_droop
state.visual_droop[5] = conf("up") * state.smoothed_droop
state.visual_droop[6] = conf("forwards") * state.smoothed_droop
end
crosshair_enabled = false
function actor_on_weapon_zoom_in(obj)
crosshair_enabled = get_console_cmd(1, "hud_crosshair")
if crosshair_enabled then
exec_console_cmd("hud_crosshair off")
end
ads = true
ads_scoped = isScopedWeapon(obj)
end
function actor_on_weapon_zoom_out(obj)
if crosshair_enabled then
exec_console_cmd("hud_crosshair on")
end
ads = false
ads_scoped = false
droop_recovery_ads = time_continual()
end
function actor_on_weapon_fired()
droop_recovery_fire = time_continual()
end
function actor_on_update(binder)
local actor = db.actor
if holding_pda(actor) then
return target_droop(0, actor)
end
local item = actor:active_item()
if not item then
return target_droop(0, actor)
end
if IsThrowable(item) then
return target_droop(0, actor)
end
if actor:active_detector() then
return target_droop(0, actor)
end
local move_state = level.actor_moving_state()
local fwd = bit_and(move_state, mcFwd) ~= 0
local back = bit_and(move_state, mcBack) ~= 0
local left = bit_and(move_state, mcLStrafe) ~= 0
local right = bit_and(move_state, mcRStrafe) ~= 0
local strafe = (left or right) and not (left and right)
if fwd and back then
fwd = false
back = false
end
local last_recovery = math.max(
droop_recovery_ads + conf("aim_timeout") * 1000,
droop_recovery_fire + conf("fire_timeout") * 1000
)
local droop
if time_continual() <= last_recovery then
droop = 0
elseif ads then
droop = 0
elseif fwd then
if strafe then
droop = 0.75 -- strafing forwards
else
droop = 1.0 -- walking fowards
end
elseif back then
if strafe then
droop = 0.25 -- strafing back
else
droop = 0 -- walking back
end
elseif strafe then
droop = 0.5 -- strafing
else -- standing sitll
droop = 0
end
local time = (time_continual() - last_recovery) / (conf("recover_length") * 1000)
if (0 < time and time < 1) then
droop = droop * time
end
target_droop(droop, actor)
print(conf("recover_length"))
end