TOOL.Category = "Conna's Tools" TOOL.Name = "#Constraint Breaker Tool" TOOL.Command = nil TOOL.ConfigName = "" // Tables local ConstraintBreaker = {} ConstraintBreaker.Constraints = { {"phys_constraint", "Welds"}, {"phys_lengthconstraint", "Ropes"}, {"phys_spring", "Elastic"}, {"phys_keepupright", "Keep Uprights"}, {"phys_slideconstraint", "Sliders"}, {"phys_hinge", "Axis"}, {"logic_collision_pair", "Nocollides"}, {"phys_torque", "Motors"}, {"phys_pulleyconstraint", "Pulleys"}, {"phys_ballsocket", "Ballsockets"}, {"gmod_winch_controller", "Winches/Hydraulics/Muscles"} } // ConVars TOOL.ClientConVar["Key"] = "5" TOOL.ClientConVar["Delay"] = "0" TOOL.ClientConVar["Delete"] = "0" TOOL.ClientConVar["Connected"] = "0" for K, V in pairs(ConstraintBreaker.Constraints) do local Type = V[1] TOOL.ClientConVar[Type] = "1" end // Friendly function ConstraintBreaker.Friendly(Entity, ID) if (Entity.ConstraintBreaker[ID] and Entity.ConstraintBreaker[ID] == 1) then return true end return false end // Client if (CLIENT) then language.Add("Tool_constraintbreaker_name", "Constraint Breaker Tool") language.Add("Tool_constraintbreaker_desc", "Makes all constraints connected to an entity break when a key is pressed") language.Add("Tool_constraintbreaker_0", "Left click on an entity to add a Constraint Breaker") language.Add("Undone_constraintbreaker", "Undone Constraint Breaker") end // Message function TOOL:Message(Text) if SERVER then self:GetOwner():SendLua("GAMEMODE:AddNotify('"..Text.."', NOTIFY_GENERIC, 10)") self:GetOwner():SendLua("surface.PlaySound('ambient/water/drip"..math.random(1, 4)..".wav')") end end // Get entities function ConstraintBreaker.GetConstraints(Entity) local Constraints = {} for K, V in pairs(Entity.Constraints) do local Index = V if (!Constraints[Index]) then Constraints[Index] = V end end return Constraints end // Get entities local function ExtractEntities(Entity, Entities, Constraints) Constraints = Constraints or {} Entities = Entities or {} if (!Entity:IsValid()) then return Entities, Constraints end Entities[Entity:EntIndex()] = Entity if (!constraint.HasConstraints(Entity)) then return Entities, Constraints end local Cons = constraint.GetTable(Entity) for K, V in pairs(Cons) do local Index = V.Constraint if (!Constraints[Index]) then Constraints[Index] = V.Constraint for B, J in pairs(V.Entity) do local E, C = ExtractEntities(J.Entity, Entities, Constraints) table.Merge(Entities, E) table.Merge(Constraints, C) end end end return Entities, Constraints end // Left click function TOOL:LeftClick(Trace) if Trace.Entity then if !Trace.Entity:IsValid() or Trace.Entity:IsPlayer() or Trace.HitWorld or Trace.Entity:IsNPC() then return false end end if(CLIENT) then return true end if(!SERVER) then return false end // Locals local User = self:GetOwner() local Entity = Trace.Entity // Values local Key = self:GetClientNumber("Key") local Delay = self:GetClientNumber("Delay") local Delete = self:GetClientNumber("Delete") local Connected = self:GetClientNumber("Connected") // Nice and clean Delay = math.floor(Delay) // Check if (Delay < 0) then self:GetOwner():ConCommand("constraintbreaker_Delay 0\n") Delay = 0 end // ConstraintBreaker table for entity Entity.ConstraintBreaker = {} // Values Entity.ConstraintBreaker.Connected = Connected Entity.ConstraintBreaker.Delay = Delay Entity.ConstraintBreaker.Delete = Delete Entity.ConstraintBreaker.ID = numpad.OnUp(User, Key, "ConstraintBreaker", Entity, false) // Constraints for K, V in pairs(ConstraintBreaker.Constraints) do local Type = V[1] Entity.ConstraintBreaker[Type] = self:GetClientNumber(Type) end // Undo local function Function(Undo, Entity) if (Entity:IsValid()) then numpad.Remove(Entity.ConstraintBreaker.ID) Entity.ConstraintBreaker = nil end end undo.Create("constraintbreaker") undo.SetPlayer(User) undo.AddFunction(Function, Entity) undo.Finish() // Message self:Message("Constraint Breaker added to entity, press "..Key.." to activate!") return true end // Pressed key if SERVER then function TOOL.Pressed(Player, Entity, Key, IDX) if !Entity:IsValid() then return end if not Key then local ID = Entity.ConstraintBreaker.ID // Remove the numpad ID if (Entity.ConstraintBreaker.Delete == 1) then numpad.Remove(ID) end // Timed function local function Function(Entity) if !Entity:IsValid() then return end local Constraints = {} local Entities = {} if (Entity.ConstraintBreaker.Connected == 1) then Entities, Constraints = ExtractEntities(Entity) else Constraints = ConstraintBreaker.GetConstraints(Entity) end for K, V in pairs(Constraints) do if (V) then local Valid = V:IsValid() if (Valid) then local Class = V:GetClass() if (ConstraintBreaker.Friendly(Entity, Class)) then V:Remove() end end end end local Random = math.random(1, 3) local Emit = Sound("physics/metal/metal_chainlink_impact_hard"..Random..".wav") Entity:EmitSound(Emit) end timer.Create("ConstraintBreaker: "..Entity:EntIndex(), Entity.ConstraintBreaker.Delay, 1, Function, Entity) end end numpad.Register("ConstraintBreaker", TOOL.Pressed) end // Build CPanel function TOOL.BuildCPanel(Panel) Panel:AddControl("Header", {Text = "#Tool_constraintbreaker_name", Description = "#Tool_constraintbreaker_desc"}) Panel:AddControl("Numpad", {Label = "Button", ButtonSize = "22", Command = "constraintbreaker_Key"}) Panel:AddControl("Slider", {Label = "Delay untill constraints break", Type = "Integer", Min = 0, Max = 10, Command = "constraintbreaker_Delay"}) Panel:AddControl("CheckBox", {Label = "Delete Constraint Breaker after use", Command = "constraintbreaker_Delete"}) Panel:AddControl("CheckBox", {Label = "Break constraints on entities connected to the entity", Command = "constraintbreaker_Connected"}) for K, V in pairs(ConstraintBreaker.Constraints) do local Type = V[1] local ID = V[2] Panel:AddControl("CheckBox", {Label = "Break "..ID, Command = "constraintbreaker_"..Type}) end end