diff --git a/README.md b/README.md index 2cee0fef..00d01495 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,11 @@ A pack of content and entity classes to add cars, motorcycles, planes, helicopte | `glide_global_damage_multiplier` `` | Multiplier for damage taken from any source (except from collisions) | `glide_player_collision_damage_multiplier` `` | Damage multiplier for players inside vehicles taking damage from hard collisions. +### Trailer +| Command | Description +| ------- | ----------- +| `glide_trailer_attach_percentage_wheel` `` | Percentage of wheels required on trailer to attach it to a vehicle. Default : 0.6 + ### Sandbox limits | Command | Description diff --git a/lua/autorun/sh_glide.lua b/lua/autorun/sh_glide.lua index 07cbf713..03d00d4d 100644 --- a/lua/autorun/sh_glide.lua +++ b/lua/autorun/sh_glide.lua @@ -183,6 +183,9 @@ if SERVER then CreateConVar( "glide_world_physics_damage_multiplier", "1", FCVAR_ARCHIVE + FCVAR_NOTIFY, "Damage multiplier taken by Glide vehicles after colliding against the world.", 0, 10 ) CreateConVar( "glide_global_damage_multiplier", "1", FCVAR_ARCHIVE + FCVAR_NOTIFY, "Multiplier for damage taken from any source (except collisions).", 0, 10 ) CreateConVar( "glide_player_collision_damage_multiplier", "0.5", FCVAR_ARCHIVE + FCVAR_NOTIFY, "Damage multiplier for players inside vehicles taking damage from hard collisions.", 0, 2 ) + + -- Trailer convars + CreateConVar( "glide_trailer_attach_percentage_wheel", "0.6", FCVAR_ARCHIVE + FCVAR_NOTIFY + FCVAR_REPLICATED, "Percentage of wheels required on trailer to attach it to a vehicle.", 0, 1 ) end -- Toggles diff --git a/lua/entities/base_glide/init.lua b/lua/entities/base_glide/init.lua index 3006f603..f21a1a1e 100644 --- a/lua/entities/base_glide/init.lua +++ b/lua/entities/base_glide/init.lua @@ -804,3 +804,109 @@ function ENT:GetSpawnColor() local color = colors[math.random( #colors )] return Color( color.r, color.g, color.b ) end + +function ENT:AttachTrailer( trailer ) + if not IsValid( trailer ) then return end + + trailer:AttachToVehicle( self ) + self.AttachedTrailer = trailer + + local driver = self:GetDriver() + if not IsValid( driver ) then return end + + Glide.SendNotification( driver, { + text = "#glide.notify.vehicle_attach", + icon = "materials/glide/icons/trailer.png", + sound = "buttons/button15.wav", + immediate = true + } ) +end + +function ENT:DetachTrailer() + if not IsValid( self.AttachedTrailer ) then return end + + self.AttachedTrailer:DetachFromVehicle( self ) + self.AttachedTrailer = nil + + local driver = self:GetDriver() + if not IsValid( driver ) then return end + + Glide.SendNotification( driver, { + text = "#glide.notify.vehicle_detach", + icon = "materials/glide/icons/trailer.png", + sound = "buttons/button15.wav", + immediate = true + } ) +end + +local percentageWheel = GetConVar( "glide_trailer_attach_percentage_wheel" ):GetFloat() -- At least 60% of wheels must be on the trailer +local minWheels = { + ["base_glide_heli"] = 0, + ["base_glide_boat"] = 0, + ["base_glide_bike"] = 2, + ["base_glide_motorcycle"] = 2, + ["base_glide_plane"] = 2, + ["base_glide_car"] = 3, + ["base_glide_tank"] = 4, +} + +local OFFSET_WHEEL = Vector( 0, 0, 200 ) + +local function canFilter( vehicle, ent ) + return ent:GetClass() ~= "glide_wheel" and ent ~= vehicle +end + +function ENT:ToggleAttachDetachTrailer() + if self.cooldownAttachTrailer and CurTime() < self.cooldownAttachTrailer then return end + self.cooldownAttachTrailer = CurTime() + 0.5 + + if self:GetSpeed() > 5 then return end + + local minWheel = minWheels[self.Base] + if not minWheel then return end + + if IsValid( self.AttachedTrailer ) then + self:DetachTrailer() + else + local totalWheels = table.Count( self.wheels ) or 0 + if minWheel == 0 or totalWheels == 0 then + local posVehicle = self:GetPos() + local Trace = util.TraceLine( { + start = posVehicle, + endpos = posVehicle - OFFSET_WHEEL, + filter = function( ent ) return canFilter( self, ent ) end + } ) + + local trailerEntity = Trace.Entity + if IsValid( trailerEntity ) and trailerEntity.Base == "base_glide_trailer" then + self:AttachTrailer( trailerEntity ) + end + else + totalWheels = math.max( totalWheels, minWheel ) + + local wheelCount = 0 + local trailerEntity = nil + for _, wheel in Glide.EntityPairs( self.wheels ) do + if not IsValid( wheel ) then continue end + + local posWheel = wheel:GetPos() + local Trace = util.TraceLine( { + start = posWheel, + endpos = posWheel - OFFSET_WHEEL, + filter = function( ent ) return canFilter( self, ent ) end + } ) + + local trailer = Trace.Entity + if IsValid( trailer ) and trailer.Base == "base_glide_trailer" and ( not IsValid( trailerEntity ) or trailerEntity == trailer ) then + wheelCount = wheelCount + 1 + + trailerEntity = Trace.Entity + end + end + + if math.ceil( wheelCount / totalWheels ) >= percentageWheel then + self:AttachTrailer( trailerEntity ) + end + end + end +end \ No newline at end of file diff --git a/lua/entities/base_glide/shared.lua b/lua/entities/base_glide/shared.lua index c51f2be5..63d96b88 100644 --- a/lua/entities/base_glide/shared.lua +++ b/lua/entities/base_glide/shared.lua @@ -44,6 +44,7 @@ function ENT:SetupDataTables() self:NetworkVar( "Int", "EngineState" ) self:NetworkVar( "Bool", "IsEngineOnFire" ) self:NetworkVar( "Bool", "IsLocked" ) + self:NetworkVar( "Bool", "IsAttachedToTrailer" ) self:NetworkVar( "Int", "LockOnState" ) self:NetworkVar( "Entity", "LockOnTarget" ) diff --git a/lua/entities/base_glide/sv_input.lua b/lua/entities/base_glide/sv_input.lua index c4219e8a..818cddc3 100644 --- a/lua/entities/base_glide/sv_input.lua +++ b/lua/entities/base_glide/sv_input.lua @@ -174,6 +174,8 @@ function ENT:SetInputBool( seatIndex, action, pressed ) icon = "materials/glide/icons/" .. ( self.inputThrottleModifierToggle and "play_next" or "fast_forward" ) .. ".png", immediate = true } ) + elseif action == "attach_vehicle" then + self:ToggleAttachDetachTrailer() end if action == "toggle_engine" then diff --git a/lua/entities/base_glide_trailer.lua b/lua/entities/base_glide_trailer.lua index 37453261..379a8e8d 100644 --- a/lua/entities/base_glide_trailer.lua +++ b/lua/entities/base_glide_trailer.lua @@ -105,3 +105,44 @@ function ENT:OnPostThink( _dt, selfTbl ) self:SetTurnSignalState( attachedVehicle:GetTurnSignalState() ) self:SetIsVehicleReversing( attachedVehicle:IsReversing() ) end + +function ENT:AttachToVehicle( vehicle ) + if not IsValid( vehicle ) then return end + + constraint.Weld( self, vehicle, 0, 0, 0, true ) + constraint.NoCollide( self, vehicle, 0, 0 ) + self.listAttachedVehicle = self.listAttachedVehicle or {} + self.listAttachedVehicle[vehicle] = true + + vehicle:EnableEngine( false ) + vehicle:SetIsAttachedToTrailer( true ) + vehicle:CallOnRemove( ( "Glide_TrailerDetach_%s" ):format( self:EntIndex() ), function() + if not IsValid( self ) then return end + self:DetachFromVehicle( vehicle ) + end ) +end + +function ENT:DetachFromVehicle( vehicle ) + if not IsValid( vehicle ) then return end + + constraint.RemoveConstraints( vehicle, "Weld" ) + constraint.RemoveConstraints( vehicle, "NoCollide" ) + + if self.listAttachedVehicle then + self.listAttachedVehicle[vehicle] = nil + end + + vehicle:EnableEngine( true ) + vehicle:RemoveCallOnRemove( ( "Glide_TrailerDetach_%s" ):format( self:EntIndex() ) ) + vehicle:SetIsAttachedToTrailer( false ) +end + +function ENT:GetAttachedVehicles() + return self.listAttachedVehicle or {} +end + +function ENT:OnRemove() + for vehicle, _ in pairs( self:GetAttachedVehicles() ) do + self:DetachFromVehicle( vehicle ) + end +end \ No newline at end of file diff --git a/lua/entities/glide_wheel/cl_init.lua b/lua/entities/glide_wheel/cl_init.lua index 9a1b792b..d5e401f0 100644 --- a/lua/entities/glide_wheel/cl_init.lua +++ b/lua/entities/glide_wheel/cl_init.lua @@ -215,7 +215,7 @@ function ENT:Think() rollFactor = rollFactor + fastFactor end - if rollFactor > 0.1 and selfTbl.enableParticles then + if rollFactor > 0.1 and selfTbl.enableParticles and not parent:GetIsAttachedToTrailer() then rollFactor = Clamp( rollFactor, 0, 0.5 ) local eff = EffectData() @@ -227,7 +227,7 @@ function ENT:Think() Effect( "glide_tire_roll", eff ) end - if forwardSlipFactor > 0.2 and selfTbl.enableParticles then + if forwardSlipFactor > 0.2 and selfTbl.enableParticles and not parent:GetIsAttachedToTrailer() then forwardSlipFactor = Clamp( forwardSlipFactor, 0, 1 ) local eff = EffectData() diff --git a/lua/glide/sh_input.lua b/lua/glide/sh_input.lua index aedad742..f8f97acd 100644 --- a/lua/glide/sh_input.lua +++ b/lua/glide/sh_input.lua @@ -78,6 +78,7 @@ Glide.AddInputAction( "general_controls", "switch_weapon", KEY_R ) Glide.AddInputAction( "general_controls", "toggle_engine", KEY_I ) Glide.AddInputAction( "general_controls", "headlights", KEY_H ) Glide.AddInputAction( "general_controls", "free_look", KEY_LALT ) +Glide.AddInputAction( "general_controls", "attach_vehicle", KEY_M ) --[[ Inputs that only apply to land vehicle types diff --git a/resource/localization/en/glide_vehicles.properties b/resource/localization/en/glide_vehicles.properties index a59dac4e..96f0d2af 100644 --- a/resource/localization/en/glide_vehicles.properties +++ b/resource/localization/en/glide_vehicles.properties @@ -101,6 +101,7 @@ glide.input.signal_right=Right turn signal glide.input.aircraft_controls=Aircraft controls glide.input.countermeasures=Countermeasures glide.input.free_look=Free look (Flying with mouse only) +glide.input.attach_vehicle=Attach/Detach vehicle to trailer glide.input.landing_gear=Landing gear glide.input.pitch_up=Pitch up glide.input.pitch_down=Pitch down @@ -204,6 +205,8 @@ glide.notify.tip.countermeasures=Press %s to deploy countermeasures. glide.notify.tip.trailer_attached=Trailer attached. Press %s to release it. glide.notify.tip.trailer_detached=Trailer detached. glide.notify.tip.vtol_toggle=Hold %s to toggle the "Vertical Take-Off and Landing" mode. +glide.notify.vehicle_attach=The vehicle has been attached to the trailer. +glide.notify.vehicle_detach=The vehicle has been detached from the trailer. # HUD diff --git a/resource/localization/fr/glide_vehicles.properties b/resource/localization/fr/glide_vehicles.properties index 87b900ea..175630f3 100644 --- a/resource/localization/fr/glide_vehicles.properties +++ b/resource/localization/fr/glide_vehicles.properties @@ -101,6 +101,7 @@ glide.input.signal_right=Clignotant droit glide.input.aircraft_controls=Contrôles des aéronefs glide.input.countermeasures=Contre-mesures glide.input.free_look=Regard libre (Vol uniquement avec la souris) +glide.input.attach_vehicle=Attacher/Détacher un véhicule a une remorque glide.input.landing_gear=Train d'atterrissage glide.input.pitch_up=Monter (Tangage) glide.input.pitch_down=Descendre (Tangage) @@ -205,6 +206,8 @@ glide.notify.tip.countermeasures=Appuyez sur %s pour déployer les contre-mesure glide.notify.tip.trailer_attached=Remorque attachée. Appuyez sur %s pour la libérer. glide.notify.tip.trailer_detached=Remorque détachée. glide.notify.tip.vtol_toggle=Maintenez %s pour basculer le mode « Décollage et atterrissage verticaux ». +glide.notify.vehicle_attach=Le véhicule a été attaché à la remorque. +glide.notify.vehicle_detach=Le véhicule a été détaché de la remorque. # HUD