Check to see if there's space to teleport something before it gets there?
20 replies, posted
How would I check to see if there's space to teleport something before it gets there?
I believe a trace.hull will help with this.
Maybe this will help,
[CODE]
local function TraceLength(spos,epos,filter,comp)
local Trace = {}
Trace.start = spos
if comp == 1 then Trace.endpos = spos+(Vector(1,0,0)*epos) elseif comp == 2 then Trace.endpos = spos+(Vector(0,1,0)*epos) else Trace.endpos = spos+(Vector(0,0,1)*epos) end
Trace.filter = filter
Trace.mask = MASK_PLAYERSOLID
local TraceHitPos = util.TraceLine(Trace).HitPos
if epos > 0 then
if comp == 1 then
local tracelenght = TraceHitPos.x-spos.x
if tracelenght <= 0 then return 0 end
return tracelenght
elseif comp == 2 then
local tracelenght = TraceHitPos.y-spos.y
if tracelenght <= 0 then return 0 end
return tracelenght
else
local tracelenght = TraceHitPos.z-spos.z
if tracelenght <= 0 then return 0 end
return tracelenght
end
else
if comp == 1 then
local tracelenght = spos.x-TraceHitPos.x
if tracelenght <= 0 then return 0 end
return tracelenght
elseif comp == 2 then
local tracelenght = spos.y-TraceHitPos.y
if tracelenght <= 0 then return 0 end
return tracelenght
else
local tracelenght = spos.z-TraceHitPos.z
if tracelenght <= 0 then return 0 end
return tracelenght
end
end
end
function AdvancedSpawnPlayer(SpawnPosition,SpawnAngle,Player,Filter)
if type(SpawnPosition) != "Vector" then return end
if !ValidEntity(Player) then return end
if type(SpawnAngle) != "nil" and type(SpawnAngle) != "Angle" then return end
if type(Filter) != "nil" and type(Filter) != "table" then return end
SpawnAngle = SpawnAngle or Angle(0,0,0)
if Player:GetMoveType() == MOVETYPE_NOCLIP then
Player:SetEyeAngles(SpawnAngle)
Player:SetPos(SpawnPosition)
return true
end
local PlayerHeight = 70
local PlayerDuckHeight = 35
local PlayerWidth = 35
local TraceLengthDown = 0
local Height = 0
local Width = 0
local Depth = 0
local HalfPlayerHeight = PlayerHeight/2
local HalfPlayerDuckHeight = PlayerDuckHeight/2
local HalfPlayerWidth = PlayerWidth/2
local SpawnDuck = false
local ToCenterVertical = 0
local ToCenterHorizantal = 0
local TraceHeight = HalfPlayerHeight
local CountToCenterVertical = false
local CountToCenterHorizantal = false
local DetectionAccuracy = 2
local Reset = false
local NewPosZ = false
local NewPosX = false
local NewPosY = false
while true do
if CountToCenterHorizantal and !CountToCenterVertical then
if -ToCenterHorizantal >= HalfPlayerWidth then
ToCenterHorizantal = 0
CountToCenterVertical = true
else
ToCenterHorizantal = ToCenterHorizantal-DetectionAccuracy
end
end
if CountToCenterVertical then
if ((TraceHeight+ToCenterVertical)*2) < DetectionAccuracy then break end
ToCenterVertical = ToCenterVertical-DetectionAccuracy
end
-- trace up
local tracelenghtup = math.min(TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),(HalfPlayerWidth+ToCenterHorizantal),0),TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),(HalfPlayerWidth+ToCenterHorizantal),0),TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),-(HalfPlayerWidth+ToCenterHorizantal),0),TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),-(HalfPlayerWidth+ToCenterHorizantal),0),TraceHeight,Filter,3))
-- trace down
TraceLengthDown = math.min(TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),(HalfPlayerWidth+ToCenterHorizantal),0),-TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),(HalfPlayerWidth+ToCenterHorizantal),0),-TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),-(HalfPlayerWidth+ToCenterHorizantal),0),-TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),-(HalfPlayerWidth+ToCenterHorizantal),0),-TraceHeight,Filter,3))
Height = TraceLengthDown+tracelenghtup
-- trace xa
local tracelenghtxa = math.min(TraceLength(SpawnPosition+Vector(0,(HalfPlayerWidth+ToCenterHorizantal),(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,-(HalfPlayerWidth+ToCenterHorizantal),(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,(HalfPlayerWidth+ToCenterHorizantal),-(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,-(HalfPlayerWidth+ToCenterHorizantal),-(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,1))
-- trace xb
local tracelenghtxb = math.min(TraceLength(SpawnPosition+Vector(0,(HalfPlayerWidth+ToCenterHorizantal),(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,-(HalfPlayerWidth+ToCenterHorizantal),(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,(HalfPlayerWidth+ToCenterHorizantal),-(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,-(HalfPlayerWidth+ToCenterHorizantal),-(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,1))
Width = tracelenghtxb+tracelenghtxa
-- trace ya
local tracelenghtya = math.min(TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),0,(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),0,(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),0,-(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),0,-(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,2))
-- trace yb
local tracelenghtyb = math.min(TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),0,(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),0,(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),0,-(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),0,-(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,2))
Depth = tracelenghtyb+tracelenghtya
if tracelenghtup < TraceHeight and TraceLengthDown == TraceHeight then
if NewPosZ and SpawnDuck then
break
else
if NewPosZ then
NewPosZ = false
if !SpawnDuck then
SpawnDuck = true
TraceHeight = HalfPlayerDuckHeight
local ToCenter = 0
local Down
local LowestDown = TraceHeight
local DetectionAccuracy = DetectionAccuracy
while true do
Down = math.min(TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenter),(HalfPlayerWidth+ToCenter),0),-TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenter),(HalfPlayerWidth+ToCenter),0),-TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenter),-(HalfPlayerWidth+ToCenter),0),-TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenter),-(HalfPlayerWidth+ToCenter),0),-TraceHeight,Filter,3))
if Down < LowestDown then LowestDown = Down end
if LowestDown <= 0 then break end
ToCenter = ToCenter-DetectionAccuracy
if -ToCenter >= HalfPlayerWidth then break end
end
SpawnPosition = SpawnPosition+Vector(0,0,-LowestDown+HalfPlayerDuckHeight)
end
else
NewPosZ = true
SpawnPosition = SpawnPosition-Vector(0,0,TraceHeight-tracelenghtup)
Reset = true
NewPosX = false
NewPosY = false
end
end
elseif TraceLengthDown < TraceHeight and tracelenghtup == TraceHeight then
if NewPosZ and SpawnDuck then
break
else
if NewPosZ then
NewPosZ = false
if !SpawnDuck then
SpawnDuck = true
TraceHeight = HalfPlayerDuckHeight
local ToCenter = 0
local Down
local LowestDown = TraceHeight
local DetectionAccuracy = DetectionAccuracy
Jesus fucking christ bro.
what the fuck
just do
[code]function checkShit() return util.TraceHull( { start = pos, endpos = pos, maxs = Vector(PlyWidth,PlyWidth,PlyHeight)/2, mins = -Vector(PlyWidth,PlyWidth,PlyHeight)/2 } ).Hit end[/code]
already
[code]
-- trace up
local tracelenghtup = math.min(TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),(HalfPlayerWidth+ToCenterHorizantal),0),TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),(HalfPlayerWidth+ToCenterHorizantal),0),TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),-(HalfPlayerWidth+ToCenterHorizantal),0),TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),-(HalfPlayerWidth+ToCenterHorizantal),0),TraceHeight,Filter,3))
-- trace down
TraceLengthDown = math.min(TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),(HalfPlayerWidth+ToCenterHorizantal),0),-TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),(HalfPlayerWidth+ToCenterHorizantal),0),-TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),-(HalfPlayerWidth+ToCenterHorizantal),0),-TraceHeight,Filter,3),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),-(HalfPlayerWidth+ToCenterHorizantal),0),-TraceHeight,Filter,3))
Height = TraceLengthDown+tracelenghtup
-- trace xa
local tracelenghtxa = math.min(TraceLength(SpawnPosition+Vector(0,(HalfPlayerWidth+ToCenterHorizantal),(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,-(HalfPlayerWidth+ToCenterHorizantal),(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,(HalfPlayerWidth+ToCenterHorizantal),-(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,-(HalfPlayerWidth+ToCenterHorizantal),-(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,1))
-- trace xb
local tracelenghtxb = math.min(TraceLength(SpawnPosition+Vector(0,(HalfPlayerWidth+ToCenterHorizantal),(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,-(HalfPlayerWidth+ToCenterHorizantal),(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,(HalfPlayerWidth+ToCenterHorizantal),-(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,1),TraceLength(SpawnPosition+Vector(0,-(HalfPlayerWidth+ToCenterHorizantal),-(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,1))
Width = tracelenghtxb+tracelenghtxa
-- trace ya
local tracelenghtya = math.min(TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),0,(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),0,(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),0,-(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),0,-(TraceHeight+ToCenterVertical)),HalfPlayerWidth,Filter,2))
-- trace yb
local tracelenghtyb = math.min(TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),0,(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),0,(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector((HalfPlayerWidth+ToCenterHorizantal),0,-(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,2),TraceLength(SpawnPosition+Vector(-(HalfPlayerWidth+ToCenterHorizantal),0,-(TraceHeight+ToCenterVertical)),-HalfPlayerWidth,Filter,2))
Depth = tracelenghtyb+tracelenghtya
[/code]
:suicide:
If you can teach me something, please teach me.
[QUOTE=P.Tigris;37314214]If you can teach me something, please teach me.[/QUOTE]
Here's something I threw together in 5 minutes after I saw your code. It's 37 lines long vs your 200+ lines. Has all the same features, and one additional feature: If no nearby position is found, it expands the search area a bit and checks again.
It can be rewritten slightly to make it cleaner and more optimized, but meh. I didn't make it to use it. I just made it because I was bored
One difference is I didn't make it actually move anything. It only returns the position if the spot is empty, or false if it's not empty.
[code]local positions = {
Vector(0, 0, 0.5),
Vector(1, 0, 0.5),
Vector(-1, 0, 0.5),
Vector(0, 1, 0.5),
Vector(0, -1, 0.5),
Vector(1, 1, 0.5),
Vector(-1, -1, 0.5),
Vector(1, -1, 0.5),
Vector(-1, 1, 0.5),
}
local positions2 = {}
for i=1,#positions do
positions2[i] = positions[i] * Vector(2,2,1)
end
function AdvMove( ply, pos, double, duck )
local size = ply:OBBMaxs()-ply:OBBMins()
if duck then size.z = size.z/2 end
local t = positions
if double then t = positions2 end
for i=1,#t do
local testpos = pos + size * t[i]
if not util.TraceHull( {start = testpos, endpos = testpos, filter = ply, maxs = size/2, mins = -size/2}, ply ).Hit then return testpos - Vector(0,0,size.z/2), duck end
end
if double == nil then
return AdvMove( ply, pos, true, duck )
elseif duck == nil then
return AdvMove( ply, pos, double, true )
end
return false
end[/code]
And here's what I used to test it
[code]function TestMove( pos )
local p, duck = AdvMove( Entity(1), pos )
if p then
if duck then
Entity(1):ConCommand("+duck")
timer.Simple( 0.25, function()
Entity(1):SetPos( p )
end)
timer.Simple( 0.5, function()
Entity(1):ConCommand("-duck")
end)
else
Entity(1):SetPos( p )
end
else
print("NOPE")
end
end[/code]
EDIT: damnit garry fix the [noparse][lua][/lua][/noparse] tags
Both spawn scripts has its own good properties;
Yours:
-Small script.
-Would spawn player in many cases.
Mine:
-Accurate.
-Would never spawn player through objects.
I think I am going to improve my script, but it would not be smaller.
[QUOTE=P.Tigris;37317164]Both spawn scripts has its own good properties;
Yours:
-Small script.
-Would spawn player in many cases.
Mine:
-Accurate.
-Would never spawn player through objects.
I think I am going to improve my script, but it would not be smaller.[/QUOTE]
I don't wan't to be mean here, just stating the facts...
Mine would never spawn players inside objects, either.
Mine is more accurate than yours. Although that depends on what you mean by "accurate". (EDIT: For example. What happens if you place a really small prop, like a pop can, in the spawn point. Mine would detect it. Would yours?)
Nope mine would not detect it in many cases.
Your script sometimes spawns a player through objects but would not be stuck in the object.
If you take Model: models/props_wasteland/cargo_container01b.mdl for example.
You set the spawn position at the back of the container then it sometimes spawns the player outside the container. So that is what I meant with through the object.
[QUOTE=P.Tigris;37318020]Nope mine would not detect it in many cases.
Your script sometimes spawns a player through objects but would not be stuck in the object.
If you take Model: models/props_wasteland/cargo_container01b.mdl for example.
You set the spawn position at the back of the container then it sometimes spawns the player outside the container. So that is what I meant with through the object.[/QUOTE]
Mine can handle spawning inside containers just fine. And it's supposed to.
Did you test it at different angles?
Angles shouldn't even matter (I much prefer Divran's code, by the way).
[QUOTE=P.Tigris;37319742]Did you test it at different angles?[/QUOTE]
The hull of players doesn't rotate. Mine won't work correctly if you want to use it to move props, however. But you can make an algorithm that uses trace hulls to more accurately check rotation.
I know the hull of the player does not rotate, that is way the traces does not rotate either in my script. I meant the rotation of the container.
Map: gm_flatgrass
Container properties:
Position: Vector(1000,-1000,60.006)
Angle: Angle(0,135,0)
Model: models/props_wasteland/cargo_container01b.mdl
Spawn position: Vector(900,-1100,66)
The spawn position is in the back of the container, but it will spawn the player behind the container.
I use:
[CODE]lua_run_cl hook.Add("PreDrawEffects","RenderPos",function() render.SetMaterial(Material("sprites/light_glow02_add")) render.DrawSprite(Vector(900,-1100,66),10,10,Color(255,255,255,255)) end)[/CODE]
to make the spawn position visible.
But I agree that my code could use some improvement, in combination with the function util.TraceHull().
Why would the rotation of the container have any effect at all? If rotating the container causes part of it to be inside the spawn point, then move the spawn point a few units off the ground.
I honestly do not know, But that is what happens.
I shall say reconstruct the situation.
Ok I’ll give you some data.
I placed print("Vector("..testpos.x..","..testpos.y..","..testpos.z..")") in the for loop.
And then I get this:
Vector(900,-1100,102)
Vector(932,-1100,102)
Vector(868,-1100,102)
Vector(900,-1068,102)
Vector(900,-1132,102)
Vector(932,-1068,102)
Vector(868,-1132,102)
Vector(932,-1132,102)
Vector(868,-1068,102)
Vector(900,-1100,102)
Vector(964,-1100,102)
Vector(836,-1100,102)
Vector(900,-1036,102)
Vector(900,-1164,102)
Vector(964,-1036,102)
Vector(836,-1164,102)
So we get the position Vector(836,-1164,66) and this position is behind the container.
ok I give up
Sorry, you need to Log In to post a reply to this thread.