-
Автор темы
- #1
super toss:
local FL_ONGROUND = bit.lshift(1, 0)
local WEAPONTYPE_GRENADE = 9
local function clamp(x, min, max)
if x < min then return min end
if x > max then return max end
return x
end
local compensate_throw do
compensate_throw = { }
local auto_strafe_ref = ui.find("Miscellaneous", "Main", "Movement", "Air Strafe")
local render_view_angles = vector()
local local_velocity = vector()
local last_local_velocity = vector()
local function is_grenade(weapon_info)
return weapon_info.weapon_type == WEAPONTYPE_GRENADE
end
local function is_auto_strafe()
return auto_strafe_ref:get()
end
local function ray_circle_intersection(ray, center, r)
if math.abs(ray.x) > math.abs(ray.y) then
local k = ray.y / ray.x
local a = 1 + k * k
local b = -2 * center.x - 2 * k * center.y
local c = center:length2dsqr() - r * r
local d = b * b - 4 * a * c
if d < 0 then -- no intersections, find nearest
local nearest_on_ray = ray * center:dot(ray)
local diff = (nearest_on_ray - center):normalized()
return center + diff * r
elseif d < 0.001 then
local x = -b / (2 * a)
local y = k * x
return vector(x, y)
end
local d_sqrt = math.sqrt(d)
local x = (-b + d_sqrt) / (2 * a)
local y = k * x
local dir1 = vector(x, y)
x = (-b - d_sqrt) / (2 * a)
y = k * x
local dir2 = vector(x, y)
if ray:dot(dir1) > ray:dot(dir2) then
return dir1
end
return dir2
else
local k = ray.x / ray.y
local a = 1 + k * k
local b = -2 * center.y - 2 * k * center.x
local c = center:length2dsqr() - r * r
local d = b * b - 4 * a * c
if d < 0 then -- no intersections, find nearest
local nearest_on_ray = ray * center:dot(ray)
local diff = (nearest_on_ray - center):normalized()
return center + diff * r
elseif d < 0.001 then
local y = -b / (2 * a)
local x = k * y
return vector(x, y)
end
local d_sqrt = math.sqrt(d)
local y = (-b + d_sqrt) / (2 * a)
local x = k * y
local dir1 = vector(x, y)
y = (-b - d_sqrt) / (2 * a)
x = k * y
local dir2 = vector(x, y)
if ray:dot(dir1) > ray:dot(dir2) then
return dir1
end
return dir2
end
end
local function calculate_throw_yaw(wish_dir, vel, throw_velocity, throw_strength)
local dir_normalized = wish_dir:clone()
dir_normalized.z = 0
dir_normalized:normalize()
local cos_pitch = dir_normalized:dot(wish_dir) / wish_dir:length()
local real_dir = ray_circle_intersection(
dir_normalized, vel * 1.25, clamp(throw_velocity * 0.9, 15, 750) * (clamp(throw_strength, 0.0, 1.0) * 0.7 + 0.3) * cos_pitch
) - vel * 1.25
return real_dir:angles().y
end
local function calculate_throw_pitch(wish_dir, wish_z_vel, vel, throw_velocity, throw_strength)
local speed = clamp(throw_velocity * 0.9, 15, 750) * (clamp(throw_strength, 0.0, 1.0) * 0.7 + 0.3)
local cur_vel = vel * 1.25 + wish_dir * speed
local wish_vel = vector(vel.x, vel.y, wish_z_vel) * 1.25 + wish_dir * speed
local ang1 = cur_vel:angles()
local ang2 = wish_dir:angles()
local ang_diff = ang2.x - ang1.x
return ang_diff * (math.cos(math.rad(ang_diff)) + 1) * 0.5
end
local function compensate_prediction(e)
local player = entity.get_local_player()
if player == nil then
return
end
local weapon = player:get_player_weapon()
if weapon == nil then
return
end
local weapon_info = weapon:get_weapon_info()
if weapon_info == nil then
return
end
local vel = e.velocity
local view_angles = e.angles:clone()
local flThrowStrength = clamp(weapon.m_flThrowStrength, 0.0, 1.0)
view_angles.x = view_angles.x + calculate_throw_pitch(
vector():angles(view_angles), clamp(-vel.z, -120, 120), vel, weapon_info.throw_velocity, flThrowStrength
)
local direction = vector():angles(view_angles)
local base_vel = direction * (clamp(weapon_info.throw_velocity * 0.9, 15, 750) * (flThrowStrength * 0.7 + 0.3))
local curent_vel = vel * 1.25 + base_vel
if curent_vel:dot(direction) > 0 then
view_angles.y = calculate_throw_yaw(
direction, vel, weapon_info.throw_velocity, flThrowStrength
)
end
e.angles = view_angles
end
local function compensate_throwable(cmd, player)
local orig_angles = render.camera_angles()
local cmd_angles = cmd.view_angles:clone()
-- fix for movement helpers
if orig_angles ~= cmd_angles then
return
end
local weapon = player:get_player_weapon()
if weapon == nil then
return
end
local weapon_info = weapon:get_weapon_info()
if weapon_info == nil or not is_grenade(weapon_info) then
return
end
if weapon.m_fThrowTime < (globals.curtime - to_time(globals.clock_offset)) then
return
end
local vangle = cmd.view_angles:clone()
local direction = vector():angles(vangle)
local smoothed_velocity = (local_velocity + last_local_velocity) * 0.5
local base_vel = direction * (clamp(weapon_info.throw_velocity * 0.9, 15, 750) * (weapon.m_flThrowStrength * 0.7 + 0.3))
local curent_vel = local_velocity * 1.25 + base_vel
local target_vel = (base_vel + smoothed_velocity * 1.25):normalized()
if curent_vel:dot(direction) > 0.0 then
target_vel = direction
end
cmd.view_angles.x = cmd.view_angles.x + calculate_throw_pitch(
vector():angles(cmd.view_angles),
0.0,
smoothed_velocity,
weapon_info.throw_velocity,
weapon.m_flThrowStrength
)
cmd.view_angles.y = calculate_throw_yaw(
target_vel, last_local_velocity, weapon_info.throw_velocity, weapon.m_flThrowStrength
)
end
local function on_grenade_override_view(e)
compensate_prediction(e)
end
local function on_createmove(cmd)
local player = entity.get_local_player()
local ctx = player:simulate_movement()
ctx:think(1)
local_velocity = ctx.velocity
last_local_velocity = local_velocity
compensate_throwable(cmd, player)
end
events.createmove(on_createmove)
events.grenade_override_view(on_grenade_override_view)
local airstrafe_fix do
local strafer = ui.find("Miscellaneous", "Main", "Movement", "Air Strafe")
local assist = ui.find("Miscellaneous", "Main", "Movement", "Strafe Assist")
local function reset_value_override()
strafer:override()
assist:override()
end
local function update_value_override(cmd)
local me = entity.get_local_player()
if me == nil then
return
end
local weapon = me:get_player_weapon()
if weapon == nil then
return
end
local weapon_info = weapon:get_weapon_info()
if weapon_info == nil or weapon_info.weapon_type ~= 9 then
return
end
if weapon.m_fThrowTime < (globals.curtime - to_time(globals.clock_offset)) then
return
end
local velocity = me.m_vecVelocity
local velocity_angle = math.rad(math.atan2(velocity.y, velocity.x))
if velocity_angle < 0 then
velocity_angle = velocity_angle + 360
end
velocity_angle = velocity_angle - math.floor(velocity_angle / 360.0 + 0.5) * 360.0
local velocity_delta = math.normalize_yaw(
cmd.view_angles.y - velocity_angle
)
strafer:override(false)
assist:override(false)
end
local function on_createmove(cmd)
reset_value_override()
update_value_override(cmd)
end
events.createmove(on_createmove, true)
end
end