├── fxmanifest.lua ├── config.lua ├── README.md └── client └── cl_main.lua /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | 4 | author 'Gamzky' 5 | description 'Script to that allows you to push vehicles' 6 | version '1.1.2' 7 | 8 | lua54 'yes' 9 | 10 | client_scripts { 11 | '@ox_lib/init.lua', 12 | 'config.lua', 13 | 'client/cl_main.lua', 14 | } 15 | -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | Config = { 2 | target = { 3 | enable = true, 4 | startLabel = 'Push Vehicle', 5 | stopLabel = 'Stop Pushing', 6 | icon = 'fas fa-hand-paper', 7 | }, 8 | 9 | -- More information on keys: https://docs.fivem.net/docs/game-references/controls/#controls 10 | pushKeyPrimary = { index = 21, label = 'SHIFT' }, 11 | pushKeySecondary = { index = 38, label = 'E' }, 12 | 13 | pushLabel = 'Push', 14 | 15 | -- The maximum engine health a vehicle can have before they are not pushable anymore. Set to 1000 to allow pushing regardless of engine health. 16 | engineHealth = 100.0, 17 | 18 | animation = { 19 | dict = 'missfinale_c2ig_11', 20 | anim = 'pushcar_offcliff_m', 21 | }, 22 | 23 | disabledClasses = { 24 | [13] = true, -- Cycles 25 | [14] = true, -- Boats 26 | [15] = true, -- Helicopters 27 | [16] = true, -- Planes 28 | [21] = true, -- Trains 29 | }, 30 | 31 | -- Disabled controls while pushing a vehicle 32 | disabledControls = { 33 | 22, -- Space 34 | 23, -- F 35 | 24, -- LMB 36 | 73, -- X 37 | 140, -- R 38 | 141, -- Q 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vehicle Push Script 2 | 3 | #### ⭐ Check out our other resources on [gamzkystore.com](https://gamzkystore.com/) or in our [Discord](https://discord.com/invite/sjFP3HrWc3). 4 | 5 | #### 📼 Preview video: [Streamable](https://streamable.com/cg6535) 6 | 7 | This vehicle push script allows players to push vehicles in the game, useful when they are undrivable or stuck. 8 | 9 | ## Features 10 | - Framework indepenent. So it works for any framework like ESX, QBCore, etc. 11 | - Vehicles can only be pushed if their engine health is below a certain threshold (Configurable). 12 | - Configurable controls: Primary push key (SHIFT) and secondary push key (E) can be adjusted in the `config.lua`. 13 | - Prevents pushing of vehicle types that are unrealistic to push, such as boats, helicopters, planes, and trains, specified in `config.lua`. 14 | - Animation support: Players perform a realistic animation when pushing vehicles. 15 | - Configurable disabled controls while pushing, ensuring players can't perform other actions like firing a weapon or jumping. 16 | - Optionally enable interactions with ox_target (or any other targeting script, but you'll have to add it yourself). 17 | 18 | #### Dependencies 19 | - The only dependency is [ox_lib](https://github.com/overextended/ox_lib). 20 | - If you want to use the targeting feature, you'll need to add [ox_target](https://github.com/overextended/ox_target) to your server. 21 | -------------------------------------------------------------------------------- /client/cl_main.lua: -------------------------------------------------------------------------------- 1 | local closestVehicle, closestDistance, closestCoords 2 | local isPushing = false 3 | 4 | CreateThread(function() 5 | while true do 6 | Wait(250) 7 | 8 | local ped = PlayerPedId() 9 | local pedCoords = GetEntityCoords(ped) 10 | local isInVehicle = IsPedInAnyVehicle(ped, false) 11 | 12 | if not isInVehicle then 13 | closestVehicle, closestCoords = lib.getClosestVehicle(pedCoords, 10.0) 14 | closestDistance = closestCoords and #(pedCoords - closestCoords) or 0 15 | else 16 | closestVehicle, closestDistance, closestCoords = nil, 0, nil 17 | end 18 | end 19 | end) 20 | 21 | function InitTargets() 22 | exports.ox_target:addGlobalVehicle({ 23 | { 24 | label = Config.target.startLabel, 25 | icon = Config.target.icon, 26 | distance = 2.0, 27 | canInteract = function(entity, distance, coords, name) 28 | if isPushing then 29 | return false 30 | end 31 | 32 | if NetworkGetEntityIsNetworked(entity) then 33 | return false 34 | end 35 | 36 | local ped = PlayerPedId() 37 | local distanceFront, distanceBack = IsPlayerInFrontOrBack(ped, entity) 38 | 39 | if (distanceFront > 1.2) and (distanceBack > 1.2) then 40 | return false 41 | end 42 | 43 | return IsVehiclePushable(entity) 44 | end, 45 | onSelect = function(data) 46 | local ped = PlayerPedId() 47 | local distanceFront, distanceBack, isVehicleInFront = IsPlayerInFrontOrBack(ped, data.entity) 48 | isPushing = true 49 | StartPushingVehicle(data.entity, isVehicleInFront) 50 | end 51 | }, 52 | { 53 | label = Config.target.stopLabel, 54 | icon = Config.target.icon, 55 | distance = 2.0, 56 | canInteract = function(entity, distance, coords, name) 57 | return isPushing 58 | end, 59 | onSelect = function(data) 60 | isPushing = false 61 | end 62 | } 63 | }) 64 | end 65 | 66 | CreateThread(function() 67 | if Config.target.enable then 68 | InitTargets() 69 | return 70 | end 71 | 72 | while true do 73 | Wait(0) 74 | 75 | local ped = PlayerPedId() 76 | if not IsPedInAnyVehicle(ped, true) then 77 | if closestVehicle and (closestDistance < 10.0) and IsVehiclePushable(closestVehicle) then 78 | local distanceFront, distanceBack, isVehicleInFront = IsPlayerInFrontOrBack(ped, closestVehicle) 79 | 80 | local textCoords 81 | if isVehicleInFront then 82 | textCoords = GetOffsetFromEntityInWorldCoords(closestVehicle, 0.0, 83 | GetModelDimensions(GetEntityModel(closestVehicle)).y * -1, 0.5) 84 | else 85 | textCoords = GetOffsetFromEntityInWorldCoords(closestVehicle, 0.0, 86 | GetModelDimensions(GetEntityModel(closestVehicle)).y, 0.5) 87 | end 88 | 89 | if (distanceFront < 4.0) or (distanceBack < 4.0) then 90 | local text = Config.pushLabel 91 | if (distanceFront < 1.2) or (distanceBack < 1.2) then 92 | text = ('[~b~%s + %s~w~] %s'):format(Config.pushKeyPrimary.label, Config.pushKeySecondary.label, 93 | Config.pushLabel) 94 | 95 | if IsControlPressed(0, Config.pushKeyPrimary.index) and IsControlPressed(0, Config.pushKeySecondary.index) then 96 | if NetworkHasControlOfEntity(closestVehicle) then 97 | StartPushingVehicle(closestVehicle, isVehicleInFront) 98 | else 99 | Notify('~r~Enter the vehicle first to gain control of the vehicle.') 100 | end 101 | end 102 | end 103 | 104 | DrawText3D(textCoords, text) 105 | else 106 | Wait(250) 107 | end 108 | else 109 | Wait(1000) 110 | end 111 | else 112 | Wait(500) 113 | end 114 | end 115 | end) 116 | 117 | function IsPlayerInFrontOrBack(ped, vehicle) 118 | local pedCoords = GetEntityCoords(ped, true) 119 | 120 | local success, entityModel = pcall(GetEntityModel, vehicle) 121 | if not success then 122 | return 999, 999, false 123 | end 124 | 125 | local dimension = GetModelDimensions(entityModel) 126 | local frontCoords = GetOffsetFromEntityInWorldCoords(vehicle, 0.0, dimension.y, 0.0) 127 | local backCoords = GetOffsetFromEntityInWorldCoords(vehicle, 0.0, dimension.y * -1, 0.0) 128 | 129 | local distanceFront = #(pedCoords - frontCoords) 130 | local distanceBack = #(pedCoords - backCoords) 131 | 132 | return distanceFront, distanceBack, distanceBack < distanceFront 133 | end 134 | 135 | function StartPushingVehicle(vehicle, isVehicleInFront) 136 | local ped = PlayerPedId() 137 | local dimension = GetModelDimensions(GetEntityModel(vehicle)) 138 | if isVehicleInFront then 139 | AttachEntityToEntity( 140 | ped, vehicle, 0, 0.0, dimension.y * -1 + 0.1, dimension.z + 1.0, 0.0, 0.0, 180.0, 0.0, false, false, true, 141 | false, true 142 | ) 143 | else 144 | AttachEntityToEntity( 145 | ped, vehicle, 0, 0.0, dimension.y - 0.3, dimension.z + 1.0, 0.0, 0.0, 0.0, 0.0, false, false, true, false, 146 | true 147 | ) 148 | end 149 | 150 | lib.requestAnimDict(Config.animation.dict) 151 | TaskPlayAnim( 152 | ped, Config.animation.dict, Config.animation.anim, 2.0, -8.0, -1, 35, 0, 0, 0, 0 153 | ) 154 | 155 | Wait(200) 156 | 157 | while true do 158 | Wait(0) 159 | 160 | for i = 1, #Config.disabledControls do 161 | DisableControlAction(0, Config.disabledControls[i], true) 162 | end 163 | 164 | if IsControlJustPressed(0, 34) then -- A 165 | local wheelAngle = GetVehicleWheelSteeringAngle(vehicle) 166 | if (wheelAngle < -0.1) then 167 | SetVehicleSteeringAngle(vehicle, 0.0) 168 | else 169 | SetVehicleSteeringAngle(vehicle, 30.0) 170 | end 171 | end 172 | 173 | if IsControlJustPressed(0, 35) then -- D 174 | local wheelAngle = GetVehicleWheelSteeringAngle(vehicle) 175 | if (wheelAngle > 0.1) then 176 | SetVehicleSteeringAngle(vehicle, 0.0) 177 | else 178 | SetVehicleSteeringAngle(vehicle, -30.0) 179 | end 180 | end 181 | 182 | if isVehicleInFront then 183 | SetVehicleForwardSpeed(vehicle, -1.0) 184 | else 185 | SetVehicleForwardSpeed(vehicle, 1.0) 186 | end 187 | 188 | local shouldStopPushing = false 189 | if Config.target.enable then 190 | shouldStopPushing = not isPushing or not IsEntityAttachedToEntity(ped, vehicle) 191 | else 192 | shouldStopPushing = not IsControlPressed(0, Config.pushKeySecondary.index) or 193 | not IsEntityAttachedToEntity(ped, vehicle) 194 | end 195 | if shouldStopPushing then 196 | SetVehicleForwardSpeed(vehicle, 0.0) 197 | DetachEntity(ped, false, false) 198 | StopAnimTask(ped, Config.animation.dict, Config.animation.anim, 2.0) 199 | break 200 | end 201 | end 202 | end 203 | 204 | function IsVehiclePushable(vehicle) 205 | if not IsVehicleSeatFree(vehicle, -1) then 206 | return false 207 | end 208 | 209 | if (GetVehicleEngineHealth(vehicle) > Config.engineHealth) then 210 | return false 211 | end 212 | 213 | local class = GetVehicleClass(vehicle) 214 | if Config.disabledClasses[class] then 215 | return false 216 | end 217 | 218 | return true 219 | end 220 | 221 | function Notify(message) 222 | SetNotificationTextEntry('STRING') 223 | AddTextComponentSubstringPlayerName(message) 224 | DrawNotification(false, true) 225 | end 226 | 227 | function DrawText3D(coords, text) 228 | local onScreen, _x, _y = World3dToScreen2d(coords.x, coords.y, coords.z) 229 | if onScreen then 230 | SetTextScale(0.3, 0.3) 231 | SetTextFont(4) 232 | SetTextProportional(true) 233 | SetTextColour(255, 255, 255, 215) 234 | SetTextEntry('STRING') 235 | SetTextCentre(true) 236 | AddTextComponentString(text) 237 | DrawText(_x, _y) 238 | local factor = (string.len(text)) / 370 239 | DrawRect(_x, _y + 0.0125, 0.015 + factor, 0.03, 41, 11, 41, 68) 240 | end 241 | end 242 | --------------------------------------------------------------------------------