Collision rules error?

Greetings! I am working on a weapon for a gamemode and I have seemed to have found a particular error: ‘Changing collision rules within a callback is likely to cause crashes!’

The SWEP i’m creating involves creating a projectile being fired when the player left or right clicks, and said projectile ricochets off walls. However i’m getting the error above when it hits a wall. This is the ENT:PhysicsCollide function that i’m currently using
[lua]
function ENT:PhysicsCollide(data, physobj)
local vphys = physobj:GetVelocity() * data.OurOldVelocity:Length()
local angles = self:GetAngles()

physobj:SetVelocityInstantaneous(Vector(vphys.x / 1000, vphys.y / 1000, 0))

self:EmitSound("ricochet/disc_hit"..math.random(1,2)..".wav", 78, 80)
self.Direction = self:GetForward()
self.Bounces = self.Bounces + 1

--self.MaxBounces <= self.Bounces
if data.HitEntity:IsWorld() then
	self:Remove()
end

end
[/lua]

I swear i’m doing everything right and it’s driving me crazy on why the error is entering the console. Does anyone know what is did wrong, or need to add/remove to stop the error?

It seems changing anything with the physics while in that function throws the error. I know 100% the ‘self:Remove()’ will also throw it, and looking at your code it removes the entity after the first collision. Is this the exact code? Because it seems to me like you want it to bounce, and your code listed above will remove the entity on first contact.

There’s not really a single solution to this, but for starters you can try something like this:



function ENT:PhysicsCollide(data, physobj)
	local vphys = physobj:GetVelocity() * data.OurOldVelocity:Length()
	local angles = self:GetAngles()

	physobj:SetVelocityInstantaneous(Vector(vphys.x / 1000, vphys.y / 1000, 0))

	self:EmitSound("ricochet/disc_hit"..math.random(1,2)..".wav", 78, 80)
	self.Direction = self:GetForward()
	self.Bounces = self.Bounces + 1

	--self.MaxBounces <= self.Bounces
	if data.HitEntity:IsWorld() then --Wheres your max bounce code? This removes literally when it hits the world
		timer.Simple(0, function() --Remove the next frame..
			if (IsValid(self)) then
				self:Remove()
			end
		end)
	end
end


It should work on next frame if u stop any act from the entity when called.
Problem is it still has collision rule when u remove. You must wait on next frame. You do nothing just on next frame remove you should block any act. I know nothing what your entity does. I did same as bullet on hit block anything to call for collision. Then next frame removed it. I used a trick to mamke it invisible then remove the bullet.

Thanks for the help! That has seemed to have fixed the error, however how can the velocity be maintained? It slows down with each hit. Here is the full code of the swep so far…
[lua]
AddCSLuaFile(“cl_init.lua”)
AddCSLuaFile(“shared.lua”)

include(“shared.lua”)

ENT.MaxBounces = 3 – Not done yet, don’t even use this… (So far it works-ish, but velocity isn’t maintained and bounces off of the sky)
ENT.DeathLimit = 15

function ENT:Initialize()
self:SetModel(“models/props_junk/sawblade001a.mdl”)
self:PhysicsInitSphere(6)
self:SetMoveType(MOVETYPE_VPHYSICS) --MOVETYPE_VPHYSICS

local phys = self:GetPhysicsObject()
if phys:IsValid() then
	phys:EnableGravity(false)
	phys:EnableDrag(false)
	phys:SetBuoyancyRatio(0)
	phys:Wake()
end

self:EmitSound("ricochet/disc_fire.wav")

self.DeathTime = self.DeathTime or CurTime() + self.DeathLimit 
self.Direction = Vector(0, 0, 0)
self.Bounces = 0

end

function ENT:Launch(speed)
local owner = self:GetOwner()
local phys = self:GetPhysicsObject()

if phys:IsValid() then
	phys:SetVelocityInstantaneous(self:GetForward() * speed)
	self.Direction = self:GetForward()
end

end

function ENT:Touch(hitent)
local owner = self:GetOwner()

if IsValid(hitent) and hitent:IsPlayer() and not (hitent == owner) and (not (hitent:Team() == owner:Team()) or (GetGlobalString("rc_gametype") == "dm")) then
	hitent:SetLastAttacker(self:GetOwner())
	if self:GetPowerShot() then hitent:TakeDamage(999, self:GetOwner(), self) end
	hitent:SetVelocity(self.Direction * 1000)
end

self:EmitSound("ricochet/disc_hit"..math.random(1,2)..".wav", 78, 80)
self:Remove()

end

function ENT:Think()
if self.DeathTime and CurTime() >= self.DeathTime then
self:Remove()
end
end

function ENT:PhysicsCollide(data, physobj)
local vphys = physobj:GetVelocity() * data.OurOldVelocity:Length()
local angles = self:GetAngles()

physobj:SetVelocityInstantaneous(Vector(vphys.x / 1000, vphys.y / 1000, 0))

self:EmitSound("ricochet/disc_hit"..math.random(1,2)..".wav", 78, 80)
self.Direction = self:GetForward()
self.Bounces = self.Bounces + 1

self.MaxBounces &lt;= self.Bounces  --This line produeces an expected symobol near '&lt;=' error :\
if data.HitEntity:IsWorld() then --Is there away to remove this if it goes outside the map (Hits edge), versus ingame walls. It bounces off the edge of map
	timer.Simple(0, function() --Remove the next frame..
		if (IsValid(self)) then
			self:Remove()
		end
	end)
end

end

function ENT:OnRemove()
local owner = self:GetOwner()

if owner:Alive() and owner:GetActiveWeapon():Clip1() &lt; 3 then
	owner:GetActiveWeapon():SetClip1(owner:GetActiveWeapon():Clip1() + self:GetAmmoBack()) 
end

local effectdata = EffectData()
effectdata:SetOrigin(self:LocalToWorld(self:OBBCenter()))

if owner:Team() == TEAM_BLUE then
	util.Effect("discdisintegration_blue", effectdata)
elseif owner:Team() == TEAM_RED or owner:Team() == TEAM_DEATHMATCH then
	util.Effect("discdisintegration_red", effectdata)
else
	util.Effect("discdisintegration_gray", effectdata)	
end

end
[/lua]