├── README.md ├── config.lua ├── fxmanifest.lua ├── locales ├── en.json ├── es.json ├── et.json └── nl.json └── resource ├── client.lua └── server.lua /README.md: -------------------------------------------------------------------------------- 1 | # Stevo's Chop Shops 2 | ## Simple but optimized and secure chopshop for FiveM! :red_car: :axe: 3 |  4 | **Created with optimization and security as a first priority, giving a seamless and secure experience.** 5 |  6 | - Any player in the zone can chop the vehicle, players can also continue chopping if they crash. 7 | - Configurable Rewards! 8 | - Configurable Police Alert! 9 | - Configurable Locations, Have as many as you want 10 | - **Supported Frameworks:** ESX, QBCore & Qbox 11 | - **Supported Inventories:** All! 12 | - **Locales:** EN, ES & NL 13 |  14 | 15 | **Follow our installation guide: [Click Here](https://docs.stevoscripts.com/free-scripts/stevo_chopshop)** 16 |  17 | > **Dependencies:** 18 | >
19 | > **[stevo_lib 1.6.8](https://github.com/stevoscriptsteam/stevo_lib/releases/tag/1.6.8)** 20 | >
21 | > **[ox_lib](https://github.com/overextended/ox_lib/releases/tag/v3.24.0)** 22 | >
23 | > **[ox_target](https://github.com/overextended/ox_target/releases/tag/v1.17.0)** 24 | 25 | 26 | Preview: [Click Here](https://youtu.be/qdrjP_yIs6s) 27 |
28 | Discord: [Click Here](https://discord.gg/stevoscripts) 29 |
30 | **Check our our paid releases!**: [Click Here](https://store.stevoscripts.com/) 31 | 32 | ![image](https://github.com/user-attachments/assets/49e559dd-9916-4844-b28e-5a0ab9e2f58a) 33 | -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | return { 2 | dropCheaters = true, -- If cheaters should be dropped/kicked from the server for exploiting events 3 | 4 | globalCooldown = 5, -- Time in minutes for global cooldown (Set to false for no cooldown) 5 | policeRequired = false, -- Police required to start chopping vehicle 6 | policeJob = 'police', 7 | 8 | policeDispatch = function(ped, vehicle) 9 | -- PS dispatch example 10 | --exports['ps-dispatch']:VehicleTheft(vehicle) 11 | end, 12 | 13 | chopShops = { 14 | lsia = { 15 | securityCoords = vec3(-425.2410, -1687.6906, 19.0291), -- Put in the middle of the chopping zone 16 | blip = false, 17 | zonePoints = { 18 | vec3(-426.0, -1674.0, 19), 19 | vec3(-434.0, -1697.0, 19), 20 | vec3(-423.0, -1700.0, 19), 21 | vec3(-411.0, -1680.0, 19) 22 | } 23 | }, 24 | sandy = { 25 | securityCoords = vec3(2340.4993, 3052.4824, 48.1473), -- Put in the middle of the chopping zone 26 | blip = { 27 | coords = vec3(2340.4993, 3052.4824, 48.1473), 28 | sprite = 225, -- https://docs.fivem.net/docs/game-references/blips/#blips 29 | color = 59, -- https://docs.fivem.net/docs/game-references/blips/#blip-colors 30 | scale = 0.8, -- float 31 | name = 'Chop Shop' 32 | 33 | }, zonePoints = { 34 | vec3(2343.0, 3049.0, 48.0), 35 | vec3(2338.0, 3049.0, 48.0), 36 | vec3(2337.0, 3058.0, 48.0), 37 | vec3(2344.0, 3059.0, 48.0), 38 | } 39 | } 40 | }, 41 | 42 | blockedVehicleTypes = { -- Its advised you dont change this unless you know what your doing. (Removing it may break the script as bikes cannot be chopped) 43 | 'bike', 44 | 'heli', 45 | 'boat' 46 | }, 47 | 48 | rewards = { -- Add rewards for each part. 49 | 50 | ["stevo_chopshop:1"] = { -- Bonnet 51 | {item = 'plastic', amount = 1}, 52 | }, 53 | 54 | ["stevo_chopshop:2"] = { -- Front dri Door 55 | {item = 'plastic', amount = 1}, 56 | }, 57 | 58 | ["stevo_chopshop:3"] = { -- Front pas door 59 | {item = 'plastic', amount = 1}, 60 | }, 61 | 62 | ["stevo_chopshop:4"] = { -- Back dri Door 63 | {item = 'plastic', amount = 1}, 64 | }, 65 | 66 | ["stevo_chopshop:5"] = { -- Back pas Door 67 | {item = 'plastic', amount = 1}, 68 | }, 69 | 70 | ["stevo_chopshop:6"] = { -- Boot 71 | {item = 'plastic', amount = 1}, 72 | }, 73 | 74 | ["stevo_chopshop:7"] = { -- Front dri wheel 75 | {item = 'plastic', amount = 1}, 76 | }, 77 | 78 | ["stevo_chopshop:8"] = { -- Front pas wheel 79 | {item = 'plastic', amount = 1}, 80 | }, 81 | 82 | ["stevo_chopshop:9"] = {-- Back dri wheel 83 | {item = 'plastic', amount = 1}, 84 | }, 85 | 86 | ["stevo_chopshop:10"] = {-- Back pas wheel 87 | {item = 'plastic', amount = 1}, 88 | }, 89 | 90 | ["stevo_chopshop:11"] = { -- Whole chassis 91 | {item = 'plastic', amount = 1}, 92 | {item = 'steel', amount = 1}, 93 | }, 94 | 95 | }, 96 | 97 | skillchecks = { 98 | ["stevo_chopshop:1"] = {'easy', 'easy'}, -- Bonnet 99 | ["stevo_chopshop:2"] = {'easy', 'easy'}, -- Front dri Door 100 | ["stevo_chopshop:3"] = {'easy', 'easy'}, -- Front pas Door 101 | ["stevo_chopshop:4"] = {'easy', 'easy'}, -- Back dri Door 102 | ["stevo_chopshop:5"] = {'easy', 'easy'}, -- Back pas Door 103 | ["stevo_chopshop:6"] = {'easy', 'easy'}, -- Boot 104 | ["stevo_chopshop:7"] = {'easy', 'easy'}, -- Front dri wheel 105 | ["stevo_chopshop:8"] = {'easy', 'easy'}, -- Front pas wheel 106 | ["stevo_chopshop:9"] = {'easy', 'easy'}, -- Back dri wheel 107 | ["stevo_chopshop:10"] = {'easy', 'easy'}, -- Back pas wheel 108 | ["stevo_chopshop:11"] = {'easy', 'easy'}, -- Whole chassis 109 | }, 110 | 111 | 112 | duration = { 113 | ["stevo_chopshop:1"] = 2000, -- Bonnet 114 | ["stevo_chopshop:2"] = 3000, -- Front dri Door 115 | ["stevo_chopshop:3"] = 3000, -- Front pas Door 116 | ["stevo_chopshop:4"] = 3000, -- Back dri Door 117 | ["stevo_chopshop:5"] = 3000, -- Back pas Door 118 | ["stevo_chopshop:6"] = 2000, -- Boot 119 | ["stevo_chopshop:7"] = 2500, -- Front dri wheel 120 | ["stevo_chopshop:8"] = 2500, -- Front pas wheel 121 | ["stevo_chopshop:9"] = 2500, -- Back dri wheel 122 | ["stevo_chopshop:10"] = 2500, -- Back pas wheel 123 | ["stevo_chopshop:11"] = 5000, -- Whole chassis 124 | }, 125 | 126 | debug = false, -- Enabling debug prints and zones. 127 | 128 | } -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | use_experimental_fxv2_oal 'yes' 4 | lua54 'yes' 5 | 6 | author "Stevo Scripts | steve" 7 | description 'Simple Chop Shop' 8 | version '1.0.3' 9 | 10 | shared_script { 11 | '@ox_lib/init.lua', 12 | 'config.lua' 13 | } 14 | 15 | client_scripts { 16 | 'resource/client.lua', 17 | } 18 | 19 | server_scripts { 20 | 'resource/server.lua' 21 | } 22 | 23 | files { 24 | 'locales/*.json', 25 | } 26 | 27 | dependencies { 28 | 'ox_lib' 29 | } 30 | -------------------------------------------------------------------------------- /locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "textui" : { 3 | "start_chopping" : "[E] - Start Chopping Vehicle", 4 | "being_chopped" : "This vehicle is already being chopped" 5 | }, 6 | 7 | "notify" : { 8 | "start_chopping" : "Started Chopping Vehicle", 9 | "fail_skillcheck" : "You failed the chop!", 10 | "chop_cooldown" : "There is currently a cooldown!", 11 | "chop_police" : "There is not enough police to start chopping!", 12 | "cant_chop" : "You cannot chop this kind of vehicle!", 13 | 14 | "stevo_chopshop:1" : "Chop the Front Driver Door", 15 | "stevo_chopshop:2" : "Chop the Front Passenger Door", 16 | "stevo_chopshop:3" : "Chop the Back Passenger Door", 17 | "stevo_chopshop:4" : "Chop the Back Driver Door", 18 | "stevo_chopshop:5" : "Chop the Boot", 19 | "stevo_chopshop:6" : "Chop the Front Left Tire", 20 | "stevo_chopshop:7" : "Chop the Front Right Tire", 21 | "stevo_chopshop:8" : "Chop the Back Left Tire", 22 | "stevo_chopshop:9" : "Chop the Back Right Tire", 23 | "stevo_chopshop:10" : "Chop the entire car!", 24 | "stevo_chopshop:11" : "You chopped the entire car!" 25 | }, 26 | 27 | "progress" : { 28 | "stevo_chopshop:1" : "Chopping the bonnet off...", 29 | "stevo_chopshop:2" : "Chopping the door off...", 30 | "stevo_chopshop:3" : "Chopping the door off...", 31 | "stevo_chopshop:4" : "Chopping the door off...", 32 | "stevo_chopshop:5" : "Chopping the door off...", 33 | "stevo_chopshop:6" : "Chopping the boot off...", 34 | "stevo_chopshop:7" : "Chopping the tire off...", 35 | "stevo_chopshop:8" : "Chopping the tire off...", 36 | "stevo_chopshop:9" : "Chopping the tire off...", 37 | "stevo_chopshop:10" :"Chopping the tire off...", 38 | "stevo_chopshop:11" : "Chopping the chassis..." 39 | }, 40 | 41 | "target" : { 42 | "stevo_chopshop:1" : "Chop Bonnet", 43 | "stevo_chopshop:2" : "Chop Door", 44 | "stevo_chopshop:3" : "Chop Door", 45 | "stevo_chopshop:4" : "Chop Door", 46 | "stevo_chopshop:5" : "Chop Door", 47 | "stevo_chopshop:6" : "Chop Boot", 48 | "stevo_chopshop:7" : "Chop Tire", 49 | "stevo_chopshop:8" : "Chop Tire", 50 | "stevo_chopshop:9" : "Chop Tire", 51 | "stevo_chopshop:10" :"Chop Tire", 52 | "stevo_chopshop:11" : "Finish Chop" 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /locales/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "textui" : { 3 | "start_chopping" : "[E] - Comenzar a desmantelar el vehículo", 4 | "being_chopped" : "Este vehículo ya está siendo desmantelado" 5 | }, 6 | 7 | "notify" : { 8 | "start_chopping" : "Comenzaste a desmantelar el vehículo", 9 | "fail_skillcheck" : "¡Fallaste en desmantelar!", 10 | "chop_cooldown" : "There is currently a cooldown!", 11 | "chop_police" : "There is not enough police to start chopping!", 12 | "cant_chop" : "¡No puedes desmantelar este tipo de vehículo!", 13 | 14 | "stevo_chopshop:1" : "Desmantelar la puerta del conductor delantero", 15 | "stevo_chopshop:2" : "Desmantelar la puerta del pasajero delantero", 16 | "stevo_chopshop:3" : "Desmantelar la puerta del pasajero trasero", 17 | "stevo_chopshop:4" : "Desmantelar la puerta del conductor trasero", 18 | "stevo_chopshop:5" : "Desmantelar el maletero", 19 | "stevo_chopshop:6" : "Desmantelar la llanta delantera izquierda", 20 | "stevo_chopshop:7" : "Desmantelar la llanta delantera derecha", 21 | "stevo_chopshop:8" : "Desmantelar la llanta trasera izquierda", 22 | "stevo_chopshop:9" : "Desmantelar la llanta trasera derecha", 23 | "stevo_chopshop:10" : "¡Desmantelar todo el coche!", 24 | "stevo_chopshop:11" : "¡Desmantelaste todo el coche!" 25 | }, 26 | 27 | "progress" : { 28 | "stevo_chopshop:1" : "Desmantelando el capó...", 29 | "stevo_chopshop:2" : "Desmantelando la puerta...", 30 | "stevo_chopshop:3" : "Desmantelando la puerta...", 31 | "stevo_chopshop:4" : "Desmantelando la puerta...", 32 | "stevo_chopshop:5" : "Desmantelando la puerta...", 33 | "stevo_chopshop:6" : "Desmantelando el maletero...", 34 | "stevo_chopshop:7" : "Desmantelando la llanta...", 35 | "stevo_chopshop:8" : "Desmantelando la llanta...", 36 | "stevo_chopshop:9" : "Desmantelando la llanta...", 37 | "stevo_chopshop:10" : "Desmantelando la llanta...", 38 | "stevo_chopshop:11" : "Desmantelando el chasis..." 39 | }, 40 | 41 | "target" : { 42 | "stevo_chopshop:1" : "Desmantelar capó", 43 | "stevo_chopshop:2" : "Desmantelar puerta", 44 | "stevo_chopshop:3" : "Desmantelar puerta", 45 | "stevo_chopshop:4" : "Desmantelar puerta", 46 | "stevo_chopshop:5" : "Desmantelar puerta", 47 | "stevo_chopshop:6" : "Desmantelar maletero", 48 | "stevo_chopshop:7" : "Desmantelar llanta", 49 | "stevo_chopshop:8" : "Desmantelar llanta", 50 | "stevo_chopshop:9" : "Desmantelar llanta", 51 | "stevo_chopshop:10" : "Desmantelar llanta", 52 | "stevo_chopshop:11" : "Desmantelar llanta" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /locales/et.json: -------------------------------------------------------------------------------- 1 | { 2 | "textui" : { 3 | "start_chopping" : "[E] Alusta sõiduki lammutamist", 4 | "being_chopped" : "Seda sõidukit juba tükeldatakse" 5 | }, 6 | 7 | "notify" : { 8 | "start_chopping" : "Hakka sõidukit lammutama", 9 | "fail_skillcheck" : "Sa ei saanud hakkama!", 10 | "chop_cooldown" : "Ära kiirusta sõiduki lammutamisega!", 11 | "chop_police" : "Politseid pole piisavalt, et lammutama hakata!", 12 | "cant_chop" : "Sellist sõidukit ei saa lammutada!", 13 | 14 | "stevo_chopshop:1" : "Sõiduki jupi lammutamine oli edukas!", 15 | "stevo_chopshop:2" : "Sõiduki jupi lammutamine oli edukas!", 16 | "stevo_chopshop:3" : "Sõiduki jupi lammutamine oli edukas!", 17 | "stevo_chopshop:4" : "Sõiduki jupi lammutamine oli edukas!", 18 | "stevo_chopshop:5" : "Sõiduki jupi lammutamine oli edukas!", 19 | "stevo_chopshop:6" : "Sõiduki jupi lammutamine oli edukas!", 20 | "stevo_chopshop:7" : "Sõiduki jupi lammutamine oli edukas!", 21 | "stevo_chopshop:8" : "Sõiduki jupi lammutamine oli edukas!", 22 | "stevo_chopshop:9" : "Sõiduki jupi lammutamine oli edukas!", 23 | "stevo_chopshop:10" : "Sõiduki jupi lammutamine oli edukas!", 24 | "stevo_chopshop:11" : "Terve sõiduk on ära lammutatud!" 25 | }, 26 | 27 | "progress" : { 28 | "stevo_chopshop:1" : "Lammutad kapotti", 29 | "stevo_chopshop:2" : "Lammutad ust", 30 | "stevo_chopshop:3" : "Lammutad ust", 31 | "stevo_chopshop:4" : "Lammutad ust", 32 | "stevo_chopshop:5" : "Lammutad ust", 33 | "stevo_chopshop:6" : "Lammutad rehvi", 34 | "stevo_chopshop:7" : "Lammutad rehvi", 35 | "stevo_chopshop:8" : "Lammutad rehvi", 36 | "stevo_chopshop:9" : "Lammutad rehvi", 37 | "stevo_chopshop:10" :"Lammutad rehvi", 38 | "stevo_chopshop:11" : "Lammutad sõidukit" 39 | }, 40 | 41 | "target" : { 42 | "stevo_chopshop:1" : "Lammutad kapotti", 43 | "stevo_chopshop:2" : "Lammutad ust", 44 | "stevo_chopshop:3" : "Lammutad ust", 45 | "stevo_chopshop:4" : "Lammutad ust", 46 | "stevo_chopshop:5" : "Lammutad ust", 47 | "stevo_chopshop:6" : "Lammutad rehvi", 48 | "stevo_chopshop:7" : "Lammutad rehvi", 49 | "stevo_chopshop:8" : "Lammutad rehvi", 50 | "stevo_chopshop:9" : "Lammutad rehvi", 51 | "stevo_chopshop:10" :"Lammutad rehvi", 52 | "stevo_chopshop:11" : "Lammuta sõidukit" 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /locales/nl.json: -------------------------------------------------------------------------------- 1 | { 2 | "textui" : { 3 | "start_chopping" : "[E] - Begin met het slopen van het voertuig", 4 | "being_chopped" : "Dit voertuig wordt al gesloopt" 5 | }, 6 | 7 | "notify" : { 8 | "start_chopping" : "Begonnen met het slopen van het voertuig", 9 | "fail_skillcheck" : "Je bent niet geslaagd met slopen!", 10 | "chop_cooldown" : "There is currently a cooldown!", 11 | "chop_police" : "There is not enough police to start chopping!", 12 | "cant_chop" : "Je kunt dit type voertuig niet slopen!", 13 | 14 | "stevo_chopshop:1" : "Sloop de voorste bestuurdersdeur", 15 | "stevo_chopshop:2" : "Sloop de voorste passagiersdeur", 16 | "stevo_chopshop:3" : "Sloop de achterste passagiersdeur", 17 | "stevo_chopshop:4" : "Sloop de achterste bestuurdersdeur", 18 | "stevo_chopshop:5" : "Sloop de kofferbak", 19 | "stevo_chopshop:6" : "Sloop de linker voorband", 20 | "stevo_chopshop:7" : "Sloop de rechter voorband", 21 | "stevo_chopshop:8" : "Sloop de linker achterband", 22 | "stevo_chopshop:9" : "Sloop de rechter achterband", 23 | "stevo_chopshop:10" : "Sloop de hele auto!", 24 | "stevo_chopshop:11" : "Je hebt de hele auto gesloopt!" 25 | }, 26 | 27 | "progress" : { 28 | "stevo_chopshop:1" : "Bezig met het slopen van de motorkap...", 29 | "stevo_chopshop:2" : "Bezig met het slopen van de deur...", 30 | "stevo_chopshop:3" : "Bezig met het slopen van de deur...", 31 | "stevo_chopshop:4" : "Bezig met het slopen van de deur...", 32 | "stevo_chopshop:5" : "Bezig met het slopen van de deur...", 33 | "stevo_chopshop:6" : "Bezig met het slopen van de kofferbak...", 34 | "stevo_chopshop:7" : "Bezig met het slopen van de band...", 35 | "stevo_chopshop:8" : "Bezig met het slopen van de band...", 36 | "stevo_chopshop:9" : "Bezig met het slopen van de band...", 37 | "stevo_chopshop:10" : "Bezig met het slopen van de band...", 38 | "stevo_chopshop:11" : "Bezig met het slopen van het chassis..." 39 | }, 40 | 41 | "target" : { 42 | "stevo_chopshop:1" : "Sloop motorkap", 43 | "stevo_chopshop:2" : "Sloop deur", 44 | "stevo_chopshop:3" : "Sloop deur", 45 | "stevo_chopshop:4" : "Sloop deur", 46 | "stevo_chopshop:5" : "Sloop deur", 47 | "stevo_chopshop:6" : "Sloop kofferbak", 48 | "stevo_chopshop:7" : "Sloop band", 49 | "stevo_chopshop:8" : "Sloop band", 50 | "stevo_chopshop:9" : "Sloop band", 51 | "stevo_chopshop:10" : "Sloop band", 52 | "stevo_chopshop:11" : "Sloop band" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /resource/client.lua: -------------------------------------------------------------------------------- 1 | if not lib.checkDependency('stevo_lib', '1.6.8') then error('stevo_lib version 1.6.8 is required for stevo_chopshop to work!') return end 2 | lib.locale() 3 | local config = require('config') 4 | local stevo_lib = exports['stevo_lib']:import() 5 | 6 | local insideZone = false 7 | local blips = {} 8 | 9 | lib.onCache('vehicle', function(value) 10 | if not insideZone then return end 11 | 12 | local isOpen, text = lib.isTextUIOpen() 13 | 14 | if not value then if isOpen then lib.hideTextUI() end return end 15 | 16 | if Entity(value).state.currentlyChopping then lib.showTextUI(locale("textui.being_chopped")) return end 17 | 18 | lib.showTextUI(locale("textui.start_chopping")) 19 | 20 | end) 21 | 22 | local function onEnter(self) 23 | insideZone = self.chopshop 24 | if cache.vehicle then 25 | lib.showTextUI(locale("textui.start_chopping")) 26 | end 27 | end 28 | 29 | local function onExit(self) 30 | insideZone = false 31 | 32 | local isOpen, text = lib.isTextUIOpen() 33 | if isOpen then 34 | lib.hideTextUI() 35 | end 36 | end 37 | 38 | local function inside(self) 39 | 40 | if not cache.vehicle then return end 41 | 42 | if Entity(cache.vehicle).state.currentlyChopping then return end 43 | 44 | local isOpen, text = lib.isTextUIOpen() 45 | 46 | if not isOpen then lib.hideTextUI() return end 47 | 48 | if IsControlJustReleased(1, 38) then 49 | 50 | if GlobalState.stevo_chopshop_cooldown then 51 | return stevo_lib.Notify(locale("notify.chop_cooldown"), 'error', 5000) 52 | end 53 | 54 | if not lib.callback.await('stevo_chopshop:canChop', false) then 55 | return stevo_lib.Notify(locale("notify.chop_police"), 'error', 5000) 56 | end 57 | 58 | local vehicleType = GetVehicleType(cache.vehicle) 59 | 60 | for i, type in pairs(config.blockedVehicleTypes) do 61 | if vehicleType == type then return stevo_lib.Notify(locale("notify.cant_chop"), 'error', 5000) end 62 | end 63 | 64 | stevo_lib.Notify(locale("notify.start_chopping"), 'info', 5000) 65 | 66 | Entity(cache.vehicle).state:set('currentlyChopping', true, true) 67 | Entity(cache.vehicle).state:set('choppingStage', 1, true) 68 | 69 | FreezeEntityPosition(cache.vehicle, true) 70 | SetVehicleDoorsLocked(cache.vehicle, 2) 71 | SetVehicleEngineOn(cache.vehicle, false, true, true) 72 | TaskLeaveVehicle(cache.ped, cache.vehicle, 0) 73 | 74 | lib.hideTextUI() 75 | end 76 | 77 | end 78 | 79 | local function chopPart(data) 80 | TaskTurnPedToFaceEntity(cache.ped, data.entity, 300) 81 | Wait(300) 82 | 83 | if not lib.skillCheck(config.skillchecks[data.name]) then stevo_lib.Notify(locale("notify.fail_skillcheck"), 'error', 3000) return end 84 | 85 | local vehicle = data.entity 86 | 87 | if data.name == 'stevo_chopshop:1' then config.policeDispatch(cache.ped, vehicle) end 88 | 89 | if data.doorIndex then 90 | SetVehicleDoorOpen(vehicle, data.doorIndex, false, false) 91 | end 92 | 93 | local wheelAnim = {scenario = "CODE_HUMAN_MEDIC_TEND_TO_DEAD"} 94 | local otherAnim = {dict = 'amb@world_human_welding@male@base', clip = 'base'} 95 | local otherProp = {model = `prop_weld_torch`, bone = 28422, pos = vec3(-0.01, 0.03, 0.02), rot = vec3(0.0, 0.0, -1.5)} 96 | 97 | if lib.progressBar({ 98 | duration = config.duration[data.name], 99 | label = locale("progress."..data.name), 100 | canCancel = true, 101 | disable = { 102 | car = true, 103 | move = true 104 | }, 105 | anim = data.wheelIndex and wheelAnim or otherAnim, 106 | prop = data.wheelIndex and false or otherProp 107 | }) 108 | 109 | then 110 | 111 | if data.doorIndex then 112 | SetVehicleDoorCanBreak(vehicle, data.doorIndex, true) 113 | SetVehicleDoorBroken(vehicle, data.doorIndex, true) 114 | end 115 | 116 | if data.wheelIndex then 117 | SetVehicleWheelsCanBreak(vehicle, true) 118 | SetVehicleTyreBurst(vehicle, data.wheelIndex, true, 1000.0) 119 | end 120 | 121 | 122 | local doors = GetNumberOfVehicleDoors(vehicle) 123 | 124 | local chopPart, chopNotify = lib.callback.await('stevo_chopshop:chopPart', false, data, NetworkGetNetworkIdFromEntity(vehicle), doors) 125 | 126 | if chopPart then stevo_lib.Notify(chopNotify, 'success', 5000) end 127 | else 128 | return 129 | end 130 | end 131 | 132 | local function loadChopShops() 133 | local totalChopShops = 0 134 | for i, chopShop in pairs(config.chopShops) do 135 | lib.zones.poly({ 136 | points = chopShop.zonePoints, 137 | thickness = 2, 138 | debug = config.debug, 139 | inside = inside, 140 | onEnter = onEnter, 141 | onExit = onExit, 142 | chopshop = i 143 | }) 144 | 145 | local blip = chopShop.blip 146 | if blip then 147 | blips[i] = AddBlipForCoord(blip.coords.x, blip.coords.y, blip.coords.z) 148 | 149 | SetBlipAsShortRange(blips[i], true) 150 | SetBlipSprite(blips[i], blip.sprite) 151 | SetBlipColour(blips[i], blip.color) 152 | SetBlipScale(blips[i], blip.scale) 153 | BeginTextCommandSetBlipName('STRING') 154 | AddTextComponentSubstringPlayerName(blip.name) 155 | EndTextCommandSetBlipName(blips[i]) 156 | 157 | SetBlipDisplay(blips[i], 4) 158 | SetBlipAsMissionCreatorBlip(blips[i], true) 159 | end 160 | 161 | totalChopShops = totalChopShops +1 162 | end 163 | 164 | if config.debug then 165 | local debugPrint = ('%s Chop Shops Loaded'):format(totalChopShops) 166 | lib.print.info(debugPrint) 167 | end 168 | 169 | local options = { 170 | { 171 | name = 'stevo_chopshop:1', 172 | icon = 'fa-solid fa-car', 173 | label = locale('target.stevo_chopshop:1'), 174 | bones = {'bonnet'}, 175 | doorIndex = 4, 176 | wheelIndex = false, 177 | chassis = false, 178 | onSelect = chopPart, 179 | canInteract = function(entity) 180 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 1 181 | end 182 | }, 183 | { 184 | name = 'stevo_chopshop:2', 185 | icon = 'fa-solid fa-car', 186 | label = locale('target.stevo_chopshop:2'), 187 | bones = {'door_dside_f'}, 188 | doorIndex = 0, 189 | wheelIndex = false, 190 | chassis = false, 191 | onSelect = chopPart, 192 | canInteract = function(entity) 193 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 2 194 | end 195 | }, 196 | { 197 | name = 'stevo_chopshop:3', 198 | icon = 'fa-solid fa-car', 199 | label = locale('target.stevo_chopshop:3'), 200 | bones = {'door_pside_f'}, 201 | doorIndex = 1, 202 | wheelIndex = false, 203 | chassis = false, 204 | onSelect = chopPart, 205 | canInteract = function(entity) 206 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 3 207 | end 208 | }, 209 | { 210 | name = 'stevo_chopshop:4', 211 | icon = 'fa-solid fa-car', 212 | label = locale('target.stevo_chopshop:4'), 213 | doorIndex = 2, 214 | wheelIndex = false, 215 | chassis = false, 216 | bones = {'door_dside_r'}, 217 | onSelect = chopPart, 218 | canInteract = function(entity) 219 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 4 220 | end 221 | }, 222 | { 223 | name = 'stevo_chopshop:5', 224 | icon = 'fa-solid fa-car', 225 | label = locale('target.stevo_chopshop:5'), 226 | doorIndex = 3, 227 | wheelIndex = false, 228 | chassis = false, 229 | bones = {'door_pside_r'}, 230 | onSelect = chopPart, 231 | canInteract = function(entity) 232 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 5 233 | end 234 | }, 235 | { 236 | name = 'stevo_chopshop:6', 237 | icon = 'fa-solid fa-car', 238 | label = locale('target.stevo_chopshop:6'), 239 | doorIndex = 5, 240 | wheelIndex = false, 241 | chassis = false, 242 | bones = {'boot'}, 243 | onSelect = chopPart, 244 | canInteract = function(entity) 245 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 6 246 | end 247 | }, 248 | { 249 | name = 'stevo_chopshop:7', 250 | icon = 'fa-solid fa-car', 251 | label = locale('target.stevo_chopshop:7'), 252 | bones = {'wheel_lf'}, 253 | doorIndex = false, 254 | wheelIndex = 0, 255 | chassis = false, 256 | onSelect = chopPart, 257 | canInteract = function(entity) 258 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 7 259 | end 260 | }, 261 | { 262 | name = 'stevo_chopshop:8', 263 | icon = 'fa-solid fa-car', 264 | label = locale('target.stevo_chopshop:8'), 265 | doorIndex = false, 266 | wheelIndex = 1, 267 | chassis = false, 268 | bones = {'wheel_rf'}, 269 | onSelect = chopPart, 270 | canInteract = function(entity) 271 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 8 272 | end 273 | }, 274 | { 275 | name = 'stevo_chopshop:9', 276 | icon = 'fa-solid fa-car', 277 | label = locale('target.stevo_chopshop:9'), 278 | doorIndex = false, 279 | wheelIndex = 4, 280 | chassis = false, 281 | bones = {'wheel_lr'}, 282 | onSelect = chopPart, 283 | canInteract = function(entity) 284 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 9 285 | end 286 | }, 287 | { 288 | name = 'stevo_chopshop:10', 289 | icon = 'fa-solid fa-car', 290 | label = locale('target.stevo_chopshop:10'), 291 | doorIndex = false, 292 | wheelIndex = 5, 293 | chassis = false, 294 | bones = {'wheel_rr'}, 295 | onSelect = chopPart, 296 | canInteract = function(entity) 297 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 10 298 | end 299 | }, 300 | { 301 | name = 'stevo_chopshop:11', 302 | icon = 'fa-solid fa-car', 303 | label = locale('target.stevo_chopshop:11'), 304 | distance = 3, 305 | doorIndex = false, 306 | wheelIndex = false, 307 | chassis = true, 308 | onSelect = chopPart, 309 | canInteract = function(entity) 310 | return insideZone and Entity(entity).state.currentlyChopping and Entity(entity).state.choppingStage == 11 311 | end 312 | } 313 | } 314 | 315 | exports.ox_target:addGlobalVehicle(options) 316 | end 317 | 318 | AddEventHandler('onResourceStart', function(resource) 319 | if resource ~= cache.resource then return end 320 | 321 | loadChopShops() 322 | end) 323 | 324 | AddEventHandler('stevo_lib:playerLoaded', function() 325 | loadChopShops() 326 | end) 327 | 328 | AddEventHandler('onResourceStop', function(resource) 329 | if resource ~= cache.resource then return end 330 | 331 | for i, blip in pairs(blips) do 332 | if DoesBlipExist(blip) then 333 | RemoveBlip(blip) 334 | end 335 | end 336 | end) 337 | -------------------------------------------------------------------------------- /resource/server.lua: -------------------------------------------------------------------------------- 1 | lib.versionCheck('stevoscriptsteam/stevo_chopshop') 2 | if not lib.checkDependency('stevo_lib', '1.6.8') then error('stevo_lib version 1.6.8 is required for stevo_chopshop to work!') return end 3 | lib.locale() 4 | local stevo_lib = exports['stevo_lib']:import() 5 | local config = lib.require('config') 6 | 7 | GlobalState.stevo_chopshop_cooldown = false 8 | 9 | ---@param source number 10 | local function playerCheating(source) 11 | local identifier = stevo_lib.GetIdentifier(source) 12 | local name = GetPlayerName(source) 13 | local warningMessage = (locale("cheater_warning")):format(name, identifier) 14 | lib.print.info(warningMessage) 15 | 16 | if not config.dropCheaters then return end 17 | 18 | return DropPlayer(source, 'Exploiting stevo_chopshop') 19 | end 20 | 21 | ---@param source number 22 | ---@param name string 23 | local function giveRewards(source, name) 24 | local rewardTable = config.rewards[name] 25 | 26 | for i, reward in pairs(rewardTable) do 27 | stevo_lib.AddItem(source, reward.item, reward.amount) 28 | end 29 | end 30 | 31 | local function cooldown() 32 | CreateThread(function() 33 | if config.globalCooldown then 34 | GlobalState.stevo_chopshop_cooldown = true 35 | SetTimeout(config.globalCooldown*60000, function() 36 | GlobalState.stevo_chopshop_cooldown = false 37 | end) 38 | end 39 | end) 40 | end 41 | 42 | ---@param source number 43 | ---@param _vehicle integer 44 | lib.callback.register('stevo_chopshop:chopPart', function(source, data, _vehicle, doors) 45 | local vehicle = NetworkGetEntityFromNetworkId(_vehicle) 46 | 47 | if not DoesEntityExist(vehicle) then 48 | return playerCheating(source) 49 | end 50 | 51 | if not Entity(vehicle).state.currentlyChopping then 52 | return playerCheating(source) 53 | end 54 | 55 | local playerPed = GetPlayerPed(source) 56 | local playerCoords = GetEntityCoords(playerPed) 57 | local insideChopshop = false 58 | 59 | for i, chopshop in pairs(config.chopShops) do 60 | local dist = #(chopshop.securityCoords - playerCoords) 61 | if dist < 50 then 62 | insideChopshop = true 63 | break 64 | end 65 | end 66 | 67 | if not insideChopshop then 68 | return playerCheating(source) 69 | end 70 | 71 | local choppingStage = Entity(vehicle).state.choppingStage 72 | 73 | if Entity(vehicle).state.choppingStage == 11 then 74 | DeleteEntity(vehicle) 75 | giveRewards(source, data.name) 76 | 77 | return true, locale("notify."..data.name) 78 | end 79 | 80 | 81 | if doors == 3 and choppingStage == 3 then 82 | Entity(vehicle).state:set('choppingStage', 7, true) 83 | giveRewards(source, data.name) 84 | 85 | return true, locale("notify.stevo_chopshop:6") 86 | end 87 | 88 | if doors == 4 and choppingStage == 3 then 89 | Entity(vehicle).state:set('choppingStage', 6, true) 90 | giveRewards(source, data.name) 91 | 92 | return true, locale("notify.stevo_chopshop:5") 93 | end 94 | 95 | 96 | Entity(vehicle).state:set('choppingStage', choppingStage + 1, true) 97 | giveRewards(source, data.name) 98 | 99 | return true, locale("notify."..data.name) 100 | end) 101 | 102 | ---@return boolean 103 | lib.callback.register('stevo_chopshop:canChop', function() 104 | 105 | if GlobalState.stevo_chopshop_cooldown then return false end 106 | 107 | if not config.policeRequirement then cooldown() return true end 108 | 109 | local police = stevo_lib.GetJobCount(config.policeJob) 110 | 111 | if police >= config.policeRequired then cooldown() return true end 112 | 113 | return false 114 | end) 115 | 116 | 117 | 118 | 119 | --------------------------------------------------------------------------------