Skip to content

Instantly share code, notes, and snippets.

@NanoAi
Forked from SunRed/unstuck.lua
Created July 21, 2016 01:23
Show Gist options
  • Save NanoAi/f8d54d863686bf144ce7d73cca55e4f6 to your computer and use it in GitHub Desktop.
Save NanoAi/f8d54d863686bf144ce7d73cca55e4f6 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 )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment