Skip to content

Instantly share code, notes, and snippets.

@SunRed
Created April 14, 2015 20:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save SunRed/da1b02efa7c167804e65 to your computer and use it in GitHub Desktop.
Save SunRed/da1b02efa7c167804e65 to your computer and use it in GitHub Desktop.
A simple unstuck script in gmod
-- TODO: Nocollided props still trigger even with MASK_PLAYERSOLID!
---------------------------------------------------------------
local ply = nil
-- WeHateGarbage
local t = {start=nil,endpos=nil,mask=MASK_PLAYERSOLID,filter=nil}
local function PlayerNotStuck()
t.start = ply:GetPos()
t.endpos = t.start
t.filter = ply
return util.TraceEntity(t,ply).StartSolid == false
end
local NewPos = nil
local function FindPassableSpace( direction, step )
local i = 0
while ( i < 100 ) do
local origin = ply:GetPos()
--origin = VectorMA( origin, step, direction )
origin = origin + step * direction
ply:SetPos( origin )
if PlayerNotStuck( ply ) then
NewPos = ply:GetPos()
return true
end
i = i + 1
end
return false
end
--
-- Purpose: Unstucks player
-- Note: Very expensive to call, you have been warned!
--
local function UnstuckPlayer( pl )
ply = pl
NewPos = ply:GetPos()
local OldPos = NewPos
if not PlayerNotStuck( ply ) then
local angle = ply:GetAngles()
local forward = angle:Forward()
local right = angle:Right()
local up = angle:Up()
local SearchScale = 1 -- Increase and it will unstuck you from even harder places but with lost accuracy. Please, don't try higher values than 12
if not FindPassableSpace( forward, SearchScale ) and -- forward
not FindPassableSpace( right, SearchScale ) and -- right
not FindPassableSpace( right, -SearchScale ) and -- left
not FindPassableSpace( up, SearchScale ) and -- up
not FindPassableSpace( up, -SearchScale ) and -- down
not FindPassableSpace( forward, -SearchScale ) -- back
then
--Msg( "Can't find the world for player "..tostring(ply).."\n" )
return false
end
if OldPos == NewPos then
return true -- Not stuck?
else
ply:SetPos( NewPos )
if SERVER and ply and ply:IsValid() and ply:GetPhysicsObject():IsValid() then
if ply:IsPlayer() then
ply:SetVelocity(vector_origin)
end
ply:GetPhysicsObject():SetVelocity(vector_origin) -- prevents bugs :s
end
return true
end
end
end
---------------------------------------------------------------
local meta = FindMetaTable( "Player" )
if not meta then return end
-- Unstucks a player
-- returns:
-- true: Unstucked
-- false: Could not UnStuck
-- else: Not stuck
--
function meta:UnStuck()
return UnstuckPlayer(self)
end
---------------------------------------------------------------
-- CONFIG -----------------------------------------------------
---------------------------------------------------------------
local config = {} -- ignore
-- Available chat commands for us_unstuck console command
config.ChatCommands = {
"!unstuck",
"!stuck",
"/unstuck",
"/stuck"
}
-- Players of these teams are not allowed to use the unstuck command
config.ExcludedTeams = {
"TEAM_PROPS"
}
-- Number of seconds a player has to wait until (s)he can use the unstuck command again
config.Wait = 10
---------------------------------------------------------------
concommand.Add( "us_unstuck", function( pl )
if not IsValid( pl ) then return end
if not pl:Alive() then
pl:ChatPrint( "You ain't alive." )
return
end
for _,team in pairs( config.ExcludedTeams ) do
if _G[team] ~= nil and _G[team] == pl:Team() then
pl:ChatPrint( "Sorry! You aren't allowed to do this in your team!" )
return
end
end
local CurrentTime = CurTime()
if pl.lastUnStuckTime then
if pl.lastUnStuckTime + config.Wait > CurrentTime then
local waittime, s = config.Wait - math.floor( CurrentTime - pl.lastUnStuckTime ), ""
if waittime ~= 1 then s = "s" end
pl:ChatPrint( "You might want to wait another " .. tostring( waittime ) .. " second" .. s .. "." )
return
end
end
local unstuck = pl:UnStuck()
if unstuck == true then
pl:ChatPrint( "Unstuck successful!" )
elseif unstuck == false then
pl:ChatPrint( "Unstuck not possible (No free space found)." )
else
pl:ChatPrint( "You are not stuck." )
end
pl.lastUnStuckTime = CurTime()
end )
hook.Add( "PlayerSay", "Unstuck Command", function( pl, text )
if table.HasValue( config.ChatCommands, string.lower(text) ) then
pl:ConCommand( "us_unstuck" )
--return false
end
end )
@tetra-fox
Copy link

Not working anymore. Chat returns Unstuck not possible (No free space found). and player is never unstuck.

@SunRed
Copy link
Author

SunRed commented Feb 23, 2016

Sorry for the late answer, according to my experiences this script still works even though there are better solutions.
You may not experience this problem anymore if you change SearchScale to 2 or 3.

@eleggameplayer
Copy link

Where do i put this script?

@Mibo5354
Copy link

Mibo5354 commented Apr 8, 2017

I put it in ...\Steam\steamapps\common\GarrysMod\garrysmod\lua\autorun

@baconbreakin
Copy link

I agree with tetra-fox, this command doesn't work on my prop hunt server. It just says the same thing, Unstuck not possible (No free space found).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment