├── .editorconfig ├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── client ├── hotwire.lua ├── main.lua ├── steeringwheel.lua ├── utils.lua └── vehiclekeys.lua ├── config.lua ├── fxmanifest.lua ├── server ├── hotwire.lua ├── main.lua └── versionchecker.lua └── translation.lua /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = tab 3 | indent_size = 4 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Lua sources 2 | luac.out 3 | 4 | # luarocks build files 5 | *.src.rock 6 | *.zip 7 | *.tar.gz 8 | 9 | # Object files 10 | *.o 11 | *.os 12 | *.ko 13 | *.obj 14 | *.elf 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | *.def 26 | *.exp 27 | 28 | # Shared objects (inc. Windows DLLs) 29 | *.dll 30 | *.so 31 | *.so.* 32 | *.dylib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.i*86 39 | *.x86_64 40 | *.hex 41 | 42 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Copyright (C) since 2024 Musiker15 - MSK Scripts 4 | 5 | Contact for business enquiries: info@msk-scripts.de 6 | 7 | This software is a resource for the "FiveM" modification for the game "Grand Theft Auto V" and is comprised of the files this license is attached to. It is only meant to function inside of this environment. 8 | 9 | ## Usage Rights 10 | The user is granted permission to use and modify this software for personal or non-commercial purposes. The user is granted permission to integrate this software as a dependency in his resources and publish his resources as long as the resource is available for FREE. 11 | 12 | The user is not allowed to publish, sell or distribute the software or any part of it without the consent of the licensor and apart from forking the official repository on GitHub. 13 | 14 | The user may not create derivatives or copies of the software that violate these licensing terms. 15 | This license may be revoked by the licensor at any time if the user violates the terms of the license. Upon termination of the license, the user must destroy all copies of the software and any resulting modifications. 16 | 17 | The licensor reserves the right to change the licensing terms with each update of the software. The user is required to review and agree to the updated licensing terms in order to continue using the updated version of the software. 18 | 19 | By using the software, the user automatically accepts these licensing terms and any future changes made through software updates. 20 | 21 | ## Disclaimer of Liability 22 | The software is provided "as is", without warranties of any kind. The licensor is not liable for any damages resulting from using and modfifying the software. 23 | 24 | ## Further information 25 | Further information and documentation referring to the software can be found at https://docu.msk-scripts.de. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MSK EngineToggle 2 | [ESX/QBCore] Vehicle EngineToggle On/Off 3 | 4 | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/MSK-Scripts/msk_enginetoggle?color=gree&label=Update) 5 | 6 | **Forum:** https://forum.cfx.re/t/msk-enginetoggle-toggle-engine-on-off/4793840 7 | 8 | **Discord Support:** https://discord.gg/5hHSBRHvJE 9 | 10 | ## Description 11 | * The engine keeps running if you leave the vehicle without turning the engine off. 12 | * You can set that the engine starts automatically when entering a vehicle. 13 | * You can set a Command and Hotkey *(RegisterKeyMapping)*. 14 | * Set your own Notification and Progressbar. 15 | * If you set `Config.VehicleKeys` to true then only the Owner of the Vehicle or someone with a Key can start the Engine! 16 | * Admin Command to start/stop the engine without a Key *(Bypass)* 17 | * Whitelist for models and plates that do not need a Key to start/stop the engine 18 | * Save the Angel of the Steering Wheel *(Synced)* 19 | * Hotwire Function in compatibility with VehicleKeyChain and Jaksams vehicle_keys 20 | 21 | ## Resmon 22 | Resmon without any near vehicles 23 | ![Screenshot_17](https://github.com/user-attachments/assets/b20c7aac-45f4-41c8-b0ab-1fd54e98f9a4) 24 | 25 | Resmon with near vehicles and engines on 26 | ![Screenshot_16](https://github.com/user-attachments/assets/e5fe6e23-a90d-4dfc-9f6f-34792f9d9c29) 27 | 28 | ## Requirements 29 | * [ESX Legacy](https://github.com/esx-framework/esx_core) or [QBCore](https://github.com/qbcore-framework/qb-core) 30 | * [oxmysql](https://github.com/overextended/oxmysql) 31 | * [ox_lib](https://github.com/overextended/ox_lib) 32 | * [msk_core](https://github.com/MSK-Scripts/msk_core) 33 | ### Optional 34 | * [MSK VehicleKeys](https://forum.cfx.re/t/esx-qbcore-msk-vehiclekeys-unique-items/5264475) 35 | * [VehicleKeyChain](https://forum.cfx.re/t/release-vehicle-key-chain-v4-1-4-esx-qb/3319563) 36 | * [VehicleClamp](https://docs.kiminaze.de/scripts/vehicleclamp-pre-release) 37 | * [vehicle_keys](https://forum.cfx.re/t/esx-qbcore-vehicles-keys-vehicles-lock-remote-control-ui-and-much-more/4857274) 38 | * [wasabi_carlock](https://forum.cfx.re/t/esx-qbcore-wasabis-car-lock-system/4982151) 39 | * [qs-vehiclekeys](https://www.quasar-store.com/de/package/5269147) 40 | 41 | ## Exports 42 | All exports are CLIENTSIDE. Look at the [Documentation](https://docu.msk-scripts.de/enginetoggle) for more information. 43 | * toggleEngine -> Toggles the engine on/off 44 | * toggleHotwire -> Starts the Hotwire Feature 45 | * GetEngineState -> Get the current Enginestate of the vehicle 46 | * SetVehicleDamaged -> Set the vehicle undrivable (Can't start/stop engine) 47 | * GetVehicleDamaged -> Get the vehicle is undrivable 48 | * SetSteeringAngle -> Set the steering angle 49 | * GetSteeringAngle -> Get the steering angle 50 | 51 | ### RealisticVehicleDamage 52 | If you use `RealisticVehicleDamage`, then replace following Code in `client.lua` on Line 333 in RealisticVehicleDamage: 53 | ```lua 54 | if healthEngineCurrent > cfg.engineSafeGuard+1 then 55 | SetVehicleUndriveable(vehicle, false) 56 | exports.msk_enginetoggle:SetVehicleDamaged(vehicle, false) 57 | end 58 | 59 | if healthEngineCurrent <= cfg.engineSafeGuard+1 and cfg.limpMode == false then 60 | SetVehicleUndriveable(vehicle, true) 61 | exports.msk_enginetoggle:SetVehicleDamaged(vehicle, true) 62 | end 63 | ``` 64 | 65 | ### QB-Vehiclefailure 66 | If you use `qb-vehiclefailure`, then replace the following Code in `client.lua` on Line 530 in qb-vehiclefailure: 67 | ```lua 68 | if healthEngineCurrent > cfg.engineSafeGuard+1 then 69 | SetVehicleUndriveable(vehicle, false) 70 | exports.msk_enginetoggle:SetVehicleDamaged(vehicle, false) 71 | end 72 | 73 | if healthEngineCurrent <= cfg.engineSafeGuard+1 and cfg.limpMode == false then 74 | local vehpos = GetEntityCoords(vehicle) 75 | StartParticleFxLoopedAtCoord("ent_ray_heli_aprtmnt_l_fire", vehpos.x, vehpos.y, vehpos.z-0.7, 0.0, 0.0, 0.0, 1.0, false, false, false, false) 76 | SetVehicleUndriveable(vehicle, true) 77 | exports.msk_enginetoggle:SetVehicleDamaged(vehicle, true) 78 | end 79 | ``` 80 | 81 | ## My other Scripts 82 | ### Paid 83 | * [[ESX] MSK Banking - Advanced Banking with NativeUI](https://forum.cfx.re/t/esx-msk-bankingsystem-with-nativeui/4859560) 84 | * [[ESX] MSK Garage - Garage & Impounds](https://forum.cfx.re/t/esx-msk-garage-and-impound/5122014) 85 | * [[ESX] MSK Handcuffs - Realistic Handcuffs](https://forum.cfx.re/t/esx-msk-handcuffs-realistic-handcuffs/4885324) 86 | * [[ESX/QBCore] MSK Radio - Channels with password](https://forum.cfx.re/t/esx-msk-radio/5237033) 87 | * [[ESX/QBCore] MSK Simcard - Change your phonenumber](https://forum.cfx.re/t/release-esx-qbcore-usable-simcard/4847008) 88 | * [[ESX] MSK Storage](https://forum.cfx.re/t/esx-msk-storage/5252155) 89 | * [[ESX/QBCore] MSK VehicleKeys - Unique Items Support](https://forum.cfx.re/t/esx-qbcore-msk-vehiclekeys-unique-items/5264475) 90 | 91 | ### Free 92 | * [MSK Scripts Repositories](https://github.com/MSK-Scripts) 93 | * [Musiker15's Repositories](https://github.com/Musiker15) 94 | -------------------------------------------------------------------------------- /client/hotwire.lua: -------------------------------------------------------------------------------- 1 | if Config.EnableLockpick and Config.LockpickHotkey.enable then 2 | RegisterCommand(Config.LockpickHotkey.command, function(source, args, rawCommand) 3 | local hasItem = MSK.HasItem(Config.LockpickSettings.item) 4 | 5 | if not hasItem then 6 | return Config.Notification(nil, Translation[Config.Locale]['hasno_lockpick'], 'error') 7 | end 8 | 9 | toggleLockpick() 10 | end) 11 | RegisterKeyMapping(Config.LockpickHotkey.command, 'Lockpick Vehicle', 'keyboard', Config.LockpickHotkey.key) 12 | end 13 | 14 | toggleLockpick = function() 15 | local playerPed = MSK.Player.ped 16 | local coords = MSK.Player.coords 17 | 18 | if IsPedInAnyVehicle(playerPed, false) then return end 19 | if not IsAnyVehicleNearPoint(coords.x, coords.y, coords.z, 5.0) then return end 20 | 21 | local vehicle = GetClosestVehicle(coords.x, coords.y, coords.z, 3.0, 0, 71) 22 | if not DoesEntityExist(vehicle) then return end 23 | 24 | local plate = GetVehicleNumberPlateText(vehicle) 25 | local animation = {dict = Config.Animation.lockpick.dict, anim = Config.Animation.lockpick.anim} 26 | 27 | local owner, stage = MSK.Trigger('msk_enginetoggle:getAlarmStage', plate) 28 | local alarmStage = Config.SafetyStages[stage] or Config.SafetyStages['stage_1'] 29 | 30 | if alarmStage.alarm then 31 | SetVehicleAlarm(vehicle, true) 32 | StartVehicleAlarm(vehicle) 33 | end 34 | 35 | if alarmStage.ownerAlert and owner then 36 | TriggerServerEvent('msk_enginetoggle:ownerAlert', GetEntityCoords(vehicle), owner) 37 | end 38 | 39 | if alarmStage.policeAlert then 40 | TriggerServerEvent('msk_enginetoggle:policeAlert', GetEntityCoords(vehicle)) 41 | end 42 | 43 | if alarmStage.liveCoords and owner then 44 | TriggerServerEvent('msk_enginetoggle:liveCoords', owner, VehToNet(vehicle), GetEntityCoords(vehicle)) 45 | end 46 | 47 | MSK.Request.AnimDict(animation.dict) 48 | TaskPlayAnim(playerPed, animation.dict, animation.anim, 8.0, 1.0, -1, 49, 0, false, false, false) 49 | FreezeEntityPosition(playerPed, true) 50 | 51 | local success = false 52 | if Config.LockpickSettings.action == 'progressbar' then 53 | local time = Config.LockpickProgessbar.time * 1000 54 | Config.progressBar(time, Translation[Config.Locale]['lockpicking']) 55 | Wait(time) 56 | elseif Config.LockpickSettings.action == 'skillbar' then 57 | if Config.LockpickSkillbar.type == 'ox_lib' then 58 | success = lib.skillCheck({Config.LockpickSkillbar.difficulty['1'], Config.LockpickSkillbar.difficulty['2'], Config.LockpickSkillbar.difficulty['3'], Config.LockpickSkillbar.difficulty['4']}, Config.LockpickSkillbar.inputs) 59 | elseif Config.LockpickSkillbar.type == 'qb-skillbar' then 60 | local p = promise.new() 61 | local Skillbar = exports['qb-skillbar']:GetSkillbarObject() 62 | 63 | Skillbar.Start({ 64 | duration = math.random(1000, 5000), -- how long the skillbar runs for 65 | pos = math.random(10, 30), -- how far to the right the static box is 66 | width = math.random(10, 20), -- how wide the static box is 67 | }, function() 68 | success = true 69 | p:resolve(success) 70 | end, function() 71 | success = false 72 | p:resolve(success) 73 | end) 74 | 75 | success = Citizen.Await(p) 76 | end 77 | end 78 | RemoveAnimDict(animation.dict) 79 | 80 | if not success and Config.LockpickSettings.action == 'progressbar' then 81 | if math.random(100) <= Config.LockpickProgessbar.lockpick then 82 | success = true 83 | end 84 | end 85 | 86 | if success then 87 | if GetResourceState('msk_vehiclekeys') == "started" then 88 | exports.msk_vehiclekeys:SetVehicleLockState(vehicle, false, true) -- vehicle, state, force 89 | else 90 | SetVehicleDoorsLocked(vehicle, 1) 91 | SetVehicleDoorsLockedForAllPlayers(vehicle, false) 92 | end 93 | FreezeEntityPosition(playerPed, false) 94 | ClearPedTasks(playerPed) 95 | Config.Notification(nil, Translation[Config.Locale]['vehicle_unlocked'], 'success') 96 | elseif not success then 97 | TriggerServerEvent('msk_enginetoggle:removeLockpickItem') 98 | FreezeEntityPosition(playerPed, false) 99 | ClearPedTasks(playerPed) 100 | Config.Notification(nil, Translation[Config.Locale]['hotwiring_failed'], 'error') 101 | return 102 | end 103 | 104 | Wait(500) 105 | 106 | local needToHotwire = false 107 | if not GetEngineState(vehicle) then 108 | needToHotwire = true 109 | end 110 | TaskEnterVehicle(playerPed, vehicle, 10.0, -1, 1.0, 1, 0) 111 | Wait(5000) 112 | 113 | local playerPed = MSK.Player.ped 114 | local vehicle = MSK.Player.vehicle 115 | local plate = GetVehicleNumberPlateText(vehicle) 116 | 117 | if Config.VehicleKeys.enable or Config.LockpickSettings.enableSearchKey then 118 | local dict = Config.Animation.searchKey.dict 119 | local anim = Config.Animation.searchKey.anim 120 | local time = Config.Animation.searchKey.time * 1000 121 | 122 | MSK.Request.AnimDict(dict) 123 | TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, -1, 49, 0, false, false, false) 124 | if Config.Animation.searchKey.enableProgressbar then 125 | Config.progressBar(time, Translation[Config.Locale]['search_key']) 126 | end 127 | Wait(time) 128 | 129 | if math.random(100) <= Config.LockpickSettings.searchKey then 130 | if Config.VehicleKeys.enable and GetResourceState(Config.VehicleKeys.script) == "started" then 131 | TriggerServerEvent('msk_enginetoggle:addTempKey', plate, GetEntityModel(vehicle)) 132 | end 133 | needToHotwire = false 134 | Config.Notification(nil, Translation[Config.Locale]['hotwiring_foundkey'], 'success') 135 | else 136 | Config.Notification(nil, Translation[Config.Locale]['hotwiring_notfoundkey'], 'error') 137 | end 138 | 139 | ClearPedTasks(playerPed) 140 | RemoveAnimDict(dict) 141 | end 142 | 143 | if needToHotwire then 144 | local dict = Config.Animation.hotwire.dict 145 | local anim = Config.Animation.hotwire.anim 146 | local action = Config.Animation.hotwire.action 147 | local time = Config.Animation.hotwire.time * 1000 148 | MSK.Request.AnimDict(dict) 149 | TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, -1, 49, 0, false, false, false) 150 | 151 | local success = false 152 | if action == 'progressbar' then 153 | Config.progressBar(time, Translation[Config.Locale]['hotwiring']) 154 | Wait(time) 155 | success = true 156 | elseif action == 'skillbar' then 157 | if Config.LockpickSkillbar.type == 'ox_lib' then 158 | success = lib.skillCheck({Config.LockpickSkillbar.difficulty['1'], Config.LockpickSkillbar.difficulty['2'], Config.LockpickSkillbar.difficulty['3'], Config.LockpickSkillbar.difficulty['4']}, Config.LockpickSkillbar.inputs) 159 | elseif Config.LockpickSkillbar.type == 'qb-skillbar' then 160 | local p = promise.new() 161 | local Skillbar = exports['qb-skillbar']:GetSkillbarObject() 162 | 163 | Skillbar.Start({ 164 | duration = math.random(1000, 5000), -- how long the skillbar runs for 165 | pos = math.random(10, 30), -- how far to the right the static box is 166 | width = math.random(10, 20), -- how wide the static box is 167 | }, function() 168 | success = true 169 | p:resolve(success) 170 | end, function() 171 | success = false 172 | p:resolve(success) 173 | end) 174 | 175 | success = Citizen.Await(p) 176 | end 177 | end 178 | 179 | ClearPedTasks(playerPed) 180 | RemoveAnimDict(dict) 181 | 182 | if success and Config.LockpickSettings.startEngine then 183 | toggleEngine(Config.LockpickSettings.startEngineBypass) 184 | end 185 | else 186 | if Config.LockpickSettings.startEngine then 187 | toggleEngine(Config.LockpickSettings.startEngineBypass) 188 | end 189 | end 190 | end 191 | exports('toggleLockpick', toggleLockpick) 192 | exports('toggleHotwire', toggleLockpick) -- Support for old Versions 193 | RegisterNetEvent('msk_enginetoggle:toggleLockpick', toggleLockpick) 194 | 195 | RegisterNetEvent('msk_enginetoggle:installAlarmStage', function(stage) 196 | if not IsPedInAnyVehicle(MSK.Player.ped, false) then 197 | return Config.Notification(nil, Translation[Config.Locale]['sit_in_vehicle'], 'error') 198 | end 199 | 200 | local vehicle = MSK.Player.vehicle 201 | local plate = GetVehicleNumberPlateText(vehicle) 202 | 203 | Config.progressBar(1000 * 15, Translation[Config.Locale]['install_alarm']) 204 | Wait(1000 * 15) 205 | 206 | TriggerServerEvent('msk_enginetoggle:saveAlarmStage', plate, stage) 207 | end) 208 | 209 | RegisterNetEvent('msk_enginetoggle:showBlipCoords', function(coords) 210 | local blip = AddBlipForCoord(coords.x, coords.y, coords.z) 211 | 212 | SetBlipSprite(blip, 326) 213 | SetBlipDisplay(blip, 2) 214 | SetBlipColour(blip, 1) 215 | SetBlipScale(blip, 1.0) 216 | SetBlipFlashes(blip, true) 217 | 218 | SetTimeout(1000 * 60, function() 219 | RemoveBlip(blip) 220 | end) 221 | end) 222 | 223 | inOneSync = function(netId) 224 | local vehicle = NetworkDoesNetworkIdExist(netId) and NetworkGetEntityFromNetworkId(netId) 225 | 226 | if DoesEntityExist(vehicle) then 227 | return {vehicle = vehicle} 228 | end 229 | return false 230 | end 231 | 232 | local activeBlips = {} 233 | 234 | deleteVehicleBlip = function(netId) 235 | if not activeBlips[netId] then return end 236 | RemoveBlip(activeBlips[netId].blip) 237 | activeBlips[netId] = nil 238 | end 239 | RegisterNetEvent('msk_enginetoggle:deleteVehicleBlip', deleteVehicleBlip) 240 | 241 | addVehicleBlip = function(netId, coords) 242 | local blip = AddBlipForCoord(coords.x, coords.y, coords.z) 243 | 244 | SetBlipSprite(blip, 326) 245 | SetBlipDisplay(blip, 2) 246 | SetBlipColour(blip, 1) 247 | SetBlipScale(blip, 1.0) 248 | SetBlipFlashes(blip, true) 249 | SetBlipAsShortRange(blip, false) 250 | 251 | BeginTextCommandSetBlipName('STRING') 252 | AddTextComponentString(Translation[Config.Locale]['blip_stolen_vehicle']) 253 | EndTextCommandSetBlipName(blip) 254 | 255 | activeBlips[netId] = {isActive = false, blip = blip} 256 | end 257 | 258 | showVehicleBlip = function(netId, coords) 259 | if not activeBlips[netId] then addVehicleBlip(netId, coords) end 260 | local OneSync = inOneSync(netId) 261 | 262 | if OneSync and activeBlips[netId] and not activeBlips[netId].isActive then 263 | CreateThread(function() 264 | activeBlips[netId].isActive = true 265 | 266 | while activeBlips[netId] and activeBlips[netId].isActive and DoesEntityExist(OneSync.vehicle) do 267 | local vehicleCoords = GetEntityCoords(OneSync.vehicle) 268 | local heading = math.ceil(GetEntityHeading(OneSync.vehicle)) 269 | 270 | SetBlipCoords(activeBlips[netId].blip, vehicleCoords.x, vehicleCoords.y, vehicleCoords.z) 271 | ShowHeadingIndicatorOnBlip(activeBlips[netId].blip, true) 272 | SetBlipRotation(activeBlips[netId].blip, heading) 273 | 274 | Wait(0) 275 | end 276 | end) 277 | elseif not OneSync and activeBlips[netId] then 278 | activeBlips[netId].isActive = false 279 | SetBlipCoords(activeBlips[netId].blip, coords.x, coords.y, coords.z) 280 | ShowHeadingIndicatorOnBlip(activeBlips[netId].blip, false) 281 | end 282 | 283 | SetTimeout(2500, function() 284 | if not activeBlips[netId] then return end 285 | showVehicleBlip(netId, coords) 286 | end) 287 | end 288 | RegisterNetEvent('msk_enginetoggle:showVehicleBlip', showVehicleBlip) -------------------------------------------------------------------------------- /client/main.lua: -------------------------------------------------------------------------------- 1 | if Config.Framework == 'AUTO' then 2 | if GetResourceState('es_extended') ~= 'missing' then 3 | ESX = exports["es_extended"]:getSharedObject() 4 | elseif GetResourceState('qb-core') ~= 'missing' then 5 | QBCore = exports['qb-core']:GetCoreObject() 6 | end 7 | elseif Config.Framework == 'ESX' then 8 | ESX = exports["es_extended"]:getSharedObject() 9 | elseif Config.Framework == 'QBCore' then 10 | QBCore = exports['qb-core']:GetCoreObject() 11 | else 12 | -- Add your own code here 13 | end 14 | 15 | currentVehicle = {} 16 | isInVehicle, isEnteringVehicle, disabledDrive = false, false, false 17 | 18 | if Config.Command.enable then 19 | RegisterCommand(Config.Command.command, function(source, args, raw) 20 | toggleEngine() 21 | end) 22 | 23 | if Config.Hotkey.enable then 24 | RegisterKeyMapping(Config.Command.command, 'Toggle Engine', 'keyboard', Config.Hotkey.key) 25 | end 26 | end 27 | 28 | toggleEngine = function(bypass) 29 | local playerPed = MSK.Player.ped 30 | local canToggleEngine = true 31 | 32 | if not IsPedInAnyVehicle(playerPed) then return end 33 | local vehicle = MSK.Player.vehicle 34 | 35 | if not Config.EngineFromSecondSeat and GetPedInVehicleSeat(vehicle, -1) ~= playerPed then return end 36 | 37 | if Config.EngineFromSecondSeat then 38 | if IsVehicleSeatFree(vehicle, -1) then return end 39 | 40 | if playerPed ~= GetPedInVehicleSeat(vehicle, -1) and playerPed ~= GetPedInVehicleSeat(vehicle, 0) then 41 | return 42 | end 43 | end 44 | 45 | if GetVehicleDamaged(vehicle) then 46 | return Config.Notification(nil, Translation[Config.Locale]['veh_is_damaged'], 'error') 47 | end 48 | 49 | if IsAnyWheelClamped(vehicle) then 50 | return Config.Notification(nil, Translation[Config.Locale]['vehicle_wheel_clamped'], 'error') 51 | end 52 | 53 | -- Cheat protection, remove this if you don't care 54 | if bypass then 55 | if not MSK.IsAceAllowed(Config.AdminCommand.command) then 56 | return Config.Notification(nil, 'You don\'t have permission to bypass the engine start/stop!', 'error') 57 | end 58 | end 59 | -- Cheat protection, remove this if you don't care 60 | 61 | if not bypass then 62 | local isBlacklisted = IsVehicleBlacklisted(vehicle) 63 | 64 | if isBlacklisted then 65 | return -- Just return without any info 66 | end 67 | 68 | local isWhitelisted = IsVehicleWhitelisted(vehicle) 69 | 70 | if not isWhitelisted then 71 | canToggleEngine = getIsKeyOwner(vehicle) 72 | end 73 | end 74 | 75 | if not canToggleEngine then 76 | return Config.Notification(nil, Translation[Config.Locale]['key_nokey'], 'error') 77 | end 78 | 79 | local isEngineOn = GetIsVehicleEngineRunning(vehicle) 80 | SetEngineState(vehicle, not isEngineOn, true) 81 | 82 | if isEngineOn then 83 | CreateThread(disableDrive) 84 | Config.Notification(nil, Translation[Config.Locale]['engine_stop'], 'success') 85 | else 86 | disabledDrive = false 87 | Config.Notification(nil, Translation[Config.Locale]['engine_start'], 'success') 88 | end 89 | 90 | TriggerEvent('msk_enginetoggle:toggledEngine', vehicle, not isEngineOn) 91 | TriggerServerEvent('msk_enginetoggle:toggledEngine', VehToNet(vehicle), not isEngineOn) 92 | end 93 | exports('toggleEngine', toggleEngine) 94 | RegisterNetEvent('msk_enginetoggle:toggleEngine', toggleEngine) 95 | 96 | AddEventHandler('msk_enginetoggle:enteringVehicle', function(vehicle, plate, seat, netId, isEngineOn, isDamaged) 97 | logging('debug', 'enteringVehicle', vehicle, plate, seat, netId, isEngineOn, isDamaged) 98 | local playerPed = MSK.Player.ped 99 | local vehicleModel = GetEntityModel(vehicle) 100 | 101 | if seat == -1 and not isEngineOn then 102 | if not Config.EngineOnAtEnter then 103 | SetEngineState(vehicle, false, true) 104 | CreateThread(disableDrive) 105 | end 106 | elseif seat == -1 and isEngineOn and (IsThisModelAHeli(vehicleModel) or IsThisModelAPlane(vehicleModel)) then 107 | SetEngineState(vehicle, true, true) 108 | SetHeliBladesFullSpeed(vehicle) 109 | end 110 | end) 111 | 112 | AddEventHandler('msk_enginetoggle:enteredVehicle', function(vehicle, plate, seat, netId, isEngineOn, isDamaged) 113 | logging('debug', 'enteredVehicle', vehicle, plate, seat, netId, isEngineOn, isDamaged) 114 | local playerPed = MSK.Player.ped 115 | local vehicleModel = GetEntityModel(vehicle) 116 | 117 | if seat == -1 and not isEngineOn then 118 | if not Config.EngineOnAtEnter then 119 | SetEngineState(vehicle, false, true) 120 | CreateThread(disableDrive) 121 | else 122 | SetEngineState(vehicle, true, true) 123 | end 124 | elseif seat == -1 and isEngineOn and (IsThisModelAHeli(vehicleModel) or IsThisModelAPlane(vehicleModel)) then 125 | SetEngineState(vehicle, true, true) 126 | SetHeliBladesFullSpeed(vehicle) 127 | end 128 | end) 129 | 130 | AddEventHandler('msk_enginetoggle:exitedVehicle', function(vehicle, plate, seat, netId, isEngineOn, isDamaged) 131 | logging('debug', 'exitedVehicle', vehicle, plate, seat, netId, isEngineOn, isDamaged) 132 | if not vehicle or not DoesEntityExist(vehicle) then return end 133 | local playerPed = MSK.Player.ped 134 | local vehicleModel = GetEntityModel(vehicle) 135 | 136 | if seat == -1 and not isEngineOn then 137 | SetEngineState(vehicle, false, true) 138 | end 139 | end) 140 | 141 | CreateThread(function() 142 | while true do 143 | local sleep = 500 144 | local playerPed = MSK.Player.ped 145 | local vehiclePool = GetGamePool('CVehicle') 146 | 147 | for i = 1, #vehiclePool do 148 | local vehicle = vehiclePool[i] 149 | 150 | if DoesEntityExist(vehicle) and not GetVehicleDamaged(vehicle) and IsVehicleSeatFree(vehicle, -1) and (not IsPedInAnyVehicle(playerPed, false) or (IsPedInAnyVehicle(playerPed, false) and vehicle ~= GetVehiclePedIsIn(playerPed, false))) then 151 | local vehicleModel = GetEntityModel(vehicle) 152 | 153 | if IsThisModelACar(vehicleModel) then 154 | local steeringAngle = GetSteeringAngle(vehicle) 155 | 156 | if steeringAngle and steeringAngle ~= GetVehicleSteeringAngle(vehicle) then 157 | SetSteeringAngle(vehicle, steeringAngle) 158 | end 159 | end 160 | 161 | if IsThisModelAHeli(vehicleModel) or IsThisModelAPlane(vehicleModel) then 162 | if GetEngineState(vehicle) then 163 | SetEngineState(vehicle, true, true) 164 | SetHeliBladesFullSpeed(vehicle) 165 | end 166 | end 167 | end 168 | end 169 | 170 | Wait(sleep) 171 | end 172 | end) 173 | 174 | -- Credits to ESX Legacy (https://github.com/esx-framework/esx_core/blob/main/%5Bcore%5D/es_extended/client/modules/actions.lua) 175 | CreateThread(function() 176 | while true do 177 | local sleep = 200 178 | local playerPed = MSK.Player.ped 179 | 180 | if not isInVehicle and not IsPlayerDead(PlayerId()) then 181 | if DoesEntityExist(GetVehiclePedIsTryingToEnter(playerPed)) and not isEnteringVehicle then 182 | local vehicle = GetVehiclePedIsTryingToEnter(playerPed) 183 | local plate = GetVehicleNumberPlateText(vehicle) 184 | local seat = GetSeatPedIsTryingToEnter(playerPed) 185 | local netId = VehToNet(vehicle) 186 | local isEngineOn = GetEngineState(vehicle) 187 | local isDamaged = GetVehicleDamaged(vehicle) 188 | isEnteringVehicle = true 189 | TriggerEvent('msk_enginetoggle:enteringVehicle', vehicle, plate, seat, netId, isEngineOn, isDamaged) 190 | TriggerServerEvent('msk_enginetoggle:enteringVehicle', plate, seat, netId, isEngineOn, isDamaged) 191 | elseif not DoesEntityExist(GetVehiclePedIsTryingToEnter(playerPed)) and not IsPedInAnyVehicle(playerPed, true) and isEnteringVehicle then 192 | TriggerEvent('msk_enginetoggle:enteringVehicleAborted') 193 | TriggerServerEvent('msk_enginetoggle:enteringVehicleAborted') 194 | isEnteringVehicle = false 195 | elseif IsPedInAnyVehicle(playerPed, false) then 196 | isEnteringVehicle = false 197 | isInVehicle = true 198 | currentVehicle.vehicle = GetVehiclePedIsIn(playerPed, false) 199 | currentVehicle.plate = GetVehicleNumberPlateText(currentVehicle.vehicle) 200 | currentVehicle.seat = GetPedVehicleSeat(playerPed, currentVehicle.vehicle) 201 | currentVehicle.netId = VehToNet(currentVehicle.vehicle) 202 | currentVehicle.isEngineOn = GetEngineState(currentVehicle.vehicle) 203 | currentVehicle.isDamaged = GetVehicleDamaged(currentVehicle.vehicle) 204 | TriggerEvent('msk_enginetoggle:enteredVehicle', currentVehicle.vehicle, currentVehicle.plate, currentVehicle.seat, currentVehicle.netId, currentVehicle.isEngineOn, currentVehicle.isDamaged) 205 | TriggerServerEvent('msk_enginetoggle:enteredVehicle', currentVehicle.plate, currentVehicle.seat, currentVehicle.netId, currentVehicle.isEngineOn, currentVehicle.isDamaged) 206 | end 207 | elseif isInVehicle then 208 | if not IsPedInAnyVehicle(playerPed, false) or IsPlayerDead(PlayerId()) then 209 | isInVehicle = false 210 | TriggerEvent('msk_enginetoggle:exitedVehicle', currentVehicle.vehicle, currentVehicle.plate, currentVehicle.seat, currentVehicle.netId, currentVehicle.isEngineOn, currentVehicle.isDamaged) 211 | TriggerServerEvent('msk_enginetoggle:exitedVehicle', currentVehicle.plate, currentVehicle.seat, currentVehicle.netId, currentVehicle.isEngineOn, currentVehicle.isDamaged) 212 | currentVehicle = {} 213 | end 214 | end 215 | 216 | Wait(sleep) 217 | end 218 | end) 219 | 220 | SetEngineState = function(vehicle, state, engine) 221 | assert(vehicle and DoesEntityExist(vehicle), 'Parameter "vehicle" is nil or the Vehicle does not exist on function SetEngineState') 222 | logging('debug', 'SetEngineState', vehicle, state) 223 | 224 | currentVehicle.isEngineOn = state 225 | Entity(vehicle).state:set('isEngineOn', state, true) 226 | 227 | SetVehicleUndriveable(vehicle, not state) 228 | SetVehicleKeepEngineOnWhenAbandoned(vehicle, state) 229 | 230 | if state then 231 | SetSteeringAngle(vehicle, 0.0) 232 | end 233 | 234 | if not engine then return end 235 | SetVehicleEngineOn(vehicle, state, false, true) 236 | end 237 | exports('SetEngineState', SetEngineState) -- Do not use this Export if you don't know what you are doing!!! 238 | RegisterNetEvent('msk_enginetoggle:setEngineState', SetEngineState) -- Do not use this Event if you don't know what you are doing!!! 239 | 240 | GetEngineState = function(vehicle) 241 | if not vehicle then vehicle = MSK.Player.vehicle end 242 | assert(vehicle and DoesEntityExist(vehicle), 'Parameter "vehicle" is nil or the Vehicle does not exist on function GetEngineState') 243 | 244 | if Entity(vehicle).state.isEngineOn == nil then 245 | SetEngineState(vehicle, GetIsVehicleEngineRunning(vehicle), false) 246 | end 247 | return Entity(vehicle).state.isEngineOn 248 | end 249 | exports('GetEngineState', GetEngineState) 250 | 251 | SetVehicleDamaged = function(vehicle, state) 252 | assert(vehicle and DoesEntityExist(vehicle), 'Parameter "vehicle" is nil or the Vehicle does not exist on function SetVehicleDamaged') 253 | 254 | currentVehicle.isDamaged = state 255 | Entity(vehicle).state:set('isDamaged', state, true) 256 | 257 | if state then 258 | SetEngineState(vehicle, false, true) 259 | 260 | if IsPedInAnyVehicle(MSK.Player.ped) then 261 | if vehicle == MSK.Player.vehicle then 262 | CreateThread(disableDrive) 263 | end 264 | end 265 | end 266 | end 267 | exports('SetVehicleDamaged', SetVehicleDamaged) 268 | RegisterNetEvent('msk_enginetoggle:setVehicleDamaged', SetVehicleDamaged) 269 | 270 | GetVehicleDamaged = function(vehicle) 271 | if not vehicle then vehicle = MSK.Player.vehicle end 272 | assert(vehicle and DoesEntityExist(vehicle), 'Parameter "vehicle" is nil or the Vehicle does not exist on function GetVehicleDamaged') 273 | 274 | if Entity(vehicle).state.isDamaged == nil then 275 | SetVehicleDamaged(vehicle, false) 276 | end 277 | return Entity(vehicle).state.isDamaged 278 | end 279 | exports('GetVehicleDamaged', GetVehicleDamaged) 280 | 281 | disableDrive = function() 282 | if disabledDrive then return end 283 | disabledDrive = true 284 | 285 | while isInVehicle and disabledDrive and MSK.Player.seat == -1 and not currentVehicle.isEngineOn do 286 | local sleep = 1 287 | 288 | DisableControlAction(0, 71, true) -- W (accelerate) 289 | DisableControlAction(0, 72, true) -- S (brake/reverse) 290 | 291 | if currentVehicle.vehicle and DoesEntityExist(currentVehicle.vehicle) then 292 | SetVehicleUndriveable(currentVehicle.vehicle, true) 293 | end 294 | 295 | Wait(sleep) 296 | end 297 | 298 | disabledDrive = false 299 | end 300 | 301 | logging = function(code, ...) 302 | if not Config.Debug then return end 303 | MSK.Logging(code, ...) 304 | end -------------------------------------------------------------------------------- /client/steeringwheel.lua: -------------------------------------------------------------------------------- 1 | if Config.SaveSteeringAngle then 2 | CreateThread(function() 3 | while true do 4 | local sleep = 500 5 | 6 | if isInVehicle and MSK.Player.seat == -1 then 7 | sleep = 1 8 | 9 | if IsControlJustPressed(0, Config.SaveAngleOnExit) then 10 | local vehicle = currentVehicle and currentVehicle.vehicle or MSK.Player.vehicle 11 | local steeringAngle = GetVehicleSteeringAngle(vehicle) 12 | 13 | while not IsControlJustReleased(0, Config.SaveAngleOnExit) do 14 | SetSteeringAngle(vehicle, steeringAngle) 15 | break 16 | end 17 | end 18 | end 19 | 20 | Wait(sleep) 21 | end 22 | end) 23 | end 24 | 25 | SetSteeringAngle = function(vehicle, angle) 26 | assert(vehicle and DoesEntityExist(vehicle), 'Parameter "vehicle" is nil or the Vehicle does not exist on function SetSteeringAngle') 27 | 28 | Entity(vehicle).state:set('SteeringAngle', angle, true) 29 | 30 | if angle and angle ~= 0.0 then 31 | SetVehicleSteeringAngle(vehicle, angle) 32 | end 33 | end 34 | exports('SetSteeringAngle', SetSteeringAngle) 35 | 36 | GetSteeringAngle = function(vehicle) 37 | if not vehicle then vehicle = MSK.Player.vehicle end 38 | assert(vehicle and DoesEntityExist(vehicle), 'Parameter "vehicle" is nil or the Vehicle does not exist on function GetSteeringAngle') 39 | 40 | if Entity(vehicle).state.SteeringAngle == nil then 41 | SetSteeringAngle(vehicle, GetVehicleSteeringAngle(vehicle)) 42 | end 43 | 44 | return Entity(vehicle).state.SteeringAngle 45 | end 46 | exports('GetSteeringAngle', GetSteeringAngle) -------------------------------------------------------------------------------- /client/utils.lua: -------------------------------------------------------------------------------- 1 | GetPedVehicleSeat = function(playerPed, vehicle) 2 | if not playerPed then playerPed = MSK.Player.ped end 3 | if not vehicle then vehicle = currentVehicle and currentVehicle.vehicle or MSK.Player.vehicle or GetVehiclePedIsIn(playerPed, false) end 4 | if not vehicle or not DoesEntityExist(vehicle) then return end 5 | 6 | if vehicle == MSK.Player.vehicle then 7 | return MSK.Player.seat 8 | end 9 | 10 | for i = -1, 16 do 11 | if (GetPedInVehicleSeat(vehicle, i) == playerPed) then 12 | return i 13 | end 14 | end 15 | 16 | return -1 17 | end 18 | 19 | IsVehicleWhitelisted = function(vehicle) 20 | local vehicleClass = GetVehicleClass(vehicle) 21 | 22 | for k, class in pairs(Config.Whitelist.classes) do 23 | if vehicleClass == class then 24 | return true 25 | end 26 | end 27 | 28 | local vehicleModel = GetEntityModel(vehicle) 29 | 30 | for k, model in pairs(Config.Whitelist.vehicles) do 31 | local modelHash = type(model) == 'number' and model or GetHashKey(model) 32 | 33 | if vehicleModel == modelHash then 34 | return true 35 | end 36 | end 37 | 38 | local vehiclePlate = GetVehicleNumberPlateText(vehicle) 39 | 40 | for k, plate in pairs(Config.Whitelist.plates) do 41 | if string.find(MSK.String.Trim(vehiclePlate, true), MSK.String.Trim(plate, true)) then 42 | return true 43 | end 44 | end 45 | end 46 | 47 | IsVehicleBlacklisted = function(vehicle) 48 | local vehicleClass = GetVehicleClass(vehicle) 49 | 50 | for k, class in pairs(Config.Blacklist.classes) do 51 | if vehicleClass == class then 52 | return true 53 | end 54 | end 55 | 56 | local vehicleModel = GetEntityModel(vehicle) 57 | 58 | for k, model in pairs(Config.Blacklist.vehicles) do 59 | local modelHash = type(model) == 'number' and model or GetHashKey(model) 60 | 61 | if vehicleModel == modelHash then 62 | return true 63 | end 64 | end 65 | 66 | local vehiclePlate = GetVehicleNumberPlateText(vehicle) 67 | 68 | for k, plate in pairs(Config.Blacklist.plates) do 69 | if string.find(MSK.String.Trim(vehiclePlate, true), MSK.String.Trim(plate, true)) then 70 | return true 71 | end 72 | end 73 | end 74 | 75 | IsAnyWheelClamped = function(vehicle) 76 | if not Config.VehicleClamp or GetResourceState('VehicleClamp') ~= 'started' then 77 | return false 78 | end 79 | 80 | return exports["VehicleClamp"]:IsAnyWheelClamped(vehicle) 81 | end -------------------------------------------------------------------------------- /client/vehiclekeys.lua: -------------------------------------------------------------------------------- 1 | getInventory = function() 2 | if (GetResourceState("ox_inventory") == "started") then 3 | return 'ox_inventory' 4 | elseif (GetResourceState("qs-inventory") == "started") then 5 | return 'qs-inventory' 6 | elseif (GetResourceState("core_inventory") == "started") then 7 | return 'core_inventory' 8 | end 9 | 10 | return false 11 | end 12 | 13 | getKeyFromInventory = function(plate) 14 | plate = MSK.String.Trim(plate, true) 15 | local inv = getInventory() 16 | 17 | if inv == 'ox_inventory' then 18 | local inventory = exports.ox_inventory:GetPlayerItems() 19 | 20 | for k, v in pairs(inventory) do 21 | if v.name == Config.VehicleKeys.item and MSK.String.Trim(v.metadata.plate or v.metadata.Plate or '', true) == plate then 22 | return true 23 | end 24 | end 25 | elseif inv == 'qs-inventory' then 26 | local inventory = exports['qs-inventory']:getUserInventory() 27 | 28 | for k, v in pairs(inventory) do 29 | if v.name == Config.VehicleKeys.item and MSK.String.Trim(v.info.plate or v.info.Plate or '', true) == plate then 30 | return true 31 | end 32 | end 33 | elseif inv == 'core_inventory' then 34 | local inventory = MSK.Trigger('msk_enginetoggle:getInventory', 'core_inventory') 35 | 36 | for k, v in pairs(inventory) do 37 | if v.name == Config.VehicleKeys.item and MSK.String.Trim(v.metadata.plate or v.metadata.Plate or '', true) == plate then 38 | return true 39 | end 40 | end 41 | else 42 | -- Add your own code here 43 | end 44 | 45 | return false 46 | end 47 | exports('getKeyFromInventory', getKeyFromInventory) 48 | 49 | getIsKeyOwner = function(vehicle) 50 | if not Config.VehicleKeys.enable then return true end 51 | local plate = GetVehicleNumberPlateText(vehicle) 52 | local isKeyOwner = getKeyFromInventory(plate) 53 | 54 | if not isKeyOwner then 55 | if Config.VehicleKeys.script == 'msk_vehiclekeys' and (GetResourceState("msk_vehiclekeys") == "started") then 56 | isKeyOwner = exports["msk_vehiclekeys"]:HasPlayerKeyOrIsVehicleOwner(vehicle) 57 | elseif Config.VehicleKeys.script == 'VehicleKeyChain' and (GetResourceState("VehicleKeyChain") == "started") then 58 | isKeyOwner = exports["VehicleKeyChain"]:IsVehicleOrKeyOwner(vehicle) 59 | elseif Config.VehicleKeys.script == 'vehicles_keys' and (GetResourceState("vehicles_keys") == "started") then 60 | isKeyOwner = exports["vehicles_keys"]:doesPlayerOwnPlate(plate) 61 | elseif Config.VehicleKeys.script == 'wasabi_carlock' and (GetResourceState("wasabi_carlock") == "started") then 62 | isKeyOwner = exports.wasabi_carlock:HasKey(plate) 63 | elseif Config.VehicleKeys.script == 'qs-vehiclekeys' and (GetResourceState("qs-vehiclekeys") == "started") then 64 | isKeyOwner = exports['qs-vehiclekeys']:GetKey(plate) 65 | else 66 | -- Add your own code here 67 | end 68 | end 69 | 70 | return isKeyOwner 71 | end 72 | exports('getIsKeyOwner', getIsKeyOwner) -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | Config = {} 2 | ---------------------------------------------------------------- 3 | Config.Locale = 'de' 4 | Config.Debug = true 5 | Config.VersionChecker = true 6 | ---------------------------------------------------------------- 7 | -- Supported Frameworks: AUTO, ESX, QBCore 8 | Config.Framework = 'AUTO' 9 | ---------------------------------------------------------------- 10 | -- !!! This function is clientside AND serverside !!! 11 | Config.Notification = function(source, message, typ) 12 | if IsDuplicityVersion() then -- serverside 13 | MSK.Notification(source, 'Engine', message, typ) 14 | else -- clientside 15 | MSK.Notification('Engine', message, typ) 16 | end 17 | end 18 | ---------------------------------------------------------------- 19 | Config.Command = { 20 | enable = true, -- If you set to false then the Hotkey won't work !!! 21 | command = 'engine' 22 | } 23 | 24 | Config.Hotkey = { 25 | enable = true, -- Set false if you don't want to use a Hotkey 26 | key = 'M' 27 | } 28 | 29 | Config.AdminCommand = { 30 | enable = true, -- Start/Stop Engine if you don't have a key for that vehicle 31 | command = 'adengine', 32 | groups = {'superadmin', 'admin'} 33 | } 34 | 35 | Config.EngineOnAtEnter = false -- Set to true to toggle the engine automatically on when entering a vehicle 36 | 37 | -- Set to true to start the engine from the second seat (Co-Driver) 38 | -- Someone has to be on the Driver Seat, otherwise it won't work! 39 | -- If VehicleKeys is activated, the Co-Driver needs a key. 40 | Config.EngineFromSecondSeat = false 41 | ---------------------------------------------------------------- 42 | -- Vehicle Key System - set true then only the Owner of the Vehicle or someone with a Key can start the Engine 43 | 44 | -- msk_vehiclekeys: https://forum.cfx.re/t/esx-qbcore-msk-vehiclekeys-unique-items/5264475 45 | -- vehicles_keys: https://forum.cfx.re/t/esx-qbcore-vehicles-keys-vehicles-lock-remote-control-ui-and-much-more/4857274 46 | -- VehicleKeyChain: https://forum.cfx.re/t/release-vehicle-key-chain-v4-1-4-esx-qb/3319563 47 | 48 | Config.VehicleKeys = { 49 | enable = true, -- Set true to enable this feature 50 | 51 | -- Supported Scripts: 'msk_vehiclekeys', 'VehicleKeyChain', 'vehicles_keys', 'okokGarage', 'wasabi_carlock', 'qs-vehiclekeys' 52 | script = 'msk_vehiclekeys', 53 | 54 | -- For uniqueItems in ox_inventory, qs-inventory or core_inventory 55 | item = 'keys', -- Item in your inventory for vehicle keys 56 | } 57 | ---------------------------------------------------------------- 58 | Config.VehicleClamp = GetResourceState('VehicleClamp') ~= 'missing' 59 | ---------------------------------------------------------------- 60 | Config.SaveSteeringAngle = true 61 | Config.SaveAngleOnExit = 75 -- default: F - 75 (Exit Vehicle) 62 | ---------------------------------------------------------------- 63 | -- With this feature you can set vehicles and plates for which you don't need a key to start the engine 64 | -- either exact plates or just a string that should be in the vehicles plate e.g. "ESX" will ignore te plate "ESX1234" too 65 | Config.Whitelist = { 66 | classes = { 67 | 68 | }, 69 | vehicles = { 70 | -- Please use `` and NOT '' or "" 71 | `caddy`, `caddy2`, `caddy3`, `airtug`, `docktug`, `forklift`, `mower`, `tractor2`, 72 | }, 73 | plates = { 74 | "ESX", "MSK", "Test", 75 | }, 76 | } 77 | 78 | Config.Blacklist = { 79 | classes = { 80 | 13, 21, 81 | }, 82 | vehicles = { 83 | -- Please use `` and NOT '' or "" 84 | `bmx`, `cruiser`, `fixter`, `scorcher`, `tribike`, `tribike2`, `tribike3`, 85 | }, 86 | plates = { 87 | "ESX2", "MSK2", "Test2", 88 | }, 89 | } 90 | ---------------------------------------------------------------- 91 | Config.EnableLockpick = true -- Set false if you want to deactivate this feature 92 | 93 | Config.progressBar = function(time, message) 94 | MSK.Progress.Start(time, message) 95 | end 96 | 97 | Config.LockpickHotkey = { 98 | enable = false, -- Set to true if you want to use a Hotkey 99 | command = 'lockpickvehicle', 100 | key = 'N' 101 | } 102 | 103 | Config.PoliceAlert = {'police', 'sheriff', 'fib'} 104 | 105 | Config.SafetyStages = { 106 | -- Do NOT rename the stages! Only change the options! 107 | -- On deafult 'stage_1' is installed on every owned vehicle 108 | 109 | ['stage_1'] = { 110 | item = 'vehicle_alarm_1', -- Usable Item to set the stage to the vehicle 111 | alarm = true, -- Acustic alarm 112 | ownerAlert = false, -- Notify Owner 113 | policeAlert = false, -- Notify Police 114 | liveCoords = false, -- Owner gets live coords (Blip) 115 | }, 116 | ['stage_2'] = { 117 | item = 'vehicle_alarm_2', -- Usable Item to set the stage to the vehicle 118 | alarm = true, -- Acustic alarm 119 | ownerAlert = true, -- Notify Owner 120 | policeAlert = false, -- Notify Police 121 | liveCoords = false, -- Owner gets live coords (Blip) 122 | }, 123 | ['stage_3'] = { 124 | item = 'vehicle_alarm_3', -- Usable Item to set the stage to the vehicle 125 | alarm = true, -- Acustic alarm 126 | ownerAlert = true, -- Notify Owner 127 | policeAlert = true, -- Notify Police 128 | liveCoords = false, -- Owner gets live coords (Blip) 129 | }, 130 | ['stage_4'] = { 131 | item = 'vehicle_alarm_4', -- Usable Item to set the stage to the vehicle 132 | alarm = true, -- Acustic alarm 133 | ownerAlert = true, -- Notify Owner 134 | policeAlert = true, -- Notify Police 135 | liveCoords = true, -- Owner gets live coords (Blip) 136 | }, 137 | } 138 | 139 | Config.LockpickSettings = { 140 | item = 'lockpick', -- Set the usable item that you want to use 141 | removeItem = true, -- Set true if you like to remove item after failing lockpicking 142 | 143 | startEngine = true, -- Set true if you want to start the engine after successfull lockpicking 144 | startEngineBypass = false, -- Set true if you want to start the engine always even if the player hasn't found the key 145 | 146 | -- If you set to 'skillbar' then there won't be a progressbar' 147 | -- If you set to 'progressbar' then there won't be a skillbar 148 | action = 'skillbar', -- Set to 'skillbar' or 'progressbar' 149 | 150 | -- If Config.VehicleKeys is activated then the player is always searching for the key 151 | enableSearchKey = true, -- Set false if you dont want this 152 | searchKey = 66 -- default: 66% // Probability to find the key 153 | } 154 | 155 | Config.LockpickProgessbar = { 156 | time = 10, -- In seconds // Time how long does it takes 157 | lockpick = 66, -- default: 66% // Probability successfully lockpick the vehicle 158 | } 159 | 160 | Config.LockpickSkillbar = { 161 | type = 'ox_lib', -- 'ox_lib' or 'qb-skillbar' 162 | 163 | -- This is only if you set to 'ox_lib' 164 | inputs = {'w', 'a', 's', 'd'}, 165 | difficulty = { 166 | -- Presets: 167 | -- 'easy' -> { areaSize: 50, speedMultiplier: 1 } 168 | -- 'medium' -> { areaSize: 40, speedMultiplier: 1.5 } 169 | -- 'hard' -> { areaSize: 25, speedMultiplier: 1.75 } 170 | -- You can also use your own type: 171 | -- Example: {areaSize = 60, speedMultiplier = 1} 172 | 173 | ['1'] = 'easy', -- 'easy', 'medium', 'hard' 174 | ['2'] = 'easy', -- 'easy', 'medium', 'hard' 175 | ['3'] = {areaSize = 60, speedMultiplier = 1}, -- 'easy', 'medium', 'hard' 176 | ['4'] = 'easy', -- 'easy', 'medium', 'hard' 177 | } 178 | } 179 | 180 | Config.Animation = { 181 | lockpick = { -- Animation for lockpicking 182 | dict = 'anim@amb@clubhouse@tutorial@bkr_tut_ig3@', 183 | anim = 'machinic_loop_mechandplayer' 184 | }, 185 | searchKey = { -- Animation for search key 186 | dict = 'veh@plane@velum@front@ds@base', 187 | anim = 'hotwire', 188 | time = 8, -- in seconds // How long does it take to search for the key 189 | enableProgressbar = true 190 | }, 191 | hotwire = { -- Animation for hotwire 192 | dict = 'veh@forklift@base', 193 | anim = 'hotwire', 194 | action = 'skillbar', -- Set to 'skillbar' or 'progressbar' 195 | time = 15, -- in seconds // How long does it take to hotwire the vehicle // Only for 'progressbar' 196 | } 197 | } 198 | ---------------------------------------------------------------- 199 | exports('Config', function() 200 | return Config 201 | end) -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | games { 'gta5' } 3 | 4 | author 'Musiker15 - MSK Scripts' 5 | name 'msk_enginetoggle' 6 | description 'EngineToggle for Vehicles' 7 | version '4.3.4' 8 | 9 | lua54 'yes' 10 | 11 | shared_script { 12 | '@msk_core/import.lua', 13 | '@ox_lib/init.lua', 14 | 'config.lua', 15 | 'translation.lua' 16 | } 17 | 18 | client_scripts { 19 | 'client/**/*.*' 20 | } 21 | 22 | server_scripts { 23 | '@oxmysql/lib/MySQL.lua', 24 | 'server/**/*.*' 25 | } 26 | 27 | dependencies { 28 | 'oxmysql', 29 | 'ox_lib', 30 | 'msk_core', 31 | } -------------------------------------------------------------------------------- /server/hotwire.lua: -------------------------------------------------------------------------------- 1 | if Config.Framework == 'ESX' or Config.Framework == 'AUTO' and GetResourceState('es_extended') ~= 'missing' then 2 | if not ESX then 3 | ESX = exports["es_extended"]:getSharedObject() 4 | Config.Framework = 'ESX' 5 | end 6 | 7 | VEHICLE_TABLE_NAME = "owned_vehicles" 8 | OWNER_COLUMN_NAME = "owner" 9 | elseif Config.Framework == 'QBCore' or Config.Framework == 'AUTO' and GetResourceState('qb-core') ~= 'missing' then 10 | if not QBCore then 11 | QBCore = exports['qb-core']:GetCoreObject() 12 | Config.Framework = 'QBCore' 13 | end 14 | 15 | VEHICLE_TABLE_NAME = "player_vehicles" 16 | OWNER_COLUMN_NAME = "citizenid" 17 | else 18 | VEHICLE_TABLE_NAME = "" 19 | OWNER_COLUMN_NAME = "" 20 | end 21 | 22 | if Config.EnableLockpick then 23 | alterDatabase = function() 24 | MySQL.query.await(("ALTER TABLE %s ADD COLUMN IF NOT EXISTS `alarmStage` varchar(50) NOT NULL DEFAULT 'stage_1';"):format(VEHICLE_TABLE_NAME)) 25 | end 26 | alterDatabase() 27 | 28 | if Config.Framework == 'ESX' then 29 | ESX.RegisterUsableItem(Config.LockpickSettings.item, function(source) 30 | TriggerClientEvent('msk_enginetoggle:toggleLockpick', source) 31 | end) 32 | 33 | for stage, data in pairs(Config.SafetyStages) do 34 | ESX.RegisterUsableItem(data.item, function(source) 35 | TriggerClientEvent('msk_enginetoggle:installAlarmStage', source, stage) 36 | end) 37 | end 38 | elseif Config.Framework == 'QBCore' then 39 | QBCore.Functions.CreateUseableItem(Config.LockpickSettings.item, function(source) 40 | TriggerClientEvent('msk_enginetoggle:toggleLockpick', source) 41 | end) 42 | 43 | for stage, data in pairs(Config.SafetyStages) do 44 | QBCore.Functions.CreateUseableItem(data.item, function(source) 45 | TriggerClientEvent('msk_enginetoggle:installAlarmStage', source, stage) 46 | end) 47 | end 48 | else 49 | -- Add your own code here 50 | end 51 | end 52 | 53 | HasPlayerJob = function(Player) 54 | for i=1, #Config.PoliceAlert do 55 | if Config.PoliceAlert[i] == GetPlayerJob(Player) then 56 | return true 57 | end 58 | end 59 | return false 60 | end 61 | 62 | getAlarmStage = function(source, plate) 63 | local result = MySQL.query.await(('SELECT * FROM %s WHERE plate = @plate'):format(VEHICLE_TABLE_NAME), { 64 | ['@plate'] = MSK.String.Trim(plate) 65 | }) 66 | 67 | if result and result[1] then 68 | return result[1][OWNER_COLUMN_NAME], result[1].alarmStage 69 | end 70 | return nil, 'stage_1' 71 | end 72 | MSK.Register('msk_enginetoggle:getAlarmStage', getAlarmStage) 73 | 74 | RegisterNetEvent('msk_enginetoggle:removeLockpickItem', function() 75 | if not Config.LockpickSettings.removeItem then return end 76 | local src = source 77 | local Player = GetPlayerFromId(src) 78 | 79 | if Config.Framework == 'ESX' then 80 | Player.removeInventoryItem(Config.LockpickSettings.item, 1) 81 | elseif Config.Framework == 'QBCore' then 82 | Player.Functions.RemoveItem(Config.LockpickSettings.item, 1) 83 | else 84 | -- Add your own code here 85 | end 86 | end) 87 | 88 | RegisterNetEvent('msk_enginetoggle:saveAlarmStage', function(plate, stage) 89 | local playerId = source 90 | local Player = GetPlayerFromId(playerId) 91 | local identifier = nil 92 | 93 | if Config.Framework == 'ESX' then 94 | identifier = Player.identifier 95 | elseif Config.Framework == 'QBCore' then 96 | identifier = Player.PlayerData.citizenid 97 | else 98 | -- Add your own code here 99 | end 100 | 101 | local result = MySQL.query.await(('SELECT * FROM %s WHERE %s = @owner AND plate = @plate'):format(VEHICLE_TABLE_NAME, OWNER_COLUMN_NAME), { 102 | ['@owner'] = identifier, 103 | ['@plate'] = MSK.String.Trim(plate) 104 | }) 105 | 106 | if result and result[1] and result[1][OWNER_COLUMN_NAME] == identifier then 107 | MySQL.update(('UPDATE %s SET alarmStage = @alarmStage WHERE %s = @owner AND plate = @plate'):format(VEHICLE_TABLE_NAME, OWNER_COLUMN_NAME), { 108 | ['@alarmStage'] = stage, 109 | ['@owner'] = identifier, 110 | ['@plate'] = MSK.String.Trim(plate), 111 | }) 112 | else 113 | Config.Notification(playerId, Translation[Config.Locale]['not_vehicle_owner'], 'error') 114 | end 115 | end) 116 | 117 | RegisterNetEvent('msk_enginetoggle:ownerAlert', function(coords, owner) 118 | local playerId = nil 119 | local Player = GetPlayerFromIdentifier(owner) 120 | if not Player then return end 121 | 122 | if Config.Framework == 'ESX' then 123 | playerId = Player.source 124 | elseif Config.Framework == 'QBCore' then 125 | playerId = Player.PlayerData.source 126 | else 127 | -- Add your own code here 128 | end 129 | 130 | if not playerId then return end 131 | Config.Notification(playerId, Translation[Config.Locale]['stole_vehicle']) 132 | TriggerClientEvent('msk_enginetoggle:showBlipCoords', playerId, coords) 133 | end) 134 | 135 | RegisterNetEvent('msk_enginetoggle:policeAlert', function(coords) 136 | if Config.Framework == 'ESX' then 137 | local xPlayers = ESX.GetExtendedPlayers() 138 | 139 | for k, xPlayer in pairs(xPlayers) do 140 | if HasPlayerJob(xPlayer) then 141 | Config.Notification(xPlayer.source, Translation[Config.Locale]['stole_vehicle_police']) 142 | TriggerClientEvent('msk_enginetoggle:showBlipCoords', xPlayer.source, coords) 143 | end 144 | end 145 | elseif Config.Framework == 'QBCore' then 146 | local Players = QBCore.Functions.GetQBPlayers() 147 | 148 | for k, Player in pairs(Players) do 149 | if HasPlayerJob(Player) then 150 | Config.Notification(Player.PlayerData.source, Translation[Config.Locale]['stole_vehicle_police']) 151 | TriggerClientEvent('msk_enginetoggle:showBlipCoords', Player.PlayerData.source, coords) 152 | end 153 | end 154 | else 155 | -- Add your own code here 156 | end 157 | end) 158 | 159 | RegisterNetEvent('msk_enginetoggle:liveCoords', function(owner, netId, coords) 160 | local Player = GetPlayerFromIdentifier(owner) 161 | if not Player then return end 162 | local playerId = nil 163 | 164 | if Config.Framework == 'ESX' then 165 | playerId = Player.source 166 | elseif Config.Framework == 'QBCore' then 167 | playerId = Player.PlayerData.source 168 | else 169 | -- Add your own code here 170 | end 171 | 172 | if not playerId then return end 173 | TriggerClientEvent('msk_enginetoggle:showVehicleBlip', playerId, netId, coords) 174 | end) -------------------------------------------------------------------------------- /server/main.lua: -------------------------------------------------------------------------------- 1 | if Config.Framework == 'AUTO' then 2 | if GetResourceState('es_extended') ~= 'missing' then 3 | ESX = exports["es_extended"]:getSharedObject() 4 | Config.Framework = 'ESX' 5 | elseif GetResourceState('qb-core') ~= 'missing' then 6 | QBCore = exports['qb-core']:GetCoreObject() 7 | Config.Framework = 'QBCore' 8 | end 9 | elseif Config.Framework == 'ESX' then 10 | ESX = exports["es_extended"]:getSharedObject() 11 | elseif Config.Framework == 'QBCore' then 12 | QBCore = exports['qb-core']:GetCoreObject() 13 | else 14 | -- Add your own code here 15 | end 16 | 17 | GetPlayerFromId = function(playerId) 18 | local Player = nil 19 | 20 | if Config.Framework == 'ESX' then 21 | Player = ESX.GetPlayerFromId(playerId) 22 | elseif Config.Framework == 'QBCore' then 23 | Player = QBCore.Functions.GetPlayer(playerId) 24 | else 25 | -- Add your own code here 26 | end 27 | 28 | return Player 29 | end 30 | 31 | GetPlayerFromIdentifier = function(identifier) 32 | local Player = nil 33 | 34 | if Config.Framework == 'ESX' then 35 | Player = ESX.GetPlayerFromIdentifier(identifier) 36 | elseif Config.Framework == 'QBCore' then 37 | Player = QBCore.Functions.GetPlayerByCitizenId(identifier) 38 | else 39 | -- Add your own code here 40 | end 41 | 42 | return Player 43 | end 44 | 45 | GetPlayerJob = function(Player) 46 | local job = 'unemployed' 47 | 48 | if Config.Framework == 'ESX' then 49 | job = Player.job.name 50 | elseif Config.Framework == 'QBCore' then 51 | job = Player.PlayerData.job.name 52 | else 53 | -- Add your own code here 54 | end 55 | 56 | return job 57 | end 58 | 59 | if Config.AdminCommand.enable then 60 | MSK.RegisterCommand(Config.AdminCommand.command, function(source, args, raw) 61 | TriggerClientEvent('msk_enginetoggle:toggleEngine', source, true) 62 | end, { 63 | allowConsole = false, 64 | restricted = Config.AdminCommand.groups, 65 | help = 'Toggle Engine as an Admin', 66 | }) 67 | end 68 | 69 | RegisterNetEvent('msk_enginetoggle:addTempKey', function(plate, model) 70 | if not Config.VehicleKeys.enable then return end 71 | local playerId = source 72 | plate = tostring(plate) 73 | 74 | if Config.VehicleKeys.script == 'msk_vehiclekeys' then 75 | exports.msk_vehiclekeys:AddTempKey({source = playerId}, {plate = plate, model = model}) 76 | elseif Config.VehicleKeys.script == 'VehicleKeyChain' then 77 | exports["VehicleKeyChain"]:AddTempKey(playerId, plate) 78 | elseif Config.VehicleKeys.script == 'vehicles_keys' then 79 | exports["vehicles_keys"]:giveVehicleKeysToPlayerId(playerId, plate, 'temporary') 80 | elseif Config.VehicleKeys.script == 'okokGarage' then 81 | TriggerEvent("okokGarage:GiveKeys", plate, playerId) 82 | else 83 | -- Add your own code here 84 | end 85 | end) 86 | 87 | RegisterNetEvent('msk_enginetoggle:enteredVehicle', function(plate, seat, netId, isEngineOn, isDamaged) 88 | local src = source 89 | local Player = GetPlayerFromId(src) 90 | local identifier = nil 91 | 92 | if Config.Framework == 'ESX' then 93 | identifier = Player.identifier 94 | elseif Config.Framework == 'QBCore' then 95 | identifier = Player.PlayerData.citizenid 96 | else 97 | -- Add your own code here 98 | end 99 | 100 | local result = MySQL.query.await(('SELECT * FROM %s WHERE %s = @owner AND plate = @plate'):format(VEHICLE_TABLE_NAME, OWNER_COLUMN_NAME), { 101 | ['@owner'] = identifier, 102 | ['@plate'] = MSK.String.Trim(plate) 103 | }) 104 | 105 | if result and result[1] then 106 | if result[1][OWNER_COLUMN_NAME] == identifier then 107 | TriggerClientEvent('msk_enginetoggle:deleteVehicleBlip', src, netId) 108 | end 109 | end 110 | end) 111 | 112 | MSK.Register('msk_enginetoggle:getInventory', function(source, inv) 113 | if inv ~= 'core_inventory' then return {} end 114 | local Player = GetPlayerFromId(src) 115 | local identifier = nil 116 | 117 | if Config.Framework == 'ESX' then 118 | identifier = Player.identifier 119 | elseif Config.Framework == 'QBCore' then 120 | identifier = Player.PlayerData.citizenid 121 | else 122 | -- Add your own code here 123 | end 124 | 125 | local invName = ('content-%s'):format(identifier):gsub(':', '') 126 | return exports['core_inventory']:getInventory(invName) 127 | end) 128 | 129 | logging = function(code, ...) 130 | if not Config.Debug then return end 131 | MSK.Logging(code, ...) 132 | end -------------------------------------------------------------------------------- /server/versionchecker.lua: -------------------------------------------------------------------------------- 1 | local AUTHOR = "MSK-Scripts" 2 | local NAME = "VERSIONS" 3 | local FILE = "EngineToggle.json" 4 | 5 | local RESOURCE_NAME = "msk_enginetoggle" 6 | local NAME_COLORED = "[^2"..GetCurrentResourceName().."^0]" 7 | local GITHUB_API = "https://raw.githubusercontent.com/%s/%s/main/%s" 8 | local DOWNLOAD = "https://github.com/%s/%s/releases/latest" 9 | 10 | local PrintKeyScripts = function() 11 | local VehicleScript = ("^3[%s]^0"):format(Config.VehicleKeys.script) 12 | 13 | if Config.VehicleKeys.enable then 14 | if (GetResourceState(Config.VehicleKeys.script) == "started") then 15 | print(("%s Script %s was found and is running!"):format(NAME_COLORED, VehicleScript)) 16 | elseif (GetResourceState(Config.VehicleKeys.script) == "stopped") then 17 | print(("%s Script %s was found but is stopped, please start the Script!"):format(NAME_COLORED, VehicleScript)) 18 | elseif (GetResourceState(Config.VehicleKeys.script) == "missing") then 19 | print(("%s Script %s was not found, please make sure that the Script is started!"):format(NAME_COLORED, VehicleScript)) 20 | end 21 | end 22 | end 23 | 24 | VersionChecker = function() 25 | SetTimeout(1000, function() 26 | if RESOURCE_NAME ~= GetCurrentResourceName() then 27 | CreateThread(function() 28 | while true do 29 | print(("%s [^3WARNING^0] ^3This resource should not be renamed! This can lead to errors. Please rename it to '%s'"):format(NAME_COLORED, RESOURCE_NAME)) 30 | Wait(5000) 31 | end 32 | end) 33 | end 34 | 35 | PerformHttpRequest(GITHUB_API:format(AUTHOR, NAME, FILE), function(status, response, headers) 36 | if status ~= 200 then 37 | return print(("%s [^1ERROR^0] ^1Version Check failed! Http Error: %s^0"):format(NAME_COLORED, status)) 38 | end 39 | 40 | local response = json.decode(response) 41 | local latestVersion = response[1].version 42 | local currentVersion = GetResourceMetadata(GetCurrentResourceName(), 'version', 0) 43 | 44 | if currentVersion == latestVersion then 45 | if Config.VersionChecker then 46 | print(("%s ^2✓ Resource is Up to Date^0 - ^5Current Version: ^2%s^0"):format(NAME_COLORED, currentVersion)) 47 | PrintKeyScripts() 48 | end 49 | return 50 | end 51 | 52 | local cV = MSK.String.Split(currentVersion, '.') 53 | local lV = MSK.String.Split(latestVersion, '.') 54 | 55 | for i = 1, #cV do 56 | local current, latest = tonumber(cV[i]), tonumber(lV[i]) 57 | 58 | if current ~= latest then 59 | if current < latest then 60 | print(("%s [^3Update Available^0] ^3An Update is available for %s! ^0[^5Current Version: ^1%s^0 - ^5Latest Version: ^2%s^0]\r\n%s ^5Download:^4 %s ^0"):format(NAME_COLORED, RESOURCE_NAME, currentVersion, latestVersion, NAME_COLORED, DOWNLOAD:format(AUTHOR, RESOURCE_NAME))) 61 | 62 | for i = 1, #response do 63 | if response[i].version == currentVersion then break end 64 | 65 | if response[i].changelogs then 66 | print(("%s [^3Changelogs v%s^0]"):format(NAME_COLORED, response[i].version)) 67 | 68 | for k = 1, #response[i].changelogs do 69 | print(('%s %s'):format(NAME_COLORED, response[i].changelogs[k])) 70 | end 71 | end 72 | end 73 | 74 | break 75 | else 76 | if Config.VersionChecker then 77 | print(("%s ^3Beta Version detected! ^0[^5Current Version: ^3%s^0 - ^5Latest Version: ^2%s^0] - ^3You can ignore this message!^0"):format(NAME_COLORED, currentVersion, latestVersion)) 78 | end 79 | 80 | break 81 | end 82 | end 83 | end 84 | 85 | PrintKeyScripts() 86 | end) 87 | end) 88 | end 89 | VersionChecker() -------------------------------------------------------------------------------- /translation.lua: -------------------------------------------------------------------------------- 1 | Translation = { 2 | ['de'] = { 3 | ['engine_start'] = 'Der Motor wurde ~g~gestartet~s~', 4 | ['engine_stop'] = 'Der Motor wurde ~r~gestoppt~s~', 5 | ['key_nokey'] = 'Du besitzt ~r~keinen~s~ Schlüssel für dieses Fahrzeug', 6 | ['veh_is_damaged'] = 'Das Fahrzeug kann nicht gestartet werden da es beschädigt ist', 7 | ['vehicle_wheel_clamped'] = 'Ein Reifen wurde gesperrt, du kannst so nicht fahren!', 8 | 9 | ['sit_in_vehicle'] = 'Du musst dafür in einem Fahrzeug sitzen', 10 | ['install_alarm'] = 'Installiere Alarmsystem', 11 | ['not_vehicle_owner'] = 'Das fahrzeug gehört dir nicht!', 12 | 13 | ['hasno_lockpick'] = 'Du hast keinen Dietrich dabei', 14 | ['lockpicking'] = 'Fahrzeug wird aufgebrochen...', 15 | ['search_key'] = 'Suche nach dem Schlüssel...', 16 | ['hotwiring'] = 'Fahrzeug kurzschließen...', 17 | ['vehicle_unlocked'] = 'Fahrzeug aufgebrochen', 18 | ['hotwiring_failed'] = 'Der Dietrich ist abgebrochen', 19 | ['hotwiring_foundkey'] = 'Fahrzeugschlüssel gefunden', 20 | ['hotwiring_notfoundkey'] = 'Fahrzeugschlüssel nicht gefunden', 21 | ['stole_vehicle'] = 'Jemand versucht gerade dein Fahrzeug zu stehlen!', 22 | ['stole_vehicle_police'] = 'Jemand versucht ein fremdes Fahrzeug zu stehlen!', 23 | ['blip_stolen_vehicle'] = 'Dein Gestohlenes Fahrzeug', 24 | }, 25 | ['en'] = { 26 | ['engine_start'] = 'The Engine ~g~started~s~', 27 | ['engine_stop'] = 'The Engine ~r~stopped~s~', 28 | ['key_nokey'] = 'You do ~r~not~s~ have a Key for this Vehicle', 29 | ['veh_is_damaged'] = 'The vehicle cannot be started because it is damaged', 30 | ['vehicle_wheel_clamped'] = 'One wheel has been locked, you cannot drive like this!', 31 | 32 | ['sit_in_vehicle'] = 'You must sit in a vehicle', 33 | ['install_alarm'] = 'Install Alarmsystem', 34 | ['not_vehicle_owner'] = 'You are not the owner of this vehicle!', 35 | 36 | ['hasno_lockpick'] = 'You don\'t have a lockpick with you', 37 | ['lockpicking'] = 'Lockpicking vehicle...', 38 | ['search_key'] = 'Search for the key...', 39 | ['hotwiring'] = 'Hotwiring the vehicle...', 40 | ['vehicle_unlocked'] = 'Vehicle broken into', 41 | ['hotwiring_failed'] = 'The lockpick is broken', 42 | ['hotwiring_foundkey'] = 'Vehiclekeys found', 43 | ['hotwiring_notfoundkey'] = 'Vehiclekeys not found', 44 | ['stole_vehicle'] = 'Someone is trying to steal your vehicle!', 45 | ['stole_vehicle_police'] = 'Someone is trying to steal the vehicle of someone else!', 46 | ['blip_stolen_vehicle'] = 'Your stolen vehicle', 47 | }, 48 | } --------------------------------------------------------------------------------