--[[ | 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 = "#Wheel Model Editor" TOOL.Command = nil TOOL.ConfigName = "" TOOL.ClientConVar[ "frontwheelmodel" ] = "models/props_vehicles/apc_tire001.mdl" TOOL.ClientConVar[ "rearwheelmodel" ] = "models/props_vehicles/apc_tire001.mdl" TOOL.ClientConVar[ "sameasfront" ] = 1 TOOL.ClientConVar[ "camber" ] = 0 TOOL.ClientConVar[ "offsetfront" ] = 0 TOOL.ClientConVar[ "offsetrear" ] = 0 if CLIENT then language.Add( "tool.simfphyswheeleditor.name", "Wheel Model Editor" ) language.Add( "tool.simfphyswheeleditor.desc", "Changes the wheels for simfphys vehicles with CustomWheels Enabled" ) language.Add( "tool.simfphyswheeleditor.0", "Left click apply wheel model. Reload to reset" ) language.Add( "tool.simfphyswheeleditor.1", "Left click apply wheel model. Reload to reset" ) 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(ply, 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 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 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 ) local ent = trace.Entity if not simfphys.IsCar( ent ) then return false end if SERVER then if not ent.CustomWheels then return end 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.25, function() if not IsValid( ent ) then return end local front_model = self:GetClientInfo("frontwheelmodel") local front_angle = GetAngleFromSpawnlist(front_model) local sameasfront = self:GetClientInfo("sameasfront") == "1" local camber = self:GetClientInfo("camber") local rear_model = sameasfront and front_model or self:GetClientInfo("rearwheelmodel") local rear_angle = GetAngleFromSpawnlist(rear_model) local front_offset = self:GetClientInfo("offsetfront") local rear_offset = self:GetClientInfo("offsetrear") if not front_model or not rear_model or not front_angle or not rear_angle then print("wtf bro how did you do this") return false end if not ValidateModel( front_model ) or not ValidateModel( rear_model ) then local ply = self:GetOwner() ply:PrintMessage( HUD_PRINTTALK, "selected wheel does not exist on the server") return false end if ent.CustomWheels then if ent.GhostWheels then ent:SteerVehicle( 0 ) for i = 1, table.Count( ent.Wheels ) do local Wheel = ent.Wheels[ i ] if IsValid( Wheel ) then local physobj = Wheel:GetPhysicsObject() physobj:EnableMotion( true ) physobj:Wake() end end ent.Camber = camber ApplyWheel(self:GetOwner(), ent, {front_model,front_angle,rear_model,rear_angle,camber}) SetWheelOffset( ent, front_offset, rear_offset ) end end timer.Simple( 0.25, 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) end return true end function TOOL:RightClick( trace ) return false end function TOOL:Reload( trace ) local ent = trace.Entity if not simfphys.IsCar( ent ) then return false end if SERVER 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.25, function() if not IsValid( ent ) then return end local vname = ent:GetSpawn_List() local VehicleList = list.Get( "simfphys_vehicles" )[vname] if ent.CustomWheels then if ent.GhostWheels then ent:SteerVehicle( 0 ) for i = 1, table.Count( ent.Wheels ) do local Wheel = ent.Wheels[ i ] if IsValid( Wheel ) then local physobj = Wheel:GetPhysicsObject() physobj:EnableMotion( true ) physobj:Wake() end end local front_model = VehicleList.Members.CustomWheelModel local front_angle = VehicleList.Members.CustomWheelAngleOffset local rear_model = VehicleList.Members.CustomWheelModel_R and VehicleList.Members.CustomWheelModel_R or front_model local rear_angle = VehicleList.Members.CustomWheelAngleOffset ApplyWheel(self:GetOwner(), ent, {front_model,front_angle,rear_model,rear_angle}) SetWheelOffset( ent, 0, 0 ) end end timer.Simple( 0.25, 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) end return true end local ConVarsDefault = TOOL:BuildConVarList() function TOOL.BuildCPanel( panel ) panel:AddControl( "Header", { Text = "#tool.simfphyswheeleditor.name", Description = "#tool.simfphyswheeleditor.desc" } ) panel:AddControl( "ComboBox", { MenuButton = 1, Folder = "wheeleditor", Options = { [ "#preset.default" ] = ConVarsDefault }, CVars = table.GetKeys( ConVarsDefault ) } ) panel:AddControl( "Slider", { Label = "Camber", Type = "Float", Min = "-60", Max = "60", Command = "simfphyswheeleditor_camber" }) panel:AddControl( "Slider", { Label = "Offset (Front)", Type = "Float", Min = "-50", Max = "50", Command = "simfphyswheeleditor_offsetfront" }) panel:AddControl( "Slider", { Label = "Offset (Rear)", Type = "Float", Min = "-50", Max = "50", Command = "simfphyswheeleditor_offsetrear" }) panel:AddControl( "Label", { Text = "" } ) panel:AddControl( "Label", { Text = "Front Wheel Model" } ) panel:AddControl( "PropSelect", { Label = "", ConVar = "simfphyswheeleditor_frontwheelmodel", Height = 0, Models = list.Get( "simfphys_Wheels" ) } ) panel:AddControl( "Label", { Text = "" } ) panel:AddControl( "Label", { Text = "Rear Wheel Model" } ) panel:AddControl( "Checkbox", { Label = "same as front", Command = "simfphyswheeleditor_sameasfront", }) panel:AddControl( "PropSelect", { Label = "", ConVar = "simfphyswheeleditor_rearwheelmodel", Height = 0, Models = list.Get( "simfphys_Wheels" ) } ) end list.Set( "simfphys_Wheels", "models/props_phx/wheels/magnetic_large.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/smallwheel.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/normal_tire.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/wheels/breakable_tire.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/wheels/drugster_front.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/wheels/drugster_back.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/wheels/moped_tire.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/wheels/trucktire.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/wheels/trucktire2.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/wheels/747wheel.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/props_phx/wheels/monster_truck.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/bmw.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/wheel_2.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/rim_1.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/wheel_extruded_48.mdl", {Angle = Angle(-90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/wheel_race.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/tractors.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/wheel_rounded_36.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/wheel_rounded_36s.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/wheel_rugged_24.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/wheel_rugged_24w.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/wheel_spike_24.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/mechanics/wheels/wheel_spike_48.mdl", {Angle = Angle(90,0,0)} ) list.Set( "simfphys_Wheels", "models/xeon133/racewheel/race-wheel-30.mdl", {Angle = Angle(0,-90,0)} ) list.Set( "simfphys_Wheels", "models/xeon133/racewheelskinny/race-wheel-30_s.mdl", {Angle = Angle(0,-90,0)} ) list.Set( "simfphys_Wheels", "models/nateswheel/nateswheel.mdl", {Angle = Angle(0,180,0)} ) list.Set( "simfphys_Wheels", "models/xqm/airplanewheel1medium.mdl", {Angle = Angle(0,180,0)} ) list.Set( "simfphys_Wheels", "models/xeon133/offroad/off-road-30.mdl", {Angle = Angle(0,180,0)} ) local LW_Wheels = { "models/lonewolfie/wheels/wheel_2015chargerpolice.mdl", "models/lonewolfie/wheels/wheel_ametorqthrust.mdl", "models/lonewolfie/wheels/wheel_ametorqthrust_eaglest.mdl", "models/lonewolfie/wheels/wheel_com_rt_gold.mdl", "models/lonewolfie/wheels/wheel_com_th2.mdl", "models/lonewolfie/wheels/wheel_cucv_big.mdl", "models/lonewolfie/wheels/wheel_cucv_small.mdl", "models/lonewolfie/wheels/wheel_fiat595.mdl", "models/lonewolfie/wheels/wheel_ham_edition_race.mdl", "models/lonewolfie/wheels/wheel_impalapolice.mdl", "models/lonewolfie/wheels/wheel_laxaniltc701.mdl", "models/lonewolfie/wheels/wheel_miktometdrag_big.mdl", "models/lonewolfie/wheels/wheel_miktometdrag_highprofile.mdl", "models/lonewolfie/wheels/wheel_miktometdrag_lowprofile.mdl", "models/lonewolfie/wheels/wheel_monstertruck.mdl", "models/lonewolfie/wheels/wheel_oet_type_rxx.mdl", "models/lonewolfie/wheels/wheel_speedline22b.mdl", "models/lonewolfie/wheels/wheel_suvpolice.mdl", "models/lonewolfie/wheels/wheel_volkte37.mdl", "models/lonewolfie/wheels/wheel_wed_sa_97.mdl", "models/lonewolfie/wheels/wheel_welddrag.mdl", "models/lonewolfie/wheels/wheel_welddrag_big.mdl" } for i = 1, table.Count( LW_Wheels ) do if file.Exists( LW_Wheels[i], "GAME" ) then list.Set( "simfphys_Wheels", LW_Wheels[i], {Angle = Angle(0,90,0)} ) end end timer.Simple( 0.1, function() 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 if (file.Exists( FrontWheel, "GAME" )) then list.Set( "simfphys_Wheels", FrontWheel, {} ) end end if (RearWheel) then if (file.Exists( RearWheel, "GAME" )) then list.Set( "simfphys_Wheels", RearWheel, {} ) end end end end end)