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

216 lines
6.9 KiB
Lua

WireToolSetup.setCategory( "Physics/Force" )
WireToolSetup.open( "motor", "Motor", "gmod_wire_motor", nil, "Motors" )
if CLIENT then
language.Add( "Tool.wire_motor.name", "Motor Tool (Wire)" )
language.Add( "Tool.wire_motor.desc", "Makes a controllable motor" )
language.Add( "WireMotorTool_torque", "Torque:" )
language.Add( "WireMotorTool_friction", "Hinge Friction:" )
language.Add( "WireMotorTool_nocollide", "No Collide" )
language.Add( "WireMotorTool_forcelimit", "Force Limit:" )
language.Add( "WireMotorTool_offset", "Position Offset:" )
TOOL.Information = {
{ name = "left_0", stage = 0, text = "Choose the wheel's axis" },
{ name = "left_1", stage = 1, text = "Choose the base's axis" },
{ name = "left_2", stage = 2, text = "Place the controller" },
}
end
WireToolSetup.BaseLang()
WireToolSetup.SetupMax( 10 )
if SERVER then
function TOOL:MakeEnt(ply, model, Ang, trace)
return MakeWireMotorController(ply, trace.HitPos, Ang, nil, model, self.constraint, self.axis)
end
end
function TOOL:GetConVars()
return self:GetClientNumber( "torque" ),
self:GetClientNumber( "friction" ),
self:GetClientNumber( "nocollide" ),
self:GetClientNumber( "forcelimit" ),
self:GetClientNumber( "offset" )
end
function TOOL:LeftClick_Update( trace )
local const = trace.Entity.constraint
if IsValid( const ) then
-- Don't remove the controller when the constraint is removed
const:DontDeleteOnRemove( trace.Entity )
if IsValid(trace.Entity.axis) then trace.Entity.axis:DontDeleteOnRemove( trace.Entity ) end
-- Get constraint info
local tbl = const:GetTable()
-- Remove constraint
const:Remove()
-- Get convars
local torque, friction, nocollide, forcelimit = self:GetConVars()
-- Make new constraint, at the old constraint's position, but with the new convar settings
local const, axis = MakeWireMotor( self:GetOwner(),
tbl.Ent1, tbl.Ent2,
tbl.Bone1, tbl.Bone2,
tbl.LPos1, tbl.LPos2,
friction, torque, nocollide, forcelimit )
-- Set the new references
const.MyCrtl = trace.Entity:EntIndex()
trace.Entity:SetConstraint( const )
trace.Entity:DeleteOnRemove( const )
if axis then
trace.Entity:SetAxis( axis )
trace.Entity:DeleteOnRemove( axis )
end
end
end
function TOOL:LeftClick( trace )
if IsValid( trace.Entity ) and trace.Entity:IsPlayer() then return end
-- If there's no physics object then we can't constraint it!
if SERVER and not util.IsValidPhysicsObject( trace.Entity, trace.PhysicsBone ) then return false end
local iNum = self:NumObjects()
local Phys = trace.Entity:GetPhysicsObjectNum( trace.PhysicsBone )
-- Update existing constraint
if self:CheckHitOwnClass( trace ) and iNum == 0 then
if SERVER then
self:LeftClick_Update( trace )
end
return true
end
-- Don't allow us to choose the world as the first object
if iNum == 0 and not IsValid( trace.Entity ) then return end
-- Don't allow us to choose the same object
if iNum == 1 and trace.Entity == self:GetEnt(1) then return end
-- Get client's CVars
local torque, friction, nocollide, forcelimit, offset = self:GetConVars()
if iNum > 1 then
if CLIENT then
self:ClearObjects()
return true
end
local ply = self:GetOwner()
local Ent1, Ent2, Ent3 = self:GetEnt(1), self:GetEnt(2), trace.Entity
local const, axis = self.constraint, self.axis
if not const or not IsValid( const ) then
WireLib.AddNotify(self:GetOwner(), "Wire Motor Invalid!", NOTIFY_GENERIC, 7)
self:ClearObjects()
self:SetStage(0)
return
end
local controller = self:LeftClick_Make(trace, ply)
if isbool(controller) then return controller end
self:LeftClick_PostMake(controller, ply, trace)
if controller then
controller:DeleteOnRemove( const )
if axis then controller:DeleteOnRemove( axis ) end
end
self:ClearObjects()
self:SetStage(0)
elseif iNum == 1 then
self:SetObject( iNum + 1, trace.Entity, trace.HitPos, Phys, trace.PhysicsBone, trace.HitNormal )
if CLIENT then
self:ClearObjects()
self:ReleaseGhostEntity()
return true
end
local Ent1, Ent2 = self:GetEnt(1), self:GetEnt(2)
local Bone1, Bone2 = self:GetBone(1), self:GetBone(2)
local WPos1, WPos2 = self:GetPos(1), self:GetPos(2)
local LPos1, LPos2 = self:GetLocalPos(1), self:GetLocalPos(2)
local Norm1, Norm2 = self:GetNormal(1), self:GetNormal(2)
local Phys1, Phys2 = self:GetPhys(1), self:GetPhys(2)
-- Note: To keep stuff ragdoll friendly try to treat things as physics objects rather than entities
local Ang1, Ang2 = Norm1:Angle(), (Norm2 * -1):Angle()
local TargetAngle = Phys1:AlignAngles( Ang1, Ang2 )
Phys1:SetAngles( TargetAngle )
-- Move the object so that the hitpos on our object is at the second hitpos
local TargetPos = WPos2 + (Phys1:GetPos() - self:GetPos(1))
-- Set the position
Phys1:SetPos( TargetPos )
-- Wake up the physics object so that the entity updates
Phys1:Wake()
-- Set the hinge Axis perpendicular to the trace hit surface
LPos1 = Phys1:WorldToLocal( WPos2 + Norm2 * 64 )
local constraint, axis = MakeWireMotor( self:GetOwner(), Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, friction, torque, nocollide, forcelimit )
self.constraint, self.axis = constraint, axis
undo.Create("gmod_wire_motor")
if axis then undo.AddEntity( axis ) end
if constraint then undo.AddEntity( constraint ) end
undo.SetPlayer( self:GetOwner() )
undo.Finish()
if axis then self:GetOwner():AddCleanup( "constraints", axis ) end
if constraint then self:GetOwner():AddCleanup( "constraints", constraint ) end
self:SetStage(2)
self:ReleaseGhostEntity()
else
offset = math.Clamp(offset, 0, 1024)
self:SetObject( iNum + 1, trace.Entity, trace.HitPos + trace.HitNormal*offset, Phys, trace.PhysicsBone, trace.HitNormal )
self:StartGhostEntity( trace.Entity )
self:SetStage( iNum+1 )
end
return true
end
function TOOL:RightClick( trace )
return false
end
function TOOL:Reload( trace )
if not IsValid( trace.Entity ) or trace.Entity:IsPlayer() then return false end
if CLIENT then return true end
return constraint.RemoveConstraints( trace.Entity, "WireMotor" )
end
function TOOL:Think()
if self:NumObjects() == 1 then self:UpdateGhostEntity() end
end
TOOL.ClientConVar = {
torque = 500,
friction = 1,
nocollide = 1,
forcelimit = 0,
offset = 2,
model = "models/jaanus/wiretool/wiretool_siren.mdl"
}
function TOOL.BuildCPanel(panel)
local models = {
["models/jaanus/wiretool/wiretool_siren.mdl"] = true,
["models/jaanus/wiretool/wiretool_controlchip.mdl"] = true
}
WireDermaExts.ModelSelect( panel, "wire_motor_model", models, 1 )
panel:NumSlider( "#WireMotorTool_torque", "wire_motor_torque", 0, 10000, 5 )
panel:NumSlider( "#WireMotorTool_forcelimit", "wire_motor_forcelimit", 0, 50000, 10 )
panel:NumSlider( "#WireMotorTool_friction", "wire_motor_friction", 0, 100, 1 )
panel:NumSlider( "#WireMotorTool_offset", "wire_motor_offset", 0, 512, 2 )
panel:CheckBox( "#WireMotorTool_nocollide", "wire_motor_nocollide" )
end