• Automatically freeze anything welded to the ground
    9 replies, posted
Hi, I'm making a gamemode deriving from sandbox and trying to make it so that any time a player welds something to the ground, the prop gets automatically frozen (i.e. like you right-clicked the physgun while holding it). The players in this gamemode will not receive the physgun so I have to do it in code. I tried using the hook GM:OnEntityCreated and GetConstrainedEntities on the phys_constraint entity that gets created, but it always seems to return two nils. I'm thinking this may just be because the hook is called before the entity is properly defined - am I right? And if so, how do I overcome that? Thanks in advance! P.S. I tried using GetConstrainedPhysObjects as well with the same result, for the record...
I think the most straightforward way would be to override the creation of weld constraints. [code] local oldconstraintweld = constraint.Weld function constraint.Weld(ent1,ent2,a,b,c,d,e) if !ent1:IsWorld() && ent1:GetPhysicsObject() then ent1:GetPhysicsObject():EnableMotion(false) end if !ent2:IsWorld() && ent2:GetPhysicsObject() then ent2:GetPhysicsObject():EnableMotion(false) end return oldconstraintweld(ent1,ent2,a,b,c,d,e) end [/code] With this, all items being welded should immediately freeze. [editline]17th January 2015[/editline] Or did you want only things welded to the ground to freeze, and not simply any welded object? [code] local oldconstraintweld = constraint.Weld function constraint.Weld(ent1,ent2,a,b,c,d,e) if ent1:IsWorld() && !ent2:IsWorld() && ent2:GetPhysicsObject() then ent2:GetPhysicsObject():EnableMotion(false) end if ent2:IsWorld() && !ent1:IsWorld() && ent1:GetPhysicsObject() then ent1:GetPhysicsObject():EnableMotion(false) end return oldconstraintweld(ent1,ent2,a,b,c,d,e) end [/code] edit: forgot to return the result, fixed (thanks kogitsune)
Ooh, I didn't know you could do that. Now, is it possible to unfreeze them when the weld is removed? Thanks for your help :) Edit: actually I think I can figure this one out for myself using GM:EntityRemoved. I'll bump this if I get stuck (or solve it!) Edit: Aww :(
[code] local oldconstraintweld = constraint.Weld function constraint.Weld(ent1,ent2,a,b,c,d,e) if ent1:IsWorld() && !ent2:IsWorld() && ent2:GetPhysicsObject() then ent2:GetPhysicsObject():EnableMotion(false) end if ent2:IsWorld() && !ent1:IsWorld() && ent1:GetPhysicsObject() then ent1:GetPhysicsObject():EnableMotion(false) end return oldconstraintweld(ent1,ent2,a,b,c,d,e) end ... weld = constraint.Weld( left, right, ... ) if IsValid( weld ) then local v if ent1:IsWorld( ) then v = ent2:GetPhysicsObject( ) else v = ent1:GetPhysicsObject( ) end weld:CallOnRemove( "ReleaseOnBreak", function( this ) if IsValid( v ) then v:EnableMotion( true ) v:Wake( ) end end ) end[/code] Something like that would probably be what you want - could definitely use a little cleaning though.
Kogitsune is saying to edit the weld tool, but here's a better way: [code] local oldconstraintweld = constraint.Weld function constraint.Weld(ent1,ent2,a,b,c,d,e) local ent if ent1:IsWorld() && !ent2:IsWorld() && ent2:GetPhysicsObject() then ent = ent2 end if ent2:IsWorld() && !ent1:IsWorld() && ent1:GetPhysicsObject() then ent = ent1 end local weld = oldconstraintweld(ent1,ent2,a,b,c,d,e) if IsValid(ent) then ent:GetPhysicsObject():EnableMotion(false) weld:CallOnRemove("ReleaseOnBreak",function() if IsValid(ent) then ent:EnableMotion(true) ent:Wake() end end) end return weld end [/code] If the entity doesn't start moving after the weld is removed, try waking the ent's physics object.
Awesome, thanks, uhh... bitches.... :S This freezes the prop when welding, but unfortunately, when undoing the weld I get this error: [img]http://gyazo.com/3525e047902f30a02895da4ea9573d42.png[/img] I've made an attempt to fix this by adding a parameter to the function inside CallOnRemove, which sadly didn't work. My code currently looks like this: [lua]local oldweld = constraint.Weld function constraint.Weld( ent1 , ent2 , a , b , force , c , d ) local ent if !ent1:IsWorld() && ent2:IsWorld() && ent2:GetPhysicsObject() then ent = ent1 end if !ent2:IsWorld() && ent1:IsWorld() && ent1:GetPhysicsObject() then ent = ent2 end local weld = oldweld( ent1 , ent2 , a , b , force, c , d ) if IsValid(ent) && force == 0 then ent:GetPhysicsObject():EnableMotion(false) weld:CallOnRemove( "ReleaseOnBreak" , function( x ) if IsValid(x) then x:EnableMotion(true) x:Wake() end end , ent) -- This is line 39 end return weld end[/lua] What I THINK is happening is that we're using ent in the function, but ent was a local function to our new constraint.Weld so it was garbage-collected. That's why I tried passing it as a parameter. I'm out of ideas. You got any? Either way, thanks immensely for your help! [b]Edit:[/b] wait a sec... [b]Edit:[/b] Okay! I got it working! First of all: obviously you were right, the local ent wasn't the problem. To quote myself from another thread: [QUOTE=Neat-Nit;46955686]Still very new to lua, so I don't have the whole 'scope' thing [i]quite[/i] figured out yet...[/QUOTE] Now, as for the actual problem: seems the only problem in the original code you gave me was a missing :GetPhysObject() - entities don't have EnableMotion(). However, this didn't solve the problem for me, since I introduced a new one when I tried to use args! Apparently, the first parameter of the function is the weld entity, and the ent ended up being the SECOND parameter! Which was being ignored, since x was set as the first parameter. Long story short, both of these work: [lua]local oldweld = constraint.Weld function constraint.Weld( ent1 , ent2 , a , b , force , c , d ) local ent if !ent1:IsWorld() && ent2:IsWorld() && ent1:GetPhysicsObject() then ent = ent1 end if !ent2:IsWorld() && ent1:IsWorld() && ent2:GetPhysicsObject() then ent = ent2 end local weld = oldweld( ent1 , ent2 , a , b , force, c , d ) if IsValid(ent) && force == 0 then ent:GetPhysicsObject():EnableMotion(false) weld:CallOnRemove( "ReleaseOnBreak" , function( _ , x ) if IsValid(x) then x:GetPhysicsObject():EnableMotion(true) x:PhysWake() end end , ent) end return weld end[/lua] [lua]local oldweld = constraint.Weld function constraint.Weld( ent1 , ent2 , a , b , force , c , d ) local ent if !ent1:IsWorld() && ent2:IsWorld() && ent1:GetPhysicsObject() then ent = ent1 end if !ent2:IsWorld() && ent1:IsWorld() && ent2:GetPhysicsObject() then ent = ent2 end local weld = oldweld( ent1 , ent2 , a , b , force, c , d ) if IsValid(ent) && force == 0 then ent:GetPhysicsObject():EnableMotion(false) weld:CallOnRemove( "ReleaseOnBreak" , function() if IsValid(ent) then ent:GetPhysicsObject():EnableMotion(true) ent:PhysWake() end end) end return weld end[/lua] Thank you for the help!! [b]Edit:[/b] I added this information to the [url=http://wiki.garrysmod.com/page/Entity/CallOnRemove]wiki[/url] ([url=http://wiki.garrysmod.com/index.php?title=Entity%2FCallOnRemove&action=historysubmit&diff=19169&oldid=8232]my additions[/url]) in case anyone in the future runs into the same confusion...
Here's how I do it: [code] // Prevent object from moving, and weld object to world - prevents invisible props from moving. local _weld = _options.weld; local _phys = _ent:GetPhysicsObject( ); if( _weld && IsValid( _phys ) ) then _ent:GetPhysicsObject( ):EnableMotion( false ); constraint.Weld( _ent, game.GetWorld( ) ); end [/code] As part of a larger function but everything is here to make it work.
[QUOTE=Acecool;46967938]Here's how I do it: [code] // Prevent object from moving, and weld object to world - prevents invisible props from moving. local _weld = _options.weld; local _phys = _ent:GetPhysicsObject( ); if( _weld && IsValid( _phys ) ) then _ent:GetPhysicsObject( ):EnableMotion( false ); constraint.Weld( _ent, game.GetWorld( ) ); end [/code] As part of a larger function but everything is here to make it work.[/QUOTE] Sorry to be blunt, but that is completely unrelated to what I asked... Check out foxcock's code above, he understood me! :)
[quote]Automatically freeze anything welded to the ground[/quote] My snippet provides the means to freeze, you only need to check if the weld is between an object and the world and then apply it.
[QUOTE=Acecool;46968202]My snippet provides the means to freeze, you only need to check if the weld is between an object and the world and then apply it.[/QUOTE] Your snippet provides both the means to freeze, and the means to weld; But it does not explain how to have code run when a player welds using the toolgun.
Sorry, you need to Log In to post a reply to this thread.