ShouldCollide dynamically changing

What’s the best way to emulate GAMEMODE:ShouldCollide without breaking the physics? I have players colliding or not colliding with certain entities at certain times but this breaks the physics because it’s not static. Is there a collisiongroup set that would work? Surely someone has worked with something like this.

What do you mean, “breaking the physics”?

[lua]function GM:ShouldCollide( a, b )
if( a:IsPlayer() and b:IsPlayer() ) then return false; end
return true;
end[/lua]

[lua]function GM:ShouldCollide( a, b )
if( a:IsPlayer() and b:IsPlayer() and (a:KeyDown(IN_ATTACK) or b:KeyDown(IN_ATTACK)) then return false; end
return true;
end[/lua]

That should break it after a while.

I believe it breaks if you return false for A + B, then return true for B + A

I’ve also noticed the physics breaks if you play a game that has pretty much anything related to modifying physics in some way, if you play long enough (I’ve had it happen in under an hour a few times). You get the “liquid solid” thing, where props sink into the floor as if its a liquid, then get stuck there - and if you wake the physics objects, they kinda bounce around. It’s really weird.

I would imagine, though I have no evidence to support this, that the more you fuck with the physics (such as how JetBoom does it), the quicker the physics fucks. It can get really frustrating, if what you’re working on depends on these custom physics.

However, yes, if you do what you said, then that really fucks the physics.

I make sure that it returns the same thing.

Any inconsistencies in the circumstances will break it. I think it’s only intended for modifying collisions between entity classes, and not for saying A sometimes collides with B.

I remember hearing something about “custom” collision types for Gmod 13, but I haven’t really been on the scene much lately so take it with a grain of salt.

The closest thing I could find in the engine was C_BaseEntity::UpdatePartitionListEntry, but that’s only defined in cl_dll.
I couldn’t find anything in dlls or game_shared.

Perhaps you could ask Garry for a shared Entity:UpdatePhysics() function?
Calling it too rapidly would probably be pretty bad, though.

Until then, perhaps you could try changing the collision group to DEBRIS (or something) and back again, and see if that calls ShouldCollide to update physics stuff.

You should also wake physics entities after you change the collision rules, to ensure props resting on other props are dealt with appropriately.

This is what I’m doing. At this point I think I’m going to have to create new entities every time collision rules change or make my own physics of some sort like parenting the player to an invisible box that always has these rules.

gamemode shared
[lua]function GM:ShouldCollide(enta, entb)
if enta.ShouldNotCollide and enta:ShouldNotCollide(entb) or entb.ShouldNotCollide and entb:ShouldNotCollide(enta) then
return false
end

return true

end[/lua]

player object shared
[lua]function meta:ShouldNotCollide(ent)
return ent:IsPlayer() and (self:Team() == ent:Team() or self.NoCollideAll or ent.NoCollideAll) or self:GetBarricadeGhosting() and ent:IsBarricadeProp()
end[/lua]

server
[lua]
– some stuff with KeyPress toggling GetBarricadeGhosting() on and off.
[/lua]

You know I’ve never had the physics crash even when changing rules between two players.

You’ll need Garry to bind either IPhysicsObject::RecheckCollisionFilter or CBaseEntity::CollisionRulesChanged.

[editline]28th December 2011[/editline]

For now, you can just change the collision group and reset it (CBaseEntity::SetCollisionGroup calls CollisionRulesChanged); much better than creating new entities every time.

Where are you suggesting I put that? In shouldcollide?

You’ll need to hook it into any location where the collision rules changes; in your case, those are Player:SetTeam(), Entity.NoCollideAll = something, Entity:SetBarricadeGhosting(), and Entity:SetIsBarricadeProp().

Simply call this whenever any of those change:
[lua]
function _R.Entity:CollisionRulesChanged()
– HACK!
local cg = self:GetCollisionGroup()
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
self:SetCollisionGroup(cg)
end
[/lua]

It will cause it to recheck twice, but that shouldn’t be a problem.

I’ll try that out. Using it in ShouldCollide eventually caused a worker thread to crash.

This really needs to be added with big letters next to the “function” wherever it’s stated :v:



void CBaseEntity::CollisionRulesChanged() {
        if ( VPhysicsGetObject() )
        {
                extern bool PhysIsInCallback();
                if ( PhysIsInCallback() )  Warning("Changing collision rules within a callback is likely to cause crashes!
");
                        

So yeah I did the collision group thing and that works fine. Two days or so and no crashes. You just have to put self:CollisionRulesChanged() at every instance where… well, the collision rules change.

You are a sexy beast!<3

what are you using this for?

i’m a curious person.

A feature on the NoxiousNet ZS server:



Humans can now hold down ZOOM (default is Z) to use ghosting mode. This causes you to walk extremely slow but you are able to move freely through barricade props. This includes deployables as well as nailed objects.

Oh, that’s cool.

I’m assuming it’s also going to be used for RTP so the physics don’t break every other match.