wiremod-svn-archive/wire/lua/weapons/gmod_tool/stools/wire_winch.lua
tad2020 19e831f08e updates in preparations for beta
changed deleteonremove to use new system in welds instead
massive updates to adv duplicator. now separate module and addon
include modified weight stool that support duplication
lots of other shit
2007-03-22 03:27:52 +00:00

351 lines
11 KiB
Lua

TOOL.Category = "Wire - Physics"
TOOL.Name = "Winch"
TOOL.Command = nil
TOOL.ConfigName = ""
TOOL.ClientConVar[ "material" ] = "cable/rope"
TOOL.ClientConVar[ "width" ] = "3"
TOOL.ClientConVar[ "fwd_speed" ] = "64"
TOOL.ClientConVar[ "bwd_speed" ] = "64"
--TOOL.ClientConVar[ "fwd_group" ] = "8"
--TOOL.ClientConVar[ "bwd_group" ] = "5"
if CLIENT then
language.Add( "Tool_wire_winch_name", "Winch Tool (Wire)" )
language.Add( "Tool_wire_winch_desc", "Makes a controllable winch" )
language.Add( "Tool_wire_winch_0", "Primary: Place winch\nSecondary: Place winch along the hit normal" )
language.Add( "Tool_wire_winch_1", "Left click on the second point" )
language.Add( "Tool_wire_winch_2", "Left click to place the controller" )
language.Add( "WireWinchTool_width", "Width:" )
language.Add( "WireWinchTool_material", "Material:" )
language.Add( "WireWinchTool_fixed", "Fixed:" )
language.Add( "undone_wirewinch", "Undone Wire Winch" )
end
function TOOL:LeftClick( trace )
if ( trace.Entity:IsValid() && trace.Entity:IsPlayer() ) then return end
// If there's no physics object then we can't constraint it!
if ( SERVER && !util.IsValidPhysicsObject( trace.Entity, trace.PhysicsBone ) ) then return false end
local iNum = self:NumObjects()
local Phys = trace.Entity:GetPhysicsObjectNum( trace.PhysicsBone )
self:SetObject( iNum + 1, trace.Entity, trace.HitPos, Phys, trace.PhysicsBone, trace.HitNormal )
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, rope = self.constraint, self.rope
// Attach our Controller to the Elastic constraint
local Ang = trace.HitNormal:Angle()
Ang.pitch = Ang.pitch + 90
local controller = MakeWireWinchController(ply, trace.HitPos, Ang, const, rope)
local min = controller:OBBMins()
controller:SetPos( trace.HitPos - trace.HitNormal * min.z )
controller:SetConstraint( const )
controller:SetRope( rope )
controller.const = const
controller.rope = rope
local const2, nocollide
// Don't weld to world
if ( trace.Entity:IsValid() ) then
local const2 = constraint.Weld( controller, trace.Entity, 0, trace.PhysicsBone, 0, true, true )
// Don't disable collision if it's not attached to anything
controller:GetPhysicsObject():EnableCollisions( false )
controller.nocollide = true
end
undo.Create("WireWinch")
undo.AddEntity( controller )
undo.AddEntity( const2 )
undo.SetPlayer( ply )
undo.Finish()
ply:AddCleanup( "ropeconstraints", controller )
ply:AddCleanup( "ropeconstraints", const2 )
controller:DeleteOnRemove( const )
if rope then controller:DeleteOnRemove( rope ) end
self:ClearObjects()
self:SetStage(0)
elseif ( iNum == 1 ) then
if ( CLIENT ) then
--self:ClearObjects()
return true
end
// Get client's CVars
local material = self:GetClientInfo( "material" ) or "cable/rope"
local width = self:GetClientNumber( "width" ) or 3
--local fwd_bind = self:GetClientNumber( "fwd_group" ) or 1
--local bwd_bind = self:GetClientNumber( "bwd_group" ) or 1
local fwd_speed = self:GetClientNumber( "fwd_speed" ) or 64
local bwd_speed = self:GetClientNumber( "bwd_speed" ) or 64
--local toggle = false
// Get information we're about to use
local Ent1, Ent2 = self:GetEnt(1), self:GetEnt(2)
local Bone1, Bone2 = self:GetBone(1), self:GetBone(2)
local LPos1, LPos2 = self:GetLocalPos(1),self:GetLocalPos(2)
local const,rope = MakeWireWinch( self:GetOwner(), Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, width, fwd_speed, bwd_speed, material )
self.constraint, self.rope = const,rope
undo.Create("WireWinch")
if constraint then undo.AddEntity( const ) end
if rope then undo.AddEntity( rope ) end
--if controller then undo.AddEntity( controller ) end
undo.SetPlayer( self:GetOwner() )
undo.Finish()
if const then self:GetOwner():AddCleanup( "ropeconstraints", const ) end
if rope then self:GetOwner():AddCleanup( "ropeconstraints", rope ) end
--if controller then self:GetOwner():AddCleanup( "ropeconstraints", controller ) end
// Clear the objects so we're ready to go again
--self:ClearObjects()
self:SetStage(2)
else
self:SetStage( iNum+1 )
end
return true
end
function TOOL:RightClick( trace )
// If there's no physics object then we can't constraint it!
if ( SERVER && !util.IsValidPhysicsObject( trace.Entity, trace.PhysicsBone ) ) then return false end
local iNum = self:NumObjects()
local Phys = trace.Entity:GetPhysicsObjectNum( trace.PhysicsBone )
self:SetObject( 1, trace.Entity, trace.HitPos, Phys, trace.PhysicsBone, trace.HitNormal )
local tr = {}
tr.start = trace.HitPos
tr.endpos = tr.start + (trace.HitNormal * 16384)
tr.filter = {}
tr.filter[1] = self:GetOwner()
if (trace.Entity:IsValid()) then
tr.filter[2] = trace.Entity
end
local tr = util.TraceLine( tr )
if ( !tr.Hit ) then
self:ClearObjects()
return
end
// Don't try to constrain world to world
if ( trace.HitWorld && tr.HitWorld ) then
self:ClearObjects()
return
end
if ( trace.Entity:IsValid() && trace.Entity:IsPlayer() ) then
self:ClearObjects()
return
end
if ( tr.Entity:IsValid() && tr.Entity:IsPlayer() ) then
self:ClearObjects()
return
end
local Phys2 = tr.Entity:GetPhysicsObjectNum( tr.PhysicsBone )
self:SetObject( 2, tr.Entity, tr.HitPos, Phys2, tr.PhysicsBone, trace.HitNormal )
if ( CLIENT ) then
--self:ClearObjects()
return true
end
// Get client's CVars
local material = self:GetClientInfo( "material" ) or "cable/rope"
local width = self:GetClientNumber( "width" ) or 3
--local fwd_bind = self:GetClientNumber( "fwd_group" ) or
--local bwd_bind = self:GetClientNumber( "bwd_group" ) or 1
local fwd_speed = self:GetClientNumber( "fwd_speed" ) or 64
local bwd_speed = self:GetClientNumber( "bwd_speed" ) or 64
// Get information we're about to use
local Ent1, Ent2 = self:GetEnt(1), self:GetEnt(2)
local Bone1, Bone2 = self:GetBone(1), self:GetBone(2)
local LPos1, LPos2 = self:GetLocalPos(1),self:GetLocalPos(2)
local const,rope,controller = MakeWireWinch( self:GetOwner(), Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, width, fwd_speed, bwd_speed, material )
self.constraint, self.rope = const,rope
undo.Create("WireWinch")
if const then undo.AddEntity( const ) end
if rope then undo.AddEntity( rope ) end
if controller then undo.AddEntity( controller ) end
undo.SetPlayer( self:GetOwner() )
undo.Finish()
if constraint then self:GetOwner():AddCleanup( "ropeconstraints", const ) end
if rope then self:GetOwner():AddCleanup( "ropeconstraints", rope ) end
if controller then self:GetOwner():AddCleanup( "ropeconstraints", controller ) end
// Clear the objects so we're ready to go again
--self:ClearObjects()
self:SetStage(2)
return true
end
if SERVER then
local function CalcElasticConsts(Phys1, Phys2, Ent1, Ent2)
local minMass = 0;
if ( Ent1:IsWorld() ) then minMass = Phys2:GetMass()
elseif ( Ent2:IsWorld() ) then minMass = Phys1:GetMass()
else
minMass = math.min( Phys1:GetMass(), Phys2:GetMass() )
end
// const, damp
local const = minMass * 100
local damp = const * 0.2
if ( iFixed == 0 ) then
const = minMass * 50
damp = const * 0.1
end
return const, damp
end
function MakeWireWinchController( pl, Pos, Ang )
//local controller = ents.Create("gmod_wire_hydraulic")
local controller = ents.Create("gmod_wire_winch_controller")
controller:SetPos( Pos )
controller:SetAngles( Ang )
controller:Setup()
controller:Spawn()
return controller
end
duplicator.RegisterEntityClass("gmod_wire_winch_controller", MakeWireWinchController, "Pos", "Ang")
function MakeWireWinch( pl, Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, width, fwd_speed, bwd_speed, material )
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)
local WPos1 = Phys1:LocalToWorld( LPos1 )
local WPos2 = Phys2:LocalToWorld( LPos2 )
if ( Phys1 == Phys2 ) then return false end
local constant, dampen = CalcElasticConsts( Phys1, Phys2, Ent1, Ent2 )
local const, rope = constraint.Elastic( Ent1, Ent2, Bone1, Bone2, LPos1, LPos2, constant, dampen, 0, material, width, true )
if ( !const ) then return nil, rope end
local ctable =
{
Type = "WireWinch",
pl = pl,
Ent1 = Ent1,
Ent2 = Ent2,
Bone1 = Bone1,
Bone2 = Bone2,
LPos1 = LPos1,
LPos2 = LPos2,
width = width,
fwd_speed = fwd_speed,
bwd_speed = bwd_speed,
material = material
}
const:SetTable( ctable )
return const, rope
end
duplicator.RegisterConstraint( "WireWinch", MakeWireWinch, "pl", "Ent1", "Ent2", "Bone1", "Bone2", "LPos1", "LPos2", "width", "fwd_speed", "bwd_speed", "material" )
end
function TOOL:Reload( trace )
if (!trace.Entity:IsValid() || trace.Entity:IsPlayer() ) then return false end
if ( CLIENT ) then return true end
local bool = constraint.RemoveConstraints( trace.Entity, "Winch" )
return bool
end
function TOOL.BuildCPanel(panel)
panel:AddControl("CheckBox", {
Label = "#WireWinchTool_fixed",
Command = "wire_winch_fixed"
})
panel:AddControl("Slider", {
Label = "#WireWinchTool_width",
Type = "Float",
Min = "1",
Max = "20",
Command = "wire_winch_width"
})
panel:AddControl("MaterialGallery", {
Label = "#WireWinchTool_material",
Height = "64",
Width = "28",
Rows = "1",
Stretch = "1",
Options = {
["Wire"] = { Material = "cable/rope_icon", wire_winch_material = "cable/rope" },
["Cable 2"] = { Material = "cable/cable_icon", wire_winch_material = "cable/cable2" },
["XBeam"] = { Material = "cable/xbeam", wire_winch_material = "cable/xbeam" },
["Red Laser"] = { Material = "cable/redlaser", wire_winch_material = "cable/redlaser" },
["Blue Electric"] = { Material = "cable/blue_elec", wire_winch_material = "cable/blue_elec" },
["Physics Beam"] = { Material = "cable/physbeam", wire_winch_material = "cable/physbeam" },
["Hydra"] = { Material = "cable/hydra", wire_winch_material = "cable/hydra" },
},
CVars = {
[0] = "wire_winch_material"
}
})
end