Help With Proximity Code for SWEP

Hi guys! So I’ve decided to do my first SWEP, and it’s going alright. It’s a Mine Turtle, and it does everything it should. You say “Hello Mine Turtle” when you throw it, then it requires you to be a certain distance away from it before it clicks and arms itself, then when a player gets near to it, it says “Hello” and blows up!

It’s supposed to be a simple SWEP but it’s proving difficult to get the proximity code to work properly in the way I want it to. So far it works on a radius base like such:



if distance < (self.Range) then
playersnear = playersnear + 1

It’s basic and it works for now. What I want it to do however is to take into account any walls obstructing the player, because a player can walk up to the other side of the wall to the mine and it’ll blow up still. Does anybody have any idea how to do this? Any help is appreciated, thank you.

Oh, and if you want any more codes from the addon to aid in your help then just let me know what you need and I’ll put it up for you.

Within the loop you are using to find the players near (I assume you are using

ents.FindInSphere) you could do a simple trace using

util.TraceLine and see if it hit’s something (trace.Hit) else before it gets to the player.



local tr = util.TraceLine({
	start = self:GetPos(),
	endpos = ply:GetPos()
})

if (!tr.HitWorld and IsValid(tr.Entity) and tr.Entity == ply) then
	-- blow up
end


Take a look at http://wiki.garrysmod.com/page/Structures/TraceResult too.

Alas I’m not sure how I’d incorporate that into the code. I should give you the full function so you know what you’re dealing with. It’s extremely basic, just a heads up.



if SERVER then
   function ENT:Think()
		if self.Warmup > 0 then
			self.Warmup = self.Warmup - 1
		else		
			local Players = player.GetAll()
			local playersnear = 0
			for i = 1, table.Count(Players) do
				local ply = Players*
				local victimpos = ply:GetPos()
				local targetpos = self:GetPos()
				local distance = victimpos:Distance( targetpos )
				if distance < (self.Range) then
					playersnear = playersnear + 1
					if self.armed == 1 then
						self.Ready = self.Ready + 1
						if self.Ready == 1 then
						sound.Play(hello, self:GetPos(), 100, 100)
						timer.Simple(self.BoomTime, function()
						self:Explode()
						sound.Play(boom, self:GetPos(), 100, 100)
						end)
						end
					end
				end
			end
			if playersnear == 0 and self.armed == 0 then
				self.armed = 1
				if SERVER then
					sound.Play(active, self:GetPos(), 40, 100)
				end
			end
		end
   end
end



if (SERVER) then
	function ENT:Think()
		for _, ent in ipairs(ents.FindInSphere(self:GetPos(), self.Range)) do
			if (ent:IsPlayer()) then
				local tr = util.TraceLine({
					start = self:GetPos(),
					endpos = ent:GetPos()
				})

				if (!tr.HitWorld and IsValid(tr.Entity) and tr.Entity == ent and !self.Exploding) then
					self.Exploding = true
					sound.Play(hello, self:GetPos(), 100, 100)

					timer.Simple(self.BoomTime, function()
						if (!IsValid(self)) then return end

						self:Explode()

						sound.Play(boom, self:GetPos(), 100, 100)
					end)
				end
			end
		end
	end
end


Don’t exactly like to spoonfeed but your code is nothing like I’d do it.

Hmmm I tried putting that in the code but it didn’t work. Not to worry, I think you’ve provided me with enough information for me to edit it and get it to work. Trial and error I suppose.

Thanks for the help anyway! I’ll update this post with the final code when I’ve done it, just in case anyone else wants to create proximity based explosives.

His code assumes that there are no obstructions.

OK, so I’ve managed to get it to work using ents.FindInSphere, but as far as tracing goes I’m a complete noob in that department. I may require a little bit more assistance. Sorry if it feels like you’re spoonfeeding me, I just can’t think of any other way to learn about it in full.

You could simply add a vector to both ent:GetPos() and ply:GetPos() (+ Vector(0, 0, 32)) so it’s not going through the floor, that might work.

The result of this was hilarious! Now whenever I throw the turtle it just says “Hello Mine Turtle” and “Hello” both at the same time, then blows up in front of my face XD

[editline]28th August 2015[/editline]



if SERVER then
   function ENT:Think()	
	local playersnear = 0
	local Ready = 0
	
			for _,ent in ipairs(ents.FindInSphere(self:GetPos(), self.Range)) do
			if (ent:IsPlayer()) then
			local tr = util.TraceLine({
					start = self:GetPos() + Vector(0, 0, 32),
					endpos = ent:GetPos() + Vector(0, 0, 32),
					filter = self
				})

				if (!tr.HitWorld and IsValid(tr.Entity) and tr.Entity == ent and !self.Exploding) then
					playersnear = playersnear + 1
					if self.armed == 1 then
						self.Ready = self.Ready + 1
						if self.Ready == 1 then
						sound.Play(hello, self:GetPos(), 100, 100)
						timer.Simple(self.BoomTime, function()
						self:Explode()
						sound.Play(boom, self:GetPos(), 100, 100)
						end)
						end
					end
				
				end
			end
			if playersnear == 0 and self.armed == 0 then
				self.armed = 1
				if SERVER then
					sound.Play(active, self:GetPos(), 70, 100)
				end
			end
		end
   end
end

THIS NEARLY WORKS! The turtle will sit happily doing nothing, you walk around the corner and it clicks, then when somebody gets near it the thing goes BOOM! Buuutttt sometimes it clicks and goes boom even when you haven’t left it, and will usually do it when you pick it up with the magneto-stick. God this is frustrating. I’ve tried changing the vectors but to no avail.