mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
Upload
This commit is contained in:
@@ -0,0 +1,854 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
TOOL.Category = "simfphys"
|
||||
TOOL.Name = "#Vehicle Duplicator"
|
||||
TOOL.Command = nil
|
||||
TOOL.ConfigName = ""
|
||||
|
||||
if SERVER then
|
||||
util.AddNetworkString( "sphys_dupe" )
|
||||
|
||||
local recv_interval_start = 0 -- first second of current interval
|
||||
local recv_interval_len = 1 -- in seconds, length of interval before resetting recv_interval_(start,count)
|
||||
local recv_interval_count = 0 -- current count of messages received in interval
|
||||
local recv_max = 500 -- maximum number of messages to receive during one interval
|
||||
local recv_stop = 0 -- is the net.Receive stopped (activates short-circuit)
|
||||
local recv_delay_after_stop = 3600 -- how long to wait (in seconds) before allowing messages again
|
||||
|
||||
net.Receive("sphys_dupe", function( length, ply )
|
||||
if (recv_stop == 1) then -- if stopped,
|
||||
return -- short-circuit
|
||||
end
|
||||
-- check if a new interval has come
|
||||
if (recv_interval_start + recv_interval_len < os.time()) then
|
||||
recv_interval_start = os.time() -- reset time
|
||||
recv_interval_count = 0 -- reset message count
|
||||
end
|
||||
recv_interval_count = recv_interval_count + 1
|
||||
-- check if below threshold
|
||||
if (recv_interval_count > recv_max) then
|
||||
-- if over threshold, activate short-circuit
|
||||
recv_stop = 1
|
||||
-- and create a timer to deactivate the short-circuit in recv_delay_after_stop seconds
|
||||
timer.Simple(recv_delay_after_stop, function()
|
||||
recv_stop = 0
|
||||
end)
|
||||
-- warn server about attack
|
||||
PrintMessage(HUD_PRINTTALK, "WARNING: " .. ply:Nick() .. " [" .. ply:SteamID() .. "] is attacking sphys_dupe. simfphys duplicator is disabled for " .. tostring(recv_delay_after_stop) .. " seconds.")
|
||||
end
|
||||
|
||||
ply.TOOLMemory = net.ReadTable()
|
||||
ply:SelectWeapon( "gmod_tool" )
|
||||
end)
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
language.Add( "tool.simfphysduplicator.name", "Vehicle Duplicator" )
|
||||
language.Add( "tool.simfphysduplicator.desc", "Copy, Paste or Save your Vehicles" )
|
||||
language.Add( "tool.simfphysduplicator.0", "Left click to spawn or update. Right click to copy" )
|
||||
language.Add( "tool.simfphysduplicator.1", "Left click to spawn or update. Right click to copy" )
|
||||
|
||||
local selecteditem = nil
|
||||
local TOOLMemory = {}
|
||||
|
||||
net.Receive("sphys_dupe", function( length )
|
||||
TOOLMemory = net.ReadTable()
|
||||
end)
|
||||
|
||||
local function GetSaves( panel )
|
||||
local saved_vehicles = file.Find("saved_vehicles/*.txt", "DATA")
|
||||
local index = 0
|
||||
local highlight = false
|
||||
local offset = 22
|
||||
|
||||
for k,v in pairs(saved_vehicles) do
|
||||
local printname = v
|
||||
|
||||
if not selecteditem then
|
||||
selecteditem = printname
|
||||
end
|
||||
|
||||
local Button = vgui.Create( "DButton", panel )
|
||||
Button:SetText( printname )
|
||||
Button:SetTextColor( Color( 255, 255, 255 ) )
|
||||
Button:SetPos( 0,index * offset)
|
||||
Button:SetSize( 280, offset )
|
||||
Button.highlight = highlight
|
||||
Button.printname = printname
|
||||
Button.Paint = function( self, w, h )
|
||||
|
||||
local c_selected = Color( 128, 185, 128, 255 )
|
||||
local c_normal = self.highlight and Color( 108, 111, 114, 200 ) or Color( 77, 80, 82, 200 )
|
||||
local c_hovered = Color( 41, 128, 185, 255 )
|
||||
local c_ = (selecteditem == self.printname) and c_selected or (self:IsHovered() and c_hovered or c_normal)
|
||||
|
||||
draw.RoundedBox( 5, 1, 1, w - 2, h - 1, c_ )
|
||||
end
|
||||
Button.DoClick = function( self )
|
||||
selecteditem = self.printname
|
||||
end
|
||||
|
||||
index = index + 1
|
||||
highlight = not highlight
|
||||
end
|
||||
end
|
||||
|
||||
function TOOL.BuildCPanel( panel )
|
||||
if not file.Exists( "saved_vehicles", "DATA" ) then
|
||||
file.CreateDir( "saved_vehicles" )
|
||||
end
|
||||
|
||||
local Frame = vgui.Create( "DFrame", panel )
|
||||
Frame:SetPos( 10, 30 )
|
||||
Frame:SetSize( 280, 320 )
|
||||
Frame:SetTitle( "" )
|
||||
Frame:SetVisible( true )
|
||||
Frame:ShowCloseButton( false )
|
||||
Frame:SetDraggable( false )
|
||||
Frame.Paint = function( self, w, h )
|
||||
draw.RoundedBox( 5, 0, 0, w, h, Color( 115, 115, 115, 255 ) )
|
||||
draw.RoundedBox( 5, 1, 1, w - 2, h - 2, Color( 234, 234, 234, 255 ) )
|
||||
end
|
||||
|
||||
local ScrollPanel = vgui.Create( "DScrollPanel", Frame )
|
||||
ScrollPanel:SetSize( 280, 320 )
|
||||
ScrollPanel:SetPos( 0, 0 )
|
||||
|
||||
GetSaves( ScrollPanel )
|
||||
|
||||
local Button = vgui.Create( "DButton", panel )
|
||||
Button:SetText( "Save" )
|
||||
Button:SetPos( 10, 350)
|
||||
Button:SetSize( 280, 20 )
|
||||
Button.DoClick = function( self )
|
||||
if isstring(TOOLMemory.SpawnName) then
|
||||
local Frame = vgui.Create( "DFrame" )
|
||||
Frame:SetPos( gui.MouseX() - 100, gui.MouseY() - 30 )
|
||||
Frame:SetSize( 280, 50 )
|
||||
Frame:SetTitle( "Save As..." )
|
||||
Frame:SetVisible( true )
|
||||
Frame:ShowCloseButton( true )
|
||||
Frame:MakePopup()
|
||||
Frame:SetDraggable( true )
|
||||
|
||||
local TextEntry = vgui.Create( "DTextEntry", Frame )
|
||||
TextEntry:SetPos( 5, 25 )
|
||||
TextEntry:SetSize( 270, 20 )
|
||||
|
||||
TextEntry.OnEnter = function()
|
||||
local Name = TextEntry:GetValue()
|
||||
|
||||
if Name ~= "" then
|
||||
local DataString = ""
|
||||
|
||||
for k,v in pairs(TOOLMemory) do
|
||||
if k == "SubMaterials" then
|
||||
local mats = ""
|
||||
local first = true
|
||||
for k, v in pairs( v ) do
|
||||
if first then
|
||||
first = false
|
||||
mats = mats..v
|
||||
else
|
||||
mats = mats..","..v
|
||||
end
|
||||
end
|
||||
DataString = DataString..k.."="..mats.."#"
|
||||
else
|
||||
DataString = DataString..k.."="..tostring( v ).."#"
|
||||
end
|
||||
end
|
||||
|
||||
local words = string.Explode( "", DataString )
|
||||
local shit = {}
|
||||
|
||||
for k, v in pairs( words ) do
|
||||
shit[k] = string.char( string.byte( v ) + 20 )
|
||||
end
|
||||
|
||||
file.Write("saved_vehicles/"..Name..".txt", string.Implode("",shit) )
|
||||
|
||||
ScrollPanel:Clear()
|
||||
selecteditem = Name..".txt"
|
||||
GetSaves( ScrollPanel )
|
||||
end
|
||||
|
||||
Frame:Close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local Button = vgui.Create( "DButton", panel )
|
||||
Button:SetText( "Load" )
|
||||
Button:SetPos( 10, 370)
|
||||
Button:SetSize( 280, 20 )
|
||||
Button.DoClick = function( self )
|
||||
if isstring(selecteditem) then
|
||||
if not file.Exists( "saved_vehicles/"..selecteditem, "DATA" ) then
|
||||
ScrollPanel:Clear()
|
||||
selecteditem = nil
|
||||
GetSaves( ScrollPanel )
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local DataString = file.Read( "saved_vehicles/"..selecteditem, "DATA" )
|
||||
|
||||
local words = string.Explode( "", DataString )
|
||||
local shit = {}
|
||||
|
||||
for k, v in pairs( words ) do
|
||||
shit[k] = string.char( string.byte( v ) - 20 )
|
||||
end
|
||||
|
||||
local Data = string.Explode( "#", string.Implode("",shit) )
|
||||
|
||||
table.Empty( TOOLMemory )
|
||||
|
||||
for _,v in pairs(Data) do
|
||||
local Var = string.Explode( "=", v )
|
||||
local name = Var[1]
|
||||
local variable = Var[2]
|
||||
|
||||
if name and variable then
|
||||
if name == "SubMaterials" then
|
||||
TOOLMemory[name] = {}
|
||||
|
||||
local submats = string.Explode( ",", variable )
|
||||
for i = 0, (table.Count( submats ) - 1) do
|
||||
TOOLMemory[name][i] = submats[i+1]
|
||||
end
|
||||
else
|
||||
TOOLMemory[name] = variable
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
net.Start("sphys_dupe")
|
||||
net.WriteTable( TOOLMemory )
|
||||
net.SendToServer()
|
||||
end
|
||||
end
|
||||
|
||||
local Button = vgui.Create( "DButton", panel )
|
||||
Button:SetText( "Delete" )
|
||||
Button:SetPos( 10, 430)
|
||||
Button:SetSize( 280, 20 )
|
||||
Button.DoClick = function( self )
|
||||
|
||||
if isstring(selecteditem) then
|
||||
file.Delete( "saved_vehicles/"..selecteditem )
|
||||
end
|
||||
|
||||
ScrollPanel:Clear()
|
||||
selecteditem = nil
|
||||
GetSaves( ScrollPanel )
|
||||
end
|
||||
|
||||
local Button = vgui.Create( "DButton", panel )
|
||||
Button:SetText( "Refresh" )
|
||||
Button:SetPos( 10, 390)
|
||||
Button:SetSize( 280, 20 )
|
||||
Button.DoClick = function( self )
|
||||
ScrollPanel:Clear()
|
||||
selecteditem = nil
|
||||
GetSaves( ScrollPanel )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function ValidateModel( model )
|
||||
local v_list = list.Get( "simfphys_vehicles" )
|
||||
for listname, _ in pairs( v_list ) do
|
||||
if v_list[listname].Members.CustomWheels then
|
||||
local FrontWheel = v_list[listname].Members.CustomWheelModel
|
||||
local RearWheel = v_list[listname].Members.CustomWheelModel_R
|
||||
|
||||
if FrontWheel then
|
||||
FrontWheel = string.lower( FrontWheel )
|
||||
end
|
||||
|
||||
if RearWheel then
|
||||
RearWheel = string.lower( RearWheel )
|
||||
end
|
||||
|
||||
if model == FrontWheel or model == RearWheel then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local list = list.Get( "simfphys_Wheels" )[model]
|
||||
|
||||
if list then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function TOOL:GetVehicleData( ent, ply )
|
||||
if not IsValid(ent) then return end
|
||||
if not istable(ply.TOOLMemory) then ply.TOOLMemory = {} end
|
||||
|
||||
table.Empty( ply.TOOLMemory )
|
||||
|
||||
ply.TOOLMemory.SpawnName = ent:GetSpawn_List()
|
||||
ply.TOOLMemory.SteerSpeed = ent:GetSteerSpeed()
|
||||
ply.TOOLMemory.SteerFadeSpeed = ent:GetFastSteerConeFadeSpeed()
|
||||
ply.TOOLMemory.SteerAngFast = ent:GetFastSteerAngle()
|
||||
ply.TOOLMemory.SoundPreset = ent:GetEngineSoundPreset()
|
||||
ply.TOOLMemory.IdleRPM = ent:GetIdleRPM()
|
||||
ply.TOOLMemory.MaxRPM = ent:GetLimitRPM()
|
||||
ply.TOOLMemory.PowerStart = ent:GetPowerBandStart()
|
||||
ply.TOOLMemory.PowerEnd = ent:GetPowerBandEnd()
|
||||
ply.TOOLMemory.PeakTorque = ent:GetMaxTorque()
|
||||
ply.TOOLMemory.HasTurbo = ent:GetTurboCharged()
|
||||
ply.TOOLMemory.HasBlower = ent:GetSuperCharged()
|
||||
ply.TOOLMemory.HasRevLimiter = ent:GetRevlimiter()
|
||||
ply.TOOLMemory.HasBulletProofTires = ent:GetBulletProofTires()
|
||||
ply.TOOLMemory.MaxTraction = ent:GetMaxTraction()
|
||||
ply.TOOLMemory.GripOffset = ent:GetTractionBias()
|
||||
ply.TOOLMemory.BrakePower = ent:GetBrakePower()
|
||||
ply.TOOLMemory.PowerDistribution = ent:GetPowerDistribution()
|
||||
ply.TOOLMemory.Efficiency = ent:GetEfficiency()
|
||||
ply.TOOLMemory.HornSound = ent.snd_horn
|
||||
ply.TOOLMemory.HasBackfire = ent:GetBackFire()
|
||||
ply.TOOLMemory.DoesntStall = ent:GetDoNotStall()
|
||||
ply.TOOLMemory.SoundOverride = ent:GetSoundoverride()
|
||||
|
||||
ply.TOOLMemory.FrontHeight = ent:GetFrontSuspensionHeight()
|
||||
ply.TOOLMemory.RearHeight = ent:GetRearSuspensionHeight()
|
||||
|
||||
ply.TOOLMemory.Camber = ent.Camber or 0
|
||||
|
||||
if ent.FrontDampingOverride and ent.FrontConstantOverride and ent.RearDampingOverride and ent.RearConstantOverride then
|
||||
ply.TOOLMemory.FrontDampingOverride = ent.FrontDampingOverride
|
||||
ply.TOOLMemory.FrontConstantOverride = ent.FrontConstantOverride
|
||||
ply.TOOLMemory.RearDampingOverride = ent.RearDampingOverride
|
||||
ply.TOOLMemory.RearConstantOverride = ent.RearConstantOverride
|
||||
end
|
||||
|
||||
if ent.CustomWheels then
|
||||
if ent.GhostWheels then
|
||||
if IsValid(ent.GhostWheels[1]) then
|
||||
ply.TOOLMemory.FrontWheelOverride = ent.GhostWheels[1]:GetModel()
|
||||
elseif IsValid(ent.GhostWheels[2]) then
|
||||
ply.TOOLMemory.FrontWheelOverride = ent.GhostWheels[2]:GetModel()
|
||||
end
|
||||
|
||||
if IsValid(ent.GhostWheels[3]) then
|
||||
ply.TOOLMemory.RearWheelOverride = ent.GhostWheels[3]:GetModel()
|
||||
elseif IsValid(ent.GhostWheels[4]) then
|
||||
ply.TOOLMemory.RearWheelOverride = ent.GhostWheels[4]:GetModel()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tsc = ent:GetTireSmokeColor()
|
||||
ply.TOOLMemory.TireSmokeColor = tsc.r..","..tsc.g..","..tsc.b
|
||||
|
||||
local Gears = ""
|
||||
for _,v in pairs(ent.Gears) do
|
||||
Gears = Gears..v..","
|
||||
end
|
||||
|
||||
local c = ent:GetColor()
|
||||
ply.TOOLMemory.Color = c.r..","..c.g..","..c.b..","..c.a
|
||||
|
||||
local bodygroups = {}
|
||||
for k,v in pairs(ent:GetBodyGroups()) do
|
||||
bodygroups[k] = ent:GetBodygroup( k )
|
||||
end
|
||||
|
||||
ply.TOOLMemory.BodyGroups = string.Implode( ",", bodygroups)
|
||||
|
||||
ply.TOOLMemory.Skin = ent:GetSkin()
|
||||
|
||||
ply.TOOLMemory.Gears = Gears
|
||||
ply.TOOLMemory.FinalGear = ent:GetDifferentialGear()
|
||||
|
||||
if ent.WheelTool_Foffset then
|
||||
ply.TOOLMemory.WheelTool_Foffset = ent.WheelTool_Foffset
|
||||
end
|
||||
|
||||
if ent.WheelTool_Roffset then
|
||||
ply.TOOLMemory.WheelTool_Roffset = ent.WheelTool_Roffset
|
||||
end
|
||||
|
||||
if ent.snd_blowoff then
|
||||
ply.TOOLMemory.snd_blowoff = ent.snd_blowoff
|
||||
end
|
||||
|
||||
if ent.snd_spool then
|
||||
ply.TOOLMemory.snd_spool = ent.snd_spool
|
||||
end
|
||||
|
||||
if ent.snd_bloweron then
|
||||
ply.TOOLMemory.snd_bloweron = ent.snd_bloweron
|
||||
end
|
||||
|
||||
if ent.snd_bloweroff then
|
||||
ply.TOOLMemory.snd_bloweroff = ent.snd_bloweroff
|
||||
end
|
||||
|
||||
ply.TOOLMemory.backfiresound = ent:GetBackfireSound()
|
||||
|
||||
ply.TOOLMemory.SubMaterials = {}
|
||||
for i = 0, (table.Count( ent:GetMaterials() ) - 1) do
|
||||
ply.TOOLMemory.SubMaterials[i] = ent:GetSubMaterial( i )
|
||||
end
|
||||
|
||||
if not IsValid( ply ) then return end
|
||||
|
||||
net.Start("sphys_dupe")
|
||||
net.WriteTable( ply.TOOLMemory )
|
||||
net.Send( ply )
|
||||
end
|
||||
|
||||
local function GetRight( ent, index, WheelPos )
|
||||
local Steer = ent:GetTransformedDirection()
|
||||
|
||||
local Right = ent.Right
|
||||
|
||||
if WheelPos.IsFrontWheel then
|
||||
Right = (IsValid( ent.SteerMaster ) and Steer.Right or ent.Right) * (WheelPos.IsRightWheel and 1 or -1)
|
||||
else
|
||||
Right = (IsValid( ent.SteerMaster ) and Steer.Right2 or ent.Right) * (WheelPos.IsRightWheel and 1 or -1)
|
||||
end
|
||||
|
||||
return Right
|
||||
end
|
||||
|
||||
local function SetWheelOffset( ent, offset_front, offset_rear )
|
||||
if not IsValid( ent ) then return end
|
||||
|
||||
ent.WheelTool_Foffset = offset_front
|
||||
ent.WheelTool_Roffset = offset_rear
|
||||
|
||||
if not istable( ent.Wheels ) or not istable( ent.GhostWheels ) then return end
|
||||
|
||||
for i = 1, table.Count( ent.GhostWheels ) do
|
||||
local Wheel = ent.Wheels[ i ]
|
||||
local WheelModel = ent.GhostWheels[i]
|
||||
local WheelPos = ent:LogicWheelPos( i )
|
||||
|
||||
if IsValid( Wheel ) and IsValid( WheelModel ) then
|
||||
local Pos = Wheel:GetPos()
|
||||
local Right = GetRight( ent, i, WheelPos )
|
||||
local offset = WheelPos.IsFrontWheel and offset_front or offset_rear
|
||||
|
||||
WheelModel:SetParent( nil )
|
||||
|
||||
local physObj = WheelModel:GetPhysicsObject()
|
||||
if IsValid( physObj ) then
|
||||
physObj:EnableMotion( false )
|
||||
end
|
||||
|
||||
WheelModel:SetPos( Pos + Right * offset )
|
||||
WheelModel:SetParent( Wheel )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function ApplyWheel(ent, data)
|
||||
ent.CustomWheelAngleOffset = data[2]
|
||||
ent.CustomWheelAngleOffset_R = data[4]
|
||||
|
||||
timer.Simple( 0.05, function()
|
||||
if not IsValid( ent ) then return end
|
||||
for i = 1, table.Count( ent.GhostWheels ) do
|
||||
local Wheel = ent.GhostWheels[i]
|
||||
|
||||
if IsValid( Wheel ) then
|
||||
local isfrontwheel = (i == 1 or i == 2)
|
||||
local swap_y = (i == 2 or i == 4 or i == 6)
|
||||
|
||||
local angleoffset = isfrontwheel and ent.CustomWheelAngleOffset or ent.CustomWheelAngleOffset_R
|
||||
|
||||
local model = isfrontwheel and data[1] or data[3]
|
||||
|
||||
local fAng = ent:LocalToWorldAngles( ent.VehicleData.LocalAngForward )
|
||||
local rAng = ent:LocalToWorldAngles( ent.VehicleData.LocalAngRight )
|
||||
|
||||
local Forward = fAng:Forward()
|
||||
local Right = swap_y and -rAng:Forward() or rAng:Forward()
|
||||
local Up = ent:GetUp()
|
||||
|
||||
local Camber = data[5] or 0
|
||||
|
||||
local ghostAng = Right:Angle()
|
||||
local mirAng = swap_y and 1 or -1
|
||||
ghostAng:RotateAroundAxis(Forward,angleoffset.p * mirAng)
|
||||
ghostAng:RotateAroundAxis(Right,angleoffset.r * mirAng)
|
||||
ghostAng:RotateAroundAxis(Up,-angleoffset.y)
|
||||
|
||||
ghostAng:RotateAroundAxis(Forward, Camber * mirAng)
|
||||
|
||||
Wheel:SetModelScale( 1 )
|
||||
Wheel:SetModel( model )
|
||||
Wheel:SetAngles( ghostAng )
|
||||
|
||||
timer.Simple( 0.05, function()
|
||||
if not IsValid(Wheel) or not IsValid( ent ) then return end
|
||||
local wheelsize = Wheel:OBBMaxs() - Wheel:OBBMins()
|
||||
local radius = isfrontwheel and ent.FrontWheelRadius or ent.RearWheelRadius
|
||||
local size = (radius * 2) / math.max(wheelsize.x,wheelsize.y,wheelsize.z)
|
||||
|
||||
Wheel:SetModelScale( size )
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function GetAngleFromSpawnlist( model )
|
||||
if not model then print("invalid model") return Angle(0,0,0) end
|
||||
|
||||
model = string.lower( model )
|
||||
|
||||
local v_list = list.Get( "simfphys_vehicles" )
|
||||
for listname, _ in pairs( v_list ) do
|
||||
if v_list[listname].Members.CustomWheels then
|
||||
local FrontWheel = v_list[listname].Members.CustomWheelModel
|
||||
local RearWheel = v_list[listname].Members.CustomWheelModel_R
|
||||
|
||||
if FrontWheel then
|
||||
FrontWheel = string.lower( FrontWheel )
|
||||
end
|
||||
|
||||
if RearWheel then
|
||||
RearWheel = string.lower( RearWheel )
|
||||
end
|
||||
|
||||
if model == FrontWheel or model == RearWheel then
|
||||
local Angleoffset = v_list[listname].Members.CustomWheelAngleOffset
|
||||
if (Angleoffset) then
|
||||
return Angleoffset
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local list = list.Get( "simfphys_Wheels" )[model]
|
||||
local output = list and list.Angle or Angle(0,0,0)
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
function TOOL:LeftClick( trace )
|
||||
if CLIENT then return true end
|
||||
|
||||
local Ent = trace.Entity
|
||||
|
||||
local ply = self:GetOwner()
|
||||
|
||||
if not istable(ply.TOOLMemory) then return end
|
||||
|
||||
local vname = ply.TOOLMemory.SpawnName
|
||||
local Update = false
|
||||
local VehicleList = list.Get( "simfphys_vehicles" )
|
||||
local vehicle = VehicleList[ vname ]
|
||||
|
||||
if not vehicle then return false end
|
||||
|
||||
ply.LockRightClick = true
|
||||
timer.Simple( 0.6, function() if IsValid( ply ) then ply.LockRightClick = false end end )
|
||||
|
||||
local SpawnPos = trace.HitPos + Vector(0,0,25) + (vehicle.SpawnOffset or Vector(0,0,0))
|
||||
|
||||
local SpawnAng = self:GetOwner():EyeAngles()
|
||||
SpawnAng.pitch = 0
|
||||
SpawnAng.yaw = SpawnAng.yaw + 180 + (vehicle.SpawnAngleOffset and vehicle.SpawnAngleOffset or 0)
|
||||
SpawnAng.roll = 0
|
||||
|
||||
if simfphys.IsCar( Ent ) then
|
||||
if vname ~= Ent:GetSpawn_List() then
|
||||
ply:PrintMessage( HUD_PRINTTALK, vname.." is not compatible with "..Ent:GetSpawn_List() )
|
||||
return
|
||||
end
|
||||
Update = true
|
||||
else
|
||||
Ent = simfphys.SpawnVehicle( ply, SpawnPos, SpawnAng, vehicle.Model, vehicle.Class, vname, vehicle )
|
||||
end
|
||||
|
||||
if not IsValid( Ent ) then return end
|
||||
|
||||
undo.Create( "Vehicle" )
|
||||
undo.SetPlayer( ply )
|
||||
undo.AddEntity( Ent )
|
||||
undo.SetCustomUndoText( "Undone " .. vehicle.Name )
|
||||
undo.Finish( "Vehicle (" .. tostring( vehicle.Name ) .. ")" )
|
||||
|
||||
ply:AddCleanup( "vehicles", Ent )
|
||||
|
||||
timer.Simple( 0.5, function()
|
||||
if not IsValid(Ent) then return end
|
||||
|
||||
local tsc = string.Explode( ",", ply.TOOLMemory.TireSmokeColor )
|
||||
Ent:SetTireSmokeColor( Vector( tonumber(tsc[1]), tonumber(tsc[2]), tonumber(tsc[3]) ) )
|
||||
|
||||
Ent.Turbocharged = tobool( ply.TOOLMemory.HasTurbo )
|
||||
Ent.Supercharged = tobool( ply.TOOLMemory.HasBlower )
|
||||
|
||||
Ent:SetEngineSoundPreset( math.Clamp( tonumber( ply.TOOLMemory.SoundPreset ), -1, 23) )
|
||||
Ent:SetMaxTorque( math.Clamp( tonumber( ply.TOOLMemory.PeakTorque ), 20, 1000) )
|
||||
Ent:SetDifferentialGear( math.Clamp( tonumber( ply.TOOLMemory.FinalGear ),0.2, 6 ) )
|
||||
|
||||
Ent:SetSteerSpeed( math.Clamp( tonumber( ply.TOOLMemory.SteerSpeed ), 1, 16 ) )
|
||||
Ent:SetFastSteerAngle( math.Clamp( tonumber( ply.TOOLMemory.SteerAngFast ), 0, 1) )
|
||||
Ent:SetFastSteerConeFadeSpeed( math.Clamp( tonumber( ply.TOOLMemory.SteerFadeSpeed ), 1, 5000 ) )
|
||||
|
||||
Ent:SetEfficiency( math.Clamp( tonumber( ply.TOOLMemory.Efficiency ) ,0.2,4) )
|
||||
Ent:SetMaxTraction( math.Clamp( tonumber( ply.TOOLMemory.MaxTraction ) , 5,1000) )
|
||||
Ent:SetTractionBias( math.Clamp( tonumber( ply.TOOLMemory.GripOffset ),-0.99,0.99) )
|
||||
Ent:SetPowerDistribution( math.Clamp( tonumber( ply.TOOLMemory.PowerDistribution ) ,-1,1) )
|
||||
|
||||
Ent:SetBackFire( tobool( ply.TOOLMemory.HasBackfire ) )
|
||||
Ent:SetDoNotStall( tobool( ply.TOOLMemory.DoesntStall ) )
|
||||
|
||||
Ent:SetIdleRPM( math.Clamp( tonumber( ply.TOOLMemory.IdleRPM ),1,25000) )
|
||||
Ent:SetLimitRPM( math.Clamp( tonumber( ply.TOOLMemory.MaxRPM ),4,25000) )
|
||||
Ent:SetRevlimiter( tobool( ply.TOOLMemory.HasRevLimiter ) )
|
||||
Ent:SetPowerBandEnd( math.Clamp( tonumber( ply.TOOLMemory.PowerEnd ), 3, 25000) )
|
||||
Ent:SetPowerBandStart( math.Clamp( tonumber( ply.TOOLMemory.PowerStart ) ,2 ,25000) )
|
||||
|
||||
Ent:SetTurboCharged( Ent.Turbocharged )
|
||||
Ent:SetSuperCharged( Ent.Supercharged )
|
||||
Ent:SetBrakePower( math.Clamp( tonumber( ply.TOOLMemory.BrakePower ), 0.1, 500) )
|
||||
|
||||
Ent:SetSoundoverride( ply.TOOLMemory.SoundOverride or "" )
|
||||
|
||||
Ent:SetLights_List( Ent.LightsTable or "no_lights" )
|
||||
|
||||
Ent:SetBulletProofTires( tobool( ply.TOOLMemory.HasBulletProofTires ) )
|
||||
|
||||
Ent.snd_horn = ply.TOOLMemory.HornSound
|
||||
|
||||
Ent.snd_blowoff = ply.TOOLMemory.snd_blowoff
|
||||
Ent.snd_spool = ply.TOOLMemory.snd_spool
|
||||
Ent.snd_bloweron = ply.TOOLMemory.snd_bloweron
|
||||
Ent.snd_bloweroff = ply.TOOLMemory.snd_bloweroff
|
||||
|
||||
Ent:SetBackfireSound( ply.TOOLMemory.backfiresound or "" )
|
||||
|
||||
local Gears = {}
|
||||
local Data = string.Explode( ",", ply.TOOLMemory.Gears )
|
||||
for i = 1, table.Count( Data ) do
|
||||
local gRatio = tonumber( Data[i] )
|
||||
|
||||
if isnumber( gRatio ) then
|
||||
if i == 1 then
|
||||
Gears[i] = math.Clamp( gRatio, -5, -0.001)
|
||||
|
||||
elseif i == 2 then
|
||||
Gears[i] = 0
|
||||
|
||||
else
|
||||
Gears[i] = math.Clamp( gRatio, 0.001, 5)
|
||||
end
|
||||
end
|
||||
end
|
||||
Ent.Gears = Gears
|
||||
|
||||
if istable( ply.TOOLMemory.SubMaterials ) then
|
||||
for i = 0, table.Count( ply.TOOLMemory.SubMaterials ) do
|
||||
Ent:SetSubMaterial( i, ply.TOOLMemory.SubMaterials[i] )
|
||||
end
|
||||
end
|
||||
|
||||
if ply.TOOLMemory.FrontDampingOverride and ply.TOOLMemory.FrontConstantOverride and ply.TOOLMemory.RearDampingOverride and ply.TOOLMemory.RearConstantOverride then
|
||||
Ent.FrontDampingOverride = tonumber( ply.TOOLMemory.FrontDampingOverride )
|
||||
Ent.FrontConstantOverride = tonumber( ply.TOOLMemory.FrontConstantOverride )
|
||||
Ent.RearDampingOverride = tonumber( ply.TOOLMemory.RearDampingOverride )
|
||||
Ent.RearConstantOverride = tonumber( ply.TOOLMemory.RearConstantOverride )
|
||||
|
||||
local data = {
|
||||
[1] = {Ent.FrontConstantOverride,Ent.FrontDampingOverride},
|
||||
[2] = {Ent.FrontConstantOverride,Ent.FrontDampingOverride},
|
||||
[3] = {Ent.RearConstantOverride,Ent.RearDampingOverride},
|
||||
[4] = {Ent.RearConstantOverride,Ent.RearDampingOverride},
|
||||
[5] = {Ent.RearConstantOverride,Ent.RearDampingOverride},
|
||||
[6] = {Ent.RearConstantOverride,Ent.RearDampingOverride}
|
||||
}
|
||||
|
||||
local elastics = Ent.Elastics
|
||||
if elastics then
|
||||
for i = 1, table.Count( elastics ) do
|
||||
local elastic = elastics[i]
|
||||
if Ent.StrengthenSuspension == true then
|
||||
if IsValid( elastic ) then
|
||||
elastic:Fire( "SetSpringConstant", data[i][1] * 0.5, 0 )
|
||||
elastic:Fire( "SetSpringDamping", data[i][2] * 0.5, 0 )
|
||||
end
|
||||
local elastic2 = elastics[i * 10]
|
||||
if IsValid( elastic2 ) then
|
||||
elastic2:Fire( "SetSpringConstant", data[i][1] * 0.5, 0 )
|
||||
elastic2:Fire( "SetSpringDamping", data[i][2] * 0.5, 0 )
|
||||
end
|
||||
else
|
||||
if IsValid( elastic ) then
|
||||
elastic:Fire( "SetSpringConstant", data[i][1], 0 )
|
||||
elastic:Fire( "SetSpringDamping", data[i][2], 0 )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Ent:SetFrontSuspensionHeight( tonumber( ply.TOOLMemory.FrontHeight ) )
|
||||
Ent:SetRearSuspensionHeight( tonumber( ply.TOOLMemory.RearHeight ) )
|
||||
|
||||
local groups = string.Explode( ",", ply.TOOLMemory.BodyGroups)
|
||||
for i = 1, table.Count( groups ) do
|
||||
Ent:SetBodygroup(i, tonumber(groups[i]) )
|
||||
end
|
||||
|
||||
Ent:SetSkin( ply.TOOLMemory.Skin )
|
||||
|
||||
local c = string.Explode( ",", ply.TOOLMemory.Color )
|
||||
local Color = Color( tonumber(c[1]), tonumber(c[2]), tonumber(c[3]), tonumber(c[4]) )
|
||||
|
||||
local dot = Color.r * Color.g * Color.b * Color.a
|
||||
Ent.OldColor = dot
|
||||
Ent:SetColor( Color )
|
||||
|
||||
local data = {
|
||||
Color = Color,
|
||||
RenderMode = 0,
|
||||
RenderFX = 0
|
||||
}
|
||||
duplicator.StoreEntityModifier( Ent, "colour", data )
|
||||
|
||||
if Update then
|
||||
local PhysObj = Ent:GetPhysicsObject()
|
||||
if not IsValid( PhysObj ) then return end
|
||||
|
||||
local freezeWhenDone = PhysObj:IsMotionEnabled()
|
||||
local freezeWheels = {}
|
||||
PhysObj:EnableMotion( false )
|
||||
Ent:SetNotSolid( true )
|
||||
|
||||
local ResetPos = Ent:GetPos()
|
||||
local ResetAng = Ent:GetAngles()
|
||||
|
||||
Ent:SetPos( ResetPos + Vector(0,0,30) )
|
||||
Ent:SetAngles( Angle(0,ResetAng.y,0) )
|
||||
|
||||
for i = 1, table.Count( Ent.Wheels ) do
|
||||
local Wheel = Ent.Wheels[ i ]
|
||||
if IsValid( Wheel ) then
|
||||
local wPObj = Wheel:GetPhysicsObject()
|
||||
|
||||
if IsValid( wPObj ) then
|
||||
freezeWheels[ i ] = {}
|
||||
freezeWheels[ i ].dofreeze = wPObj:IsMotionEnabled()
|
||||
freezeWheels[ i ].pos = Wheel:GetPos()
|
||||
freezeWheels[ i ].ang = Wheel:GetAngles()
|
||||
Wheel:SetNotSolid( true )
|
||||
wPObj:EnableMotion( true )
|
||||
wPObj:Wake()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
timer.Simple( 0.5, function()
|
||||
if not IsValid( Ent ) then return end
|
||||
if not IsValid( PhysObj ) then return end
|
||||
|
||||
PhysObj:EnableMotion( freezeWhenDone )
|
||||
Ent:SetNotSolid( false )
|
||||
Ent:SetPos( ResetPos )
|
||||
Ent:SetAngles( ResetAng )
|
||||
|
||||
for i = 1, table.Count( freezeWheels ) do
|
||||
local Wheel = Ent.Wheels[ i ]
|
||||
if IsValid( Wheel ) then
|
||||
local wPObj = Wheel:GetPhysicsObject()
|
||||
|
||||
Wheel:SetNotSolid( false )
|
||||
|
||||
if IsValid( wPObj ) then
|
||||
wPObj:EnableMotion( freezeWheels[i].dofreeze )
|
||||
end
|
||||
|
||||
Wheel:SetPos( freezeWheels[ i ].pos )
|
||||
Wheel:SetAngles( freezeWheels[ i ].ang )
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if Ent.CustomWheels then
|
||||
if Ent.GhostWheels then
|
||||
timer.Simple( Update and 0.25 or 0, function()
|
||||
if not IsValid( Ent ) then return end
|
||||
if ply.TOOLMemory.WheelTool_Foffset and ply.TOOLMemory.WheelTool_Roffset then
|
||||
SetWheelOffset( Ent, ply.TOOLMemory.WheelTool_Foffset, ply.TOOLMemory.WheelTool_Roffset )
|
||||
end
|
||||
|
||||
if not ply.TOOLMemory.FrontWheelOverride and not ply.TOOLMemory.RearWheelOverride then return end
|
||||
|
||||
local front_model = ply.TOOLMemory.FrontWheelOverride or vehicle.Members.CustomWheelModel
|
||||
local front_angle = GetAngleFromSpawnlist(front_model)
|
||||
|
||||
local camber = ply.TOOLMemory.Camber or 0
|
||||
local rear_model = ply.TOOLMemory.RearWheelOverride or (vehicle.Members.CustomWheelModel_R and vehicle.Members.CustomWheelModel_R or front_model)
|
||||
local rear_angle = GetAngleFromSpawnlist(rear_model)
|
||||
|
||||
if not front_model or not rear_model or not front_angle or not rear_angle then return end
|
||||
|
||||
if ValidateModel( front_model ) and ValidateModel( rear_model ) then
|
||||
Ent.Camber = camber
|
||||
ApplyWheel(Ent, {front_model,front_angle,rear_model,rear_angle,camber})
|
||||
else
|
||||
ply:PrintMessage( HUD_PRINTTALK, "selected wheel does not exist on the server")
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function TOOL:RightClick( trace )
|
||||
if CLIENT then return true end
|
||||
|
||||
local ent = trace.Entity
|
||||
local ply = self:GetOwner()
|
||||
|
||||
if ply.LockRightClick then ply:PrintMessage( HUD_PRINTTALK, "Duplicator is busy") return end
|
||||
|
||||
if not istable(ply.TOOLMemory) then
|
||||
ply.TOOLMemory = {}
|
||||
end
|
||||
|
||||
if not IsValid(ent) then
|
||||
table.Empty( ply.TOOLMemory )
|
||||
|
||||
net.Start("sphys_dupe")
|
||||
net.WriteTable( ply.TOOLMemory )
|
||||
net.Send( ply )
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
if not simfphys.IsCar( ent ) then return false end
|
||||
|
||||
self:GetVehicleData( ent, ply )
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function TOOL:Reload( trace )
|
||||
return false
|
||||
end
|
||||
Reference in New Issue
Block a user