dobrograd-13-06-2022/garrysmod/addons/feature-wire/lua/entities/gmod_wire_latch.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

208 lines
5.4 KiB
Lua

AddCSLuaFile()
DEFINE_BASECLASS( "base_wire_entity" )
ENT.PrintName = "Wire Constraint Latch"
ENT.Purpose = "Controllable weld and nocollide between two selected entities"
ENT.WireDebugName = "Latch"
if CLIENT then return end -- No more client
function ENT:Initialize()
self:PhysicsInit( SOLID_VPHYSICS )
self:SetMoveType( MOVETYPE_VPHYSICS )
self:SetSolid( SOLID_VPHYSICS )
self.Inputs = Wire_CreateInputs( self, { "Activate", "NoCollide", "Strength" } )
self.Outputs = Wire_CreateOutputs( self, { "Welded" } )
-- masks containing all current states
self.nocollide_masks = {
-- Ent1, Ent2 , nocollide between the two
{ false, false, true }, -- 1 nocollide between the two
{ true , false, false }, -- 2 nocollide Ent1 with all
{ false, true , false }, -- 3 nocollide Ent2 with all
{ true , true , false } -- 4 nocollide both with all
-- all other values: { false, false, false }
}
self.nocollide_description = {
"NoCollided",
"Ent1 has collisions disabled",
"Ent2 has collisions disabled",
"All collisions disabled"
}
self.Nocollide = nil
self:TriggerInput("NoCollide", 0)
end
-- Run if weld is removed (will run *after* Create_Weld)
local function Weld_Removed( weld, ent )
if IsValid(ent) then
if !ent.Constraint or ent.Constraint == weld then
ent.Constraint = nil
Wire_TriggerOutput( ent, "Welded", 0 )
ent:UpdateOverlay()
end
end
end
function ENT:Remove_Weld()
if self.Constraint then
if self.Constraint:IsValid() then
self.Constraint:Remove()
end
self.Constraint = nil
end
end
function ENT:Create_Weld()
self:Remove_Weld()
self.Constraint = MakeWireLatch( self.Ent1, self.Ent2, self.Bone1, self.Bone2, self.weld_strength or 0 )
if self.Constraint then
self.Constraint:CallOnRemove( "Weld Latch Removed", Weld_Removed, self )
end
end
-- This function is called by the STOOL
function ENT:SendVars( Ent1, Ent2, Bone1, Bone2, const )
self.Ent1 = Ent1
self.Ent2 = Ent2
self.Bone1 = Bone1
self.Bone2 = Bone2
self.Constraint = const
end
function ENT:TriggerInput( iname, value )
if iname == "Activate" then
if value == 0 and self.Constraint then
self:Remove_Weld()
elseif value ~= 0 and not self.Constraint then
self:Create_Weld()
Wire_TriggerOutput( self, "Welded", 1 )
end
elseif iname == "NoCollide" then
self.nocollide_status = value
local mask = self.nocollide_masks[value] or {false, false, false}
if IsValid( self.Ent1 ) then
local phys = self.Ent1:GetPhysicsObject()
if phys:IsValid() then phys:EnableCollisions(not mask[1]) end
end
if IsValid( self.Ent2 ) then
local phys = self.Ent2:GetPhysicsObject()
if phys:IsValid() then phys:EnableCollisions(not mask[2]) end
end
if mask[3] then
if not self.Nocollide then
if self.Ent1 and self.Ent2 then
-- enable NoCollide between the two entities
self.Nocollide = constraint.NoCollide( self.Ent1, self.Ent2, self.Bone1, self.Bone2 )
end
end
else
if self.Nocollide then
if self.Nocollide:IsValid() then
-- disable NoCollide between the two entities
self.Nocollide:Input("EnableCollisions", nil, nil, nil)
self.Nocollide:Remove()
end
self.Nocollide = nil
end
end
elseif iname == "Strength" then
local newvalue = math.max( value, 0 )
if newvalue ~= self.weld_strength then
self.weld_strength = newvalue
if self.Constraint then
self:Create_Weld()
end
end
end
self:UpdateOverlay()
end
function ENT:OnRemove()
self:TriggerInput("Activate", 0)
self:TriggerInput("NoCollide", 0)
end
function ENT:UpdateOverlay()
local desc = self.nocollide_description[self.nocollide_status]
if not desc then
if IsValid( self.Constraint ) then
self:SetOverlayText( "Welded" )
else
self:SetOverlayText( "Deactivated" )
end
return
end
local text = self.Constraint and "Welded and " or "Not welded but "
text = text .. desc
self:SetOverlayText( text )
end
-- duplicator support
function ENT:BuildDupeInfo()
local info = BaseClass.BuildDupeInfo(self) or {}
if IsValid( self.Ent1 ) then
info.Ent1 = self.Ent1:EntIndex()
info.Bone1 = self.Bone1
end
if IsValid( self.Ent2 ) then
info.Ent2 = self.Ent2:EntIndex()
info.Bone2 = self.Bone2
end
info.Activate = self.Constraint and 1 or 0
info.NoCollide = self.nocollide_status
info.weld_strength = self.weld_strength
return info
end
function ENT:ApplyDupeInfo(ply, ent, info, GetEntByID)
BaseClass.ApplyDupeInfo(self, ply, ent, info, GetEntByID)
self.Ent1 = GetEntByID(info.Ent1, game.GetWorld())
if IsValid(self.Ent1) then
self.Bone1 = info.Bone1
end
self.Ent2 = GetEntByID(info.Ent2, game.GetWorld())
if IsValid(self.Ent2) then
self.Bone2 = info.Bone2
end
self:TriggerInput("Strength", info.weld_strength or 0)
self:TriggerInput("Activate", info.Activate)
self:TriggerInput("NoCollide", info.NoCollide)
end
duplicator.RegisterEntityClass("gmod_wire_latch", WireLib.MakeWireEnt, "Data")
function MakeWireLatch( Ent1, Ent2, Bone1, Bone2, forcelimit )
if ( !constraint.CanConstrain( Ent1, Bone1 ) ) then return false end
if ( !constraint.CanConstrain( Ent2, Bone2 ) ) then return false end
local Phys1 = Ent1:GetPhysicsObjectNum( Bone1 )
local Phys2 = Ent2:GetPhysicsObjectNum( Bone2 )
if ( Phys1 == Phys2 ) then return false end
local const = constraint.Weld( Ent1, Ent2, Bone1, Bone2, forcelimit or 0 )
if !IsValid(const) then return nil end
const.Type = "" -- prevents the duplicator from copying this weld
return const
end