233 lines
5.3 KiB
Plaintext
233 lines
5.3 KiB
Plaintext
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
|