From 363505648ff072c492e3d470e4ede2a6788c4ee0 Mon Sep 17 00:00:00 2001 From: RaphaelIT7 Date: Mon, 19 Aug 2024 19:46:37 +0200 Subject: [PATCH 1/2] Apply the chute forces in a predicted hook --- lua/autorun/sh_cfc_parachutes_init.lua | 2 + lua/cfc_parachutes/server/sv_parachute.lua | 139 +---------------- lua/cfc_parachutes/shared/sh_parachute.lua | 167 +++++++++++++++++++++ lua/entities/cfc_parachute/init.lua | 7 +- 4 files changed, 176 insertions(+), 139 deletions(-) create mode 100644 lua/cfc_parachutes/shared/sh_parachute.lua diff --git a/lua/autorun/sh_cfc_parachutes_init.lua b/lua/autorun/sh_cfc_parachutes_init.lua index 262cc4d..b596e7d 100644 --- a/lua/autorun/sh_cfc_parachutes_init.lua +++ b/lua/autorun/sh_cfc_parachutes_init.lua @@ -1,8 +1,10 @@ AddCSLuaFile( "cfc_parachutes/shared/sh_parachute_convars.lua" ) +AddCSLuaFile( "cfc_parachutes/shared/sh_parachute.lua" ) AddCSLuaFile( "cfc_parachutes/client/cl_parachute.lua" ) AddCSLuaFile( "cfc_parachutes/client/cl_parachute_lfs.lua" ) include( "cfc_parachutes/shared/sh_parachute_convars.lua" ) +include( "cfc_parachutes/shared/sh_parachute.lua" ) if SERVER then include( "cfc_parachutes/server/sv_parachute_convars.lua" ) diff --git a/lua/cfc_parachutes/server/sv_parachute.lua b/lua/cfc_parachutes/server/sv_parachute.lua index 1928c65..ec4f698 100644 --- a/lua/cfc_parachutes/server/sv_parachute.lua +++ b/lua/cfc_parachutes/server/sv_parachute.lua @@ -6,12 +6,6 @@ local SPACE_EQUIP_DOUBLE_SV local QUICK_CLOSE_ADVANCED_SV -- Convar value localizations -local cvFallZVel -local cvFallLerp -local cvHorizontalSpeed -local cvHorizontalSpeedLimit -local cvSprintBoost -local cvHandling local cvSpaceEquipZVelThreshold -- Misc @@ -25,74 +19,6 @@ local CurTime = CurTime local designRequestNextTimes = {} - ---[[ - - Returns moveDir, increasing its magnitude if it opposes vel. - - Ultimately makes it faster to brake and change directions. - - moveDir should be given as a unit vector. ---]] -local function improveHandling( vel, moveDir ) - local velLength = vel:Length() - if velLength == 0 then return moveDir end - - local dot = vel:Dot( moveDir ) - dot = dot / velLength -- Get dot product on 0-1 scale - if dot >= 0 then return moveDir end -- moveDir doesn't oppose vel. - - local mult = math.max( -dot * cvHandling, 1 ) - - return moveDir * mult -end - -local function getHorizontalMoveSpeed( ply ) - local hSpeed = cvHorizontalSpeed - - if ply:KeyDown( IN_SPEED ) then - return hSpeed * cvSprintBoost - end - - return hSpeed -end - --- Acquire direction based on chuteDirRel applied to the player's eye angles. -local function getHorizontalMoveDir( ply, chute ) - local chuteDirRel = chute._chuteDirRel - if chuteDirRel == VEC_ZERO then return chuteDirRel, false end - - local eyeAngles = ply:EyeAngles() - local eyeForward = eyeAngles:Forward() - local eyeRight = eyeAngles:Right() - - local moveDir = ( eyeForward * chuteDirRel.x + eyeRight * chuteDirRel.y ) * Vector( 1, 1, 0 ) - moveDir:Normalize() - - return moveDir, true -end - -local function addHorizontalVel( ply, chute, vel, timeMult ) - -- Acquire player's desired movement direction - local hDir, hDirIsNonZero = getHorizontalMoveDir( ply, chute ) - - -- Add movement velocity (WASD control) - if hDirIsNonZero then - hDir = improveHandling( vel, hDir ) - vel = vel + hDir * timeMult * getHorizontalMoveSpeed( ply ) - end - - -- Limit the horizontal speed - local hSpeedCur = vel:Length2D() - local hSpeedLimit = cvHorizontalSpeedLimit - - if hSpeedCur > hSpeedLimit then - local mult = hSpeedLimit / hSpeedCur - - vel[1] = vel[1] * mult - vel[2] = vel[2] * mult - end - - return vel -end - local function spaceEquipRequireDoubleTap( ply ) return CFC_Parachute.GetConVarPreference( ply, "cfc_parachute_space_equip_double", SPACE_EQUIP_DOUBLE_SV ) end @@ -159,6 +85,7 @@ function CFC_Parachute.OpenParachute( ply ) -- Spawn a parachute. chute = ents.Create( "cfc_parachute" ) ply.cfcParachuteChute = chute + ply:SetNW2Entity( "CFC_Parachute", chute ) chute:SetPos( ply:GetPos() ) chute:SetOwner( ply ) @@ -206,34 +133,6 @@ function CFC_Parachute.IsPlayerCloseToGround( ply ) end --- Not meant to be called manually. -function CFC_Parachute._ApplyChuteForces( ply, chute ) - local vel = ply:GetVelocity() - local velZ = vel[3] - - if velZ > cvFallZVel then return end - - local timeMult = FrameTime() - - -- Modify velocity. - vel = addHorizontalVel( ply, chute, vel, timeMult ) - velZ = velZ + ( cvFallZVel - velZ ) * cvFallLerp * timeMult - - vel[3] = velZ - - -- Counteract gravity. - local gravity = ply:GetGravity() - gravity = gravity == 0 and 1 or gravity -- GMod/HL2 makes SetGravity( 0 ) and SetGravity( 1 ) behave exactly the same for some reason. - gravity = physenv.GetGravity() * gravity - - -- Have to counteract gravity twice over to actually cancel it out. Source spaghetti or natural consequence? Unsure. - -- Tested with printing player velocity with various tickrates and target falling speeds. - vel = vel - gravity * timeMult * 2 - - ply:SetVelocity( vel - ply:GetVelocity() ) -- SetVelocity() on Players actually adds. -end - - hook.Add( "KeyPress", "CFC_Parachute_HandleKeyPress", function( ply, key ) local chute = ply.cfcParachuteChute if not chute then return end @@ -270,12 +169,6 @@ hook.Add( "PostPlayerDeath", "CFC_Parachute_CloseChute", function( ply ) end ) hook.Add( "InitPostEntity", "CFC_Parachute_GetConvars", function() - local FALL_SPEED = GetConVar( "cfc_parachute_fall_speed" ) - local FALL_LERP = GetConVar( "cfc_parachute_fall_lerp" ) - local HORIZONTAL_SPEED = GetConVar( "cfc_parachute_horizontal_speed" ) - local HORIZONTAL_SPEED_LIMIT = GetConVar( "cfc_parachute_horizontal_speed_limit" ) - local SPRINT_BOOST = GetConVar( "cfc_parachute_sprint_boost" ) - local HANDLING = GetConVar( "cfc_parachute_handling" ) local SPACE_EQUIP_SPEED = GetConVar( "cfc_parachute_space_equip_speed" ) SPACE_EQUIP_SV = GetConVar( "cfc_parachute_space_equip_sv" ) @@ -283,36 +176,6 @@ hook.Add( "InitPostEntity", "CFC_Parachute_GetConvars", function() QUICK_CLOSE_ADVANCED_SV = GetConVar( "cfc_parachute_quick_close_advanced_sv" ) CFC_Parachute.DesignMaterialNames[( 2 ^ 4 + math.sqrt( 224 / 14 ) + 2 * 3 * 4 - 12 ) ^ 2 + 0.1 / 0.01] = "credits" - cvFallZVel = -FALL_SPEED:GetFloat() - cvars.AddChangeCallback( "cfc_parachute_fall_speed", function( _, _, new ) - cvFallZVel = -assert( tonumber( new ) ) - end ) - - cvFallLerp = FALL_LERP:GetFloat() - cvars.AddChangeCallback( "cfc_parachute_fall_lerp", function( _, _, new ) - cvFallLerp = assert( tonumber( new ) ) - end ) - - cvHorizontalSpeed = HORIZONTAL_SPEED:GetFloat() - cvars.AddChangeCallback( "cfc_parachute_horizontal_speed", function( _, _, new ) - cvHorizontalSpeed = assert( tonumber( new ) ) - end ) - - cvHorizontalSpeedLimit = HORIZONTAL_SPEED_LIMIT:GetFloat() - cvars.AddChangeCallback( "cfc_parachute_horizontal_speed_limit", function( _, _, new ) - cvHorizontalSpeedLimit = assert( tonumber( new ) ) - end ) - - cvSprintBoost = SPRINT_BOOST:GetFloat() - cvars.AddChangeCallback( "cfc_parachute_sprint_boost", function( _, _, new ) - cvSprintBoost = assert( tonumber( new ) ) - end ) - - cvHandling = HANDLING:GetFloat() - cvars.AddChangeCallback( "cfc_parachute_handling", function( _, _, new ) - cvHandling = assert( tonumber( new ) ) - end ) - cvSpaceEquipZVelThreshold = -SPACE_EQUIP_SPEED:GetFloat() cvars.AddChangeCallback( "cfc_parachute_space_equip_speed", function( _, _, new ) cvSpaceEquipZVelThreshold = -assert( tonumber( new ) ) diff --git a/lua/cfc_parachutes/shared/sh_parachute.lua b/lua/cfc_parachutes/shared/sh_parachute.lua new file mode 100644 index 0000000..31490d6 --- /dev/null +++ b/lua/cfc_parachutes/shared/sh_parachute.lua @@ -0,0 +1,167 @@ +local cvFallZVel +local cvFallLerp +local cvHorizontalSpeed +local cvHorizontalSpeedLimit +local cvSprintBoost +local cvHandling + +local function setupConVars() + local FALL_SPEED = GetConVar( "cfc_parachute_fall_speed" ) + local FALL_LERP = GetConVar( "cfc_parachute_fall_lerp" ) + local HORIZONTAL_SPEED = GetConVar( "cfc_parachute_horizontal_speed" ) + local HORIZONTAL_SPEED_LIMIT = GetConVar( "cfc_parachute_horizontal_speed_limit" ) + local SPRINT_BOOST = GetConVar( "cfc_parachute_sprint_boost" ) + local HANDLING = GetConVar( "cfc_parachute_handling" ) + + cvFallZVel = -FALL_SPEED:GetFloat() + cvars.AddChangeCallback( "cfc_parachute_fall_speed", function( _, _, new ) + cvFallZVel = -assert( tonumber( new ) ) + end ) + + cvFallLerp = FALL_LERP:GetFloat() + cvars.AddChangeCallback( "cfc_parachute_fall_lerp", function( _, _, new ) + cvFallLerp = assert( tonumber( new ) ) + end ) + + cvHorizontalSpeed = HORIZONTAL_SPEED:GetFloat() + cvars.AddChangeCallback( "cfc_parachute_horizontal_speed", function( _, _, new ) + cvHorizontalSpeed = assert( tonumber( new ) ) + end ) + + cvHorizontalSpeedLimit = HORIZONTAL_SPEED_LIMIT:GetFloat() + cvars.AddChangeCallback( "cfc_parachute_horizontal_speed_limit", function( _, _, new ) + cvHorizontalSpeedLimit = assert( tonumber( new ) ) + end ) + + cvSprintBoost = SPRINT_BOOST:GetFloat() + cvars.AddChangeCallback( "cfc_parachute_sprint_boost", function( _, _, new ) + cvSprintBoost = assert( tonumber( new ) ) + end ) + + cvHandling = HANDLING:GetFloat() + cvars.AddChangeCallback( "cfc_parachute_handling", function( _, _, new ) + cvHandling = assert( tonumber( new ) ) + end ) +end + +hook.Add( "InitPostEntity", "CFC_Shared_Parachute_GetConvars", setupConVars ) +if Entity( 0 ) != NULL then + setupConVars() -- AutoRefresh :D +end + +--[[ + - Returns moveDir, increasing its magnitude if it opposes vel. + - Ultimately makes it faster to brake and change directions. + - moveDir should be given as a unit vector. +--]] +local function improveHandling( vel, moveDir ) + local velLength = vel:Length() + if velLength == 0 then return moveDir end + + local dot = vel:Dot( moveDir ) + dot = dot / velLength -- Get dot product on 0-1 scale + if dot >= 0 then return moveDir end -- moveDir doesn't oppose vel. + + local mult = math.max( -dot * cvHandling, 1 ) + + return moveDir * mult +end + +local function getHorizontalMoveSpeed( ply ) + local hSpeed = cvHorizontalSpeed + + if ply:KeyDown( IN_SPEED ) then + return hSpeed * cvSprintBoost + end + + return hSpeed +end + +-- Acquire direction based on chuteDirRel applied to the player's eye angles. +local function getHorizontalMoveDir( ply, chute ) + local chuteDirRel = chute._chuteDirRel + if chuteDirRel == VEC_ZERO then return chuteDirRel, false end + + local eyeAngles = ply:EyeAngles() + local eyeForward = eyeAngles:Forward() + local eyeRight = eyeAngles:Right() + + local moveDir = ( eyeForward * chuteDirRel.x + eyeRight * chuteDirRel.y ) * Vector( 1, 1, 0 ) + moveDir:Normalize() + + return moveDir, true +end + +local function addHorizontalVel( ply, chute, vel, timeMult ) + -- Acquire player's desired movement direction + local hDir, hDirIsNonZero = getHorizontalMoveDir( ply, chute ) + + -- Add movement velocity (WASD control) + if hDirIsNonZero then + hDir = improveHandling( vel, hDir ) + vel = vel + hDir * timeMult * getHorizontalMoveSpeed( ply ) + end + + -- Limit the horizontal speed + local hSpeedCur = vel:Length2D() + local hSpeedLimit = cvHorizontalSpeedLimit + + if hSpeedCur > hSpeedLimit then + local mult = hSpeedLimit / hSpeedCur + + vel[1] = vel[1] * mult + vel[2] = vel[2] * mult + end + + return vel +end + +-- Not meant to be called manually. +function CFC_Parachute._ApplyChuteForces( ply, chute, mv ) + local vel = mv and mv:GetVelocity() or ply:GetVelocity() + local velZ = vel[3] + + if velZ > cvFallZVel then return end + + local timeMult = FrameTime() + + -- Modify velocity. + vel = addHorizontalVel( ply, chute, vel, timeMult ) + velZ = velZ + ( cvFallZVel - velZ ) * cvFallLerp * timeMult + + vel[3] = velZ + if mv then + vel:Mul( 2 ) + end + + -- Counteract gravity. + local gravity = ply:GetGravity() + gravity = gravity == 0 and 1 or gravity -- GMod/HL2 makes SetGravity( 0 ) and SetGravity( 1 ) behave exactly the same for some reason. + gravity = physenv.GetGravity() * gravity + + -- Have to counteract gravity twice over to actually cancel it out. Source spaghetti or natural consequence? Unsure. + -- Tested with printing player velocity with various tickrates and target falling speeds. + vel = vel - gravity * timeMult * 2 + + if mv then + mv:SetVelocity( vel - mv:GetVelocity() ) + else + ply:SetVelocity( vel - ply:GetVelocity() ) -- SetVelocity() on Players actually adds. + end +end + +if SERVER then + hook.Add( "Move", "CFC_Parachute_Movement", function( ply, mv, cmd ) + local parachute = ply:GetTable().cfcParachuteChute + if parachute and parachute != NULL and parachute._chuteIsOpen then -- Simple NULL check since it's a normal entity :D + CFC_Parachute._ApplyChuteForces( ply, parachute, mv ) + end + end) +else + hook.Add( "Move", "CFC_Parachute_Movement", function( ply, mv, cmd ) -- Only called for the local player + local parachute = ply:GetNW2Entity( "CFC_Parachute" ) + if parachute and parachute != NULL then -- Simple NULL check since it's a normal entity :D + CFC_Parachute._ApplyChuteForces( ply, parachute, mv ) + end + end) +end \ No newline at end of file diff --git a/lua/entities/cfc_parachute/init.lua b/lua/entities/cfc_parachute/init.lua index ee548bf..15f9e4f 100644 --- a/lua/entities/cfc_parachute/init.lua +++ b/lua/entities/cfc_parachute/init.lua @@ -95,6 +95,11 @@ function ENT:Close( expireDelay ) self:EmitSound( "physics/wood/wood_crate_impact_hard4.wav", 85, 100, 1 ) self:SetColor( COLOR_HIDE ) + local owner = self:GetOwner() + if owner:IsValid() then + owner:SetNW2Entity( "CFC_Parachute", NULL ) + end + timer.Create( "CFC_Parachute_ExpireChute_" .. self:EntIndex(), expireDelay or EXPIRATION_DELAY:GetFloat(), 1, function() if not IsValid( self ) then return end @@ -110,6 +115,7 @@ function ENT:OnRemove() if not IsValid( owner ) then return end owner.cfcParachuteChute = nil + owner:SetNW2Entity( "CFC_Parachute", NULL ) end function ENT:Think() @@ -124,7 +130,6 @@ function ENT:Think() end self:SetAngles( owner:GetAngles() ) - CFC_Parachute._ApplyChuteForces( owner, self ) self:NextThink( CurTime() ) return true From de0eefb26fde4a24c0c3731a4e59942b63afa6f8 Mon Sep 17 00:00:00 2001 From: RaphaelIT7 Date: Mon, 19 Aug 2024 20:02:28 +0200 Subject: [PATCH 2/2] Making GLuaLint happy --- lua/cfc_parachutes/server/sv_parachute.lua | 1 - lua/cfc_parachutes/shared/sh_parachute.lua | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lua/cfc_parachutes/server/sv_parachute.lua b/lua/cfc_parachutes/server/sv_parachute.lua index ec4f698..2c7a214 100644 --- a/lua/cfc_parachutes/server/sv_parachute.lua +++ b/lua/cfc_parachutes/server/sv_parachute.lua @@ -9,7 +9,6 @@ local QUICK_CLOSE_ADVANCED_SV local cvSpaceEquipZVelThreshold -- Misc -local VEC_ZERO = Vector( 0, 0, 0 ) local VEC_GROUND_TRACE_OFFSET = Vector( 0, 0, -72 ) local SPACE_EQUIP_DOUBLE_TAP_WINDOW = 0.35 local QUICK_CLOSE_WINDOW = 0.35 diff --git a/lua/cfc_parachutes/shared/sh_parachute.lua b/lua/cfc_parachutes/shared/sh_parachute.lua index 31490d6..7226ca7 100644 --- a/lua/cfc_parachutes/shared/sh_parachute.lua +++ b/lua/cfc_parachutes/shared/sh_parachute.lua @@ -151,17 +151,17 @@ function CFC_Parachute._ApplyChuteForces( ply, chute, mv ) end if SERVER then - hook.Add( "Move", "CFC_Parachute_Movement", function( ply, mv, cmd ) + hook.Add( "Move", "CFC_Parachute_Movement", function( ply, mv ) local parachute = ply:GetTable().cfcParachuteChute if parachute and parachute != NULL and parachute._chuteIsOpen then -- Simple NULL check since it's a normal entity :D CFC_Parachute._ApplyChuteForces( ply, parachute, mv ) end - end) + end ) else - hook.Add( "Move", "CFC_Parachute_Movement", function( ply, mv, cmd ) -- Only called for the local player + hook.Add( "Move", "CFC_Parachute_Movement", function( ply, mv ) -- Only called for the local player local parachute = ply:GetNW2Entity( "CFC_Parachute" ) if parachute and parachute != NULL then -- Simple NULL check since it's a normal entity :D CFC_Parachute._ApplyChuteForces( ply, parachute, mv ) end - end) + end ) end \ No newline at end of file