Skip to content

Commit d43588f

Browse files
committed
Add ulx wheel
1 parent 392132c commit d43588f

File tree

1 file changed

+209
-0
lines changed

1 file changed

+209
-0
lines changed

lua/ulx/modules/sh/cfc_wheel.lua

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
CFCUlxCommands.wheel = CFCUlxCommands.wheel or {}
2+
CFCUlxCommands.propify = CFCUlxCommands.propify or {}
3+
local cmd = CFCUlxCommands.wheel
4+
local propifyCmd = CFCUlxCommands.propify
5+
6+
local CATEGORY_NAME = "Fun"
7+
local VEC_UP = Vector( 0, 0, 1 )
8+
local WHEEL_MODEL = "models/props_vehicles/carparts_wheel01a.mdl"
9+
local WHEEL_GROUND_TRACE_OFFSET
10+
local WHEEL_JUMP_COOLDOWN = 0.3
11+
local WHEEL_UPRIGHT_STRENGTH = 230
12+
local WHEEL_UPRIGHT_THRESHOLD = 0.07
13+
local WHEEL_HORIZONTAL_THRESHOLD = 0.99
14+
local WHEEL_ASSIST_GROUND_MULT = 3
15+
local WHEEL_TURN_ASSIST_SPINDOWN_MULT = 0.5
16+
local WHEEL_TURN_ASSIST_REORIENT_THRESHOLD = 0.35
17+
local WHEEL_UPRIGHT_STABILIZE = Vector( 0.9, 0, 0 )
18+
local WHEEL_SPIN_STRENGTH = CreateConVar( "cfc_ulx_wheel_spin_strength", 30, FCVAR_NONE, "The speed that propify wheel players can move at", 0, 50000 )
19+
local WHEEL_TURN_STRENGTH = CreateConVar( "cfc_ulx_wheel_turn_strength", 10, FCVAR_NONE, "The speed that propify wheel players can turn at", 0, 50000 )
20+
21+
local wheelProps = {}
22+
local wheelPropCount = 0
23+
cmd.wheelProps = wheelProps
24+
cmd.wheelPropCount = wheelPropCount
25+
26+
cmd.relativeDirFuncsWheel = {
27+
[IN_FORWARD] = function( ang ) return -ang:Right() end,
28+
[IN_BACK] = function( ang ) return ang:Right() end,
29+
[IN_MOVERIGHT] = function( ang ) return -VEC_UP end,
30+
[IN_MOVELEFT] = function( ang ) return VEC_UP end,
31+
[IN_JUMP] = function() return VEC_UP end
32+
}
33+
local relativeDirFuncsWheel = cmd.relativeDirFuncsWheel
34+
35+
local IsValid = IsValid
36+
local tableRemove = table.remove
37+
local mAbs = math.abs
38+
39+
local function mSignNoZero( x )
40+
return ( x < 0 and -1 ) or 1
41+
end
42+
43+
local function overridePrint( isUnpropifying )
44+
if isUnpropifying then return "#A made a flat out of #T" end
45+
return "#A took #T out for a spin"
46+
end
47+
48+
function cmd.wheelTargets( caller, targets, shouldUnwheel )
49+
local props = propifyCmd.propifyTargets( caller, targets, WHEEL_MODEL, shouldUnwheel, overridePrint, cmd.propHopOverride, cmd.hopCooldownOverride )
50+
51+
if table.IsEmpty( props ) then return end
52+
53+
table.Add( wheelProps, props )
54+
wheelPropCount = #wheelProps
55+
cmd.wheelPropCount = wheelPropCount
56+
end
57+
58+
local function getRelativeHopDirWheel( eyeAngles, key )
59+
local dirFunc = relativeDirFuncsWheel[key]
60+
61+
if not dirFunc then return eyeAngles:Forward() end
62+
63+
return dirFunc( eyeAngles )
64+
end
65+
66+
function cmd.propHopOverride( ply, prop, key, state, moveDir )
67+
if not relativeDirFuncsWheel[key] then return end
68+
69+
local isTurning = key == IN_MOVERIGHT or key == IN_MOVELEFT
70+
71+
if not state then
72+
if key == IN_JUMP then return end
73+
74+
if isTurning then
75+
prop.propifyWheelTurning = false
76+
else
77+
prop.propifyWheelSpinning = false
78+
end
79+
80+
return
81+
end
82+
83+
local phys = prop:GetPhysicsObject()
84+
85+
if not IsValid( phys ) then
86+
propifyCmd.unpropifyPlayer( ply )
87+
88+
return
89+
end
90+
91+
if key == IN_JUMP then
92+
if not prop:IsOnGround() then return false end
93+
94+
phys:ApplyForceCenter( moveDir * GetConVar( "cfc_ulx_propify_hop_strength" ):GetFloat() * phys:GetMass() )
95+
96+
return true
97+
end
98+
99+
local moveDirWheel = getRelativeHopDirWheel( ply:EyeAngles(), key )
100+
local rotStrength = isTurning and WHEEL_TURN_STRENGTH:GetFloat() or WHEEL_SPIN_STRENGTH:GetFloat()
101+
102+
if isTurning then
103+
prop.propifyWheelTurning = moveDirWheel * rotStrength
104+
else
105+
prop.propifyWheelSpinning = moveDirWheel * rotStrength
106+
end
107+
108+
return false
109+
end
110+
111+
function cmd.hopCooldownOverride()
112+
return WHEEL_JUMP_COOLDOWN
113+
end
114+
115+
local wheelCommand = ulx.command( CATEGORY_NAME, "ulx wheel", cmd.wheelTargets, "!wheel" )
116+
wheelCommand:addParam{ type = ULib.cmds.PlayersArg }
117+
wheelCommand:addParam{ type = ULib.cmds.BoolArg, invisible = true }
118+
wheelCommand:defaultAccess( ULib.ACCESS_ADMIN )
119+
wheelCommand:help( "Turns the target(s) into a wheel." )
120+
wheelCommand:setOpposite( "ulx unwheel", { _, _, true }, "!unwheel" )
121+
122+
123+
hook.Add( "Think", "CFC_ULX_WheelKeepUpright", function()
124+
for i = wheelPropCount, 1, -1 do
125+
local wheel = wheelProps[i]
126+
wheel = IsValid( wheel ) and wheel
127+
local phys = wheel and wheel:GetPhysicsObject()
128+
local ply = wheel.ragdolledPly
129+
130+
if not wheel or not IsValid( phys ) or not IsValid( ply ) then
131+
tableRemove( wheelProps, i )
132+
wheelPropCount = wheelPropCount - 1
133+
cmd.wheelPropCount = wheelPropCount
134+
135+
continue
136+
end
137+
138+
local wheelRight = wheel:GetRight()
139+
local wheelRightZ = wheelRight[3]
140+
local wheelRightZAbs = mAbs( wheelRightZ )
141+
local wheelRightZOriginal = wheelRightZ
142+
local isHorizontal = wheelRightZAbs > WHEEL_HORIZONTAL_THRESHOLD
143+
local plyForward = ply:GetAimVector()
144+
local spinTorque = wheel.propifyWheelSpinning
145+
local turnTorque = wheel.propifyWheelTurning
146+
local groundMult = wheel:IsOnGround() and WHEEL_ASSIST_GROUND_MULT or 1
147+
148+
if spinTorque then
149+
local spindownMult = turnTorque and WHEEL_TURN_ASSIST_SPINDOWN_MULT or 1 -- Assist turning by reducing forwards spin
150+
local rightDotAim = wheelRight:Dot( plyForward )
151+
152+
if mAbs( rightDotAim ) > WHEEL_TURN_ASSIST_REORIENT_THRESHOLD then
153+
spinTorque = -VEC_UP * WHEEL_TURN_STRENGTH:GetFloat() * mSignNoZero( rightDotAim )
154+
end
155+
156+
phys:AddAngleVelocity( phys:WorldToLocalVector( spinTorque * groundMult * spindownMult ) )
157+
end
158+
159+
if turnTorque then
160+
phys:AddAngleVelocity( phys:WorldToLocalVector( turnTorque * groundMult ) )
161+
end
162+
163+
if wheelRightZAbs < WHEEL_UPRIGHT_THRESHOLD then continue end
164+
165+
if isHorizontal then
166+
wheelRight = plyForward:Angle():Right()
167+
wheelRightZ = wheelRight[3]
168+
end
169+
170+
local rightDot = isHorizontal and mSignNoZero( wheelRightZOriginal ) or VEC_UP:Dot( wheelRight )
171+
local angVel = phys:GetAngleVelocity()
172+
local forwardEff = wheelRight:Angle():Right()
173+
174+
local torque = phys:WorldToLocalVector( -WHEEL_UPRIGHT_STRENGTH * rightDot * forwardEff )
175+
torque = torque - angVel * WHEEL_UPRIGHT_STABILIZE
176+
177+
phys:AddAngleVelocity( torque )
178+
end
179+
end )
180+
181+
timer.Create( "CFC_ULX_WheelGroundCheck", 0.2, 0, function()
182+
for i = wheelPropCount, 1, -1 do
183+
local wheel = wheelProps[i]
184+
185+
if not IsValid( wheel ) then
186+
tableRemove( wheelProps, i )
187+
wheelPropCount = wheelPropCount - 1
188+
cmd.wheelPropCount = wheelPropCount
189+
190+
continue
191+
end
192+
193+
WHEEL_GROUND_TRACE_OFFSET = WHEEL_GROUND_TRACE_OFFSET or -VEC_UP * ( wheel:OBBMaxs()[3] + 10 )
194+
195+
local wheelPos = wheel:GetPos()
196+
local tr = util.TraceLine( {
197+
start = wheelPos,
198+
endpos = wheelPos + WHEEL_GROUND_TRACE_OFFSET,
199+
filter = wheel
200+
} )
201+
202+
if tr.Hit then
203+
wheel:SetGroundEntity( tr.Entity )
204+
wheel:AddFlags( FL_ONGROUND )
205+
else
206+
wheel:RemoveFlags( FL_ONGROUND )
207+
end
208+
end
209+
end )

0 commit comments

Comments
 (0)