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

217 lines
7.1 KiB
Lua

AddCSLuaFile()
DEFINE_BASECLASS( "base_wire_entity" )
ENT.PrintName = "Wire Hydraulic Controller"
ENT.WireDebugName = "Hydraulic"
if CLIENT then return end -- No more client
function ENT:Initialize()
BaseClass.Initialize(self)
self.Inputs = WireLib.CreateInputs( self, { "Length", "In", "Out", "Constant", "Damping" } )
self.Outputs = WireLib.CreateOutputs( self, { "Length", "Target Length", "Constant", "Damping" } )
self.TargetLength = 0
self.current_constant = 0
self.current_damping = 0
self.direction = 0
self.last_time = CurTime()
end
function ENT:GetWPos( ent, phys, lpos )
if ent:EntIndex() == 0 then
return lpos
end
if IsValid( phys ) then
return phys:LocalToWorld( lpos )
else
return ent:LocalToWorld( lpos )
end
end
function ENT:GetDistance()
local CTable = self.constraint:GetTable()
local p1 = self:GetWPos( CTable.Ent1, CTable.Phys1 or CTable.Ent1:GetPhysicsObject(), CTable.LPos1 )
local p2 = self:GetWPos( CTable.Ent2, CTable.Phys2 or CTable.Ent2:GetPhysicsObject(), CTable.LPos2 )
return p1:Distance(p2)
end
function ENT:Think()
BaseClass.Think( self )
if not IsValid(self.constraint) then return end
local deltaTime = CurTime() - self.last_time
self.last_time = CurTime()
if self.direction ~= 0 then
self:SetLength(math.max(self.TargetLength + (self.constraint:GetTable().speed * self.direction * deltaTime), 1))
end
self:UpdateOutputs( true )
self:NextThink(CurTime()+0.05)
return true
end
function ENT:UpdateOutputs( OnlyLength )
local curLength = self:GetDistance()
WireLib.TriggerOutput( self, "Length", curLength )
WireLib.TriggerOutput( self, "Target Length", self.TargetLength )
if not OnlyLength then
WireLib.TriggerOutput( self, "Length", self.TargetLength )
WireLib.TriggerOutput( self, "Constant", self.current_constant )
WireLib.TriggerOutput( self, "Damping", self.current_damping )
end
self:SetOverlayText(string.format("%s length: %.2f\nConstant: %i\nDamping: %i", (self.constraint.stretchonly and "Winch" or "Hydraulic"), curLength, self.current_constant, self.current_damping))
end
function ENT:SetConstraint( c )
self.constraint = c
if self.current_constant ~= 0 or (self.Inputs and self.Inputs.Constant.Src) then
self:TriggerInput("Constant", self.Inputs.Constant.Value)
else
self.current_constant = self.constraint:GetKeyValues().constant
end
if self.current_damping ~= 0 or (self.Inputs and self.Inputs.Damping.Src) then
self:TriggerInput("Damping", self.Inputs.Damping.Value)
else
self.current_damping = self.constraint:GetKeyValues().damping
end
self:SetLength(self:GetDistance())
self:UpdateOutputs()
end
function ENT:SetRope( r )
self.rope = r
end
function ENT:SetLength(value)
self.TargetLength = value
self.constraint:Fire("SetSpringLength", value, 0)
if IsValid(self.rope) then self.rope:Fire("SetLength", value, 0) end
end
function ENT:TriggerInput(iname, value)
if not IsValid(self.constraint) then return end
if (iname == "Length") then
self:SetLength(math.max(value,1))
elseif (iname == "In") then
self.direction = -value
elseif (iname == "Out") then
self.direction = value
elseif (iname == "Constant") then
if value == 0 then
self.current_constant, _ = WireLib.CalcElasticConsts(self.constraint.Ent1, self.constraint.Ent2)
else
self.current_constant = value
end
self.constraint:Fire("SetSpringConstant",self.current_constant)
timer.Simple( 0.1, function() if IsValid(self) then self:UpdateOutputs() end end) -- Needs to be delayed because ent:Fire doesn't update that fast.
elseif (iname == "Damping") then
if value == 0 then
_, self.current_damping = WireLib.CalcElasticConsts(self.constraint.Ent1, self.constraint.Ent2)
else
self.current_damping = value
end
self.constraint:Fire("SetSpringDamping",self.current_damping)
timer.Simple( 0.1, function() if IsValid(self) then self:UpdateOutputs() end end)
end
end
-- needed for the constraint to find the controller after being duplicator pasted
local WireHydraulicTracking = {}
function MakeWireHydraulicController( pl, Pos, Ang, model, MyEntId, const, rope )
local controller = WireLib.MakeWireEnt(pl, {Class = "gmod_wire_hydraulic", Pos=Pos, Angle=Ang, Model=model})
if not IsValid(controller) then return end
if not const then
WireHydraulicTracking[ MyEntId ] = controller
else
controller.MyId = controller:EntIndex()
const.MyCrtl = controller:EntIndex()
controller:SetConstraint( const )
controller:DeleteOnRemove( const )
end
if rope then
controller:SetRope( rope )
controller:DeleteOnRemove( rope )
end
return controller
end
duplicator.RegisterEntityClass("gmod_wire_hydraulic", MakeWireHydraulicController, "Pos", "Ang", "Model", "MyId" )
duplicator.RegisterEntityClass("gmod_wire_winch_controller", MakeWireHydraulicController, "Pos", "Ang", "Model", "MyId")
scripted_ents.Alias("gmod_wire_winch_controller", "gmod_wire_hydraulic")
function MakeWireHydraulic( pl, Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, width, material, speed, fixed, stretchonly, MyCrtl )
if not constraint.CanConstrain(Ent1, Bone1) then return false end
if not constraint.CanConstrain(Ent2, Bone2) then return false end
local Phys1 = Ent1:GetPhysicsObjectNum( Bone1 )
local Phys2 = Ent2:GetPhysicsObjectNum( Bone2)
local WPos1 = Phys1:LocalToWorld( LPos1 )
local WPos2 = Phys2:LocalToWorld( LPos2 )
if ( Phys1 == Phys2 ) then return false end
local constant, dampen = WireLib.CalcElasticConsts(Ent1, Ent2)
local const, rope = constraint.Elastic( Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, constant, dampen, 0, material, width, stretchonly )
if not const then return nil, rope end
if fixed == 1 then
local slider = constraint.Slider( Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, 0 )
slider:SetTable( {} )
const:DeleteOnRemove( slider )
end
local ctable = {
Type = "WireHydraulic",
pl = pl,
Ent1 = Ent1,
Ent2 = Ent2,
Bone1 = Bone1,
Bone2 = Bone2,
LPos1 = LPos1,
LPos2 = LPos2,
width = width,
material = material,
speed = speed,
fixed = fixed,
stretchonly = stretchonly
}
const:SetTable( ctable )
if MyCrtl then
local controller = WireHydraulicTracking[ MyCrtl ]
const.MyCrtl = controller:EntIndex()
controller.MyId = controller:EntIndex()
controller:SetConstraint( const )
controller:DeleteOnRemove( const )
if (rope) then
controller:SetRope( rope )
controller:DeleteOnRemove( rope )
end
Ent1:DeleteOnRemove( controller )
Ent2:DeleteOnRemove( controller )
const:DeleteOnRemove( controller )
end
return const, rope
end
duplicator.RegisterConstraint("WireHydraulic", MakeWireHydraulic, "pl", "Ent1", "Ent2", "Bone1", "Bone2", "LPos1", "LPos2", "width", "material", "speed", "fixed", "stretchonly", "MyCrtl")
-- Backwards compatibility with old dupes of Winches, which were just Hydraulics with strechonly = true
local function WinchToHydraulic(pl, Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, width, fwd_speed, bwd_speed, material, MyCrtl)
return MakeWireHydraulic(pl, Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, width, material, fwd_speed, 0, true, MyCrtl)
end
duplicator.RegisterConstraint("WireWinch", WinchToHydraulic, "pl", "Ent1", "Ent2", "Bone1", "Bone2", "LPos1", "LPos2", "width", "fwd_speed", "bwd_speed", "material", "MyCrtl")