├── [IMAGES] ├── goldcoin.png ├── irontrash.png ├── steelcan.png ├── ww2relic.png ├── aincientcoin.png ├── aluminiumcan.png ├── antiquecoin.png ├── brokenknife.png ├── brokenphone.png ├── goldnugget.png ├── metaltrash.png ├── pocketwatch.png ├── treasurekey.png ├── BulletCasings.png ├── brokendetector.png ├── brokengameboy.png ├── metaldetector.png └── burriedtreasure.png ├── stream ├── w_am_digiscanner.ydr ├── w_am_digiscanner.ytd ├── w_am_digiscanner+hi.ytd ├── w_am_metaldetector.ydr ├── w_am_metaldetector.ytd └── gen_w_am_metaldetector.ytyp ├── fxmanifest.lua ├── client ├── cl_target.lua └── cl_main.lua ├── config.lua ├── README.md ├── server └── sv_main.lua └── LICENSE /[IMAGES]/goldcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/goldcoin.png -------------------------------------------------------------------------------- /[IMAGES]/irontrash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/irontrash.png -------------------------------------------------------------------------------- /[IMAGES]/steelcan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/steelcan.png -------------------------------------------------------------------------------- /[IMAGES]/ww2relic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/ww2relic.png -------------------------------------------------------------------------------- /[IMAGES]/aincientcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/aincientcoin.png -------------------------------------------------------------------------------- /[IMAGES]/aluminiumcan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/aluminiumcan.png -------------------------------------------------------------------------------- /[IMAGES]/antiquecoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/antiquecoin.png -------------------------------------------------------------------------------- /[IMAGES]/brokenknife.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/brokenknife.png -------------------------------------------------------------------------------- /[IMAGES]/brokenphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/brokenphone.png -------------------------------------------------------------------------------- /[IMAGES]/goldnugget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/goldnugget.png -------------------------------------------------------------------------------- /[IMAGES]/metaltrash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/metaltrash.png -------------------------------------------------------------------------------- /[IMAGES]/pocketwatch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/pocketwatch.png -------------------------------------------------------------------------------- /[IMAGES]/treasurekey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/treasurekey.png -------------------------------------------------------------------------------- /[IMAGES]/BulletCasings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/BulletCasings.png -------------------------------------------------------------------------------- /[IMAGES]/brokendetector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/brokendetector.png -------------------------------------------------------------------------------- /[IMAGES]/brokengameboy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/brokengameboy.png -------------------------------------------------------------------------------- /[IMAGES]/metaldetector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/metaldetector.png -------------------------------------------------------------------------------- /stream/w_am_digiscanner.ydr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/stream/w_am_digiscanner.ydr -------------------------------------------------------------------------------- /stream/w_am_digiscanner.ytd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/stream/w_am_digiscanner.ytd -------------------------------------------------------------------------------- /[IMAGES]/burriedtreasure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/[IMAGES]/burriedtreasure.png -------------------------------------------------------------------------------- /stream/w_am_digiscanner+hi.ytd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/stream/w_am_digiscanner+hi.ytd -------------------------------------------------------------------------------- /stream/w_am_metaldetector.ydr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/stream/w_am_metaldetector.ydr -------------------------------------------------------------------------------- /stream/w_am_metaldetector.ytd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/stream/w_am_metaldetector.ytd -------------------------------------------------------------------------------- /stream/gen_w_am_metaldetector.ytyp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasmaFPS/qb-metaldetecting/HEAD/stream/gen_w_am_metaldetector.ytyp -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | 4 | author 'plasma#2782 & EU ENVY#9641' 5 | description 'In-Depth & Multi-Feature QB Metal Detecting Script' 6 | repo 'https://github.com/plasmaFPS/qb-metaldetector' 7 | version '1.0' 8 | 9 | file 'gen_w_am_metaldetector.ytyp' 10 | 11 | client_scripts { 12 | 'client/**.lua', 13 | '@PolyZone/client.lua', 14 | '@PolyZone/BoxZone.lua', 15 | '@PolyZone/EntityZone.lua', 16 | '@PolyZone/CircleZone.lua', 17 | '@PolyZone/ComboZone.lua' 18 | } 19 | 20 | server_script 'server/sv_main.lua' 21 | shared_script 'config.lua' 22 | -------------------------------------------------------------------------------- /client/cl_target.lua: -------------------------------------------------------------------------------- 1 | local QBCore = exports['qb-core']:GetCoreObject() 2 | 3 | CreateThread(function() 4 | exports['qb-target']:SpawnPed({ 5 | model = Config.CommonPed, 6 | coords = Config.CommonPedLocation, 7 | minusOne = true, 8 | freeze = true, 9 | invincible = true, 10 | blockevents = true, 11 | scenario = 'WORLD_HUMAN_DRUG_DEALER', 12 | target = { 13 | options = { 14 | { 15 | type="client", 16 | event = "qb-metaldetector:CommonTradingMenu", 17 | icon = "fas fa-user-secret", 18 | label = "Trade your Finds" 19 | } 20 | }, 21 | distance = 2.5, 22 | }, 23 | }) 24 | 25 | exports['qb-target']:SpawnPed({ 26 | model = Config.RarePed, 27 | coords = Config.RarePedLocation, 28 | minusOne = true, 29 | freeze = true, 30 | invincible = true, 31 | blockevents = true, 32 | scenario = 'WORLD_HUMAN_DRUG_DEALER', 33 | target = { 34 | options = { 35 | { 36 | type = "client", 37 | event = "qb-metaldetector:RareTradingMenu", 38 | icon = "fas fa-user-secret", 39 | label = "Trade your Rare Finds" 40 | } 41 | }, 42 | distance = 2.5, 43 | }, 44 | }) 45 | end) 46 | -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | Config = {} 2 | 3 | -- display polyzones (green boxes) 4 | Config.DebugPoly = false 5 | 6 | -- common trade ped location & ped hash 7 | Config.CommonPedLocation = vector4(-1158.44, -1986.14, 13.16, 322.02) 8 | Config.CommonPed = 'mp_m_forgery_01' 9 | 10 | -- rare trade ped location & ped hash 11 | Config.RarePedLocation = vector4(-2085.17, -1017.98, 12.78, 74.19) 12 | Config.RarePed = 'mp_m_weapexp_01' 13 | 14 | -- the amount of time it takes to detect items. (progressbar) 15 | Config.DetectTime = math.random(6000, 10000) 16 | 17 | -- if doesnt land on common or rare you get nothing. 18 | -- 70% chance of receiving common item. 19 | Config.CommonChance = 70 20 | 21 | -- 5% chance of receiving rare item. 22 | Config.RareChance = 95 23 | 24 | -- The amount of common items received when detected. 25 | Config.CommonAmount = math.random(1,5) 26 | 27 | -- The amount of rare items received when detected. 28 | Config.RareAmount = 1 29 | 30 | -- %6 chance of overheating. 31 | Config.OverheatChance = 6 32 | 33 | -- how long the detecter gets overheated for 34 | Config.OverheatTime = math.random(50000, 60000) 35 | 36 | -- list of common items detectable 37 | Config.CommonItems = { 38 | 'metaltrash', 39 | 'irontrash', 40 | 'bulletcasings', 41 | 'aluminumcan', 42 | 'steeltrash', 43 | 'brokenknife', 44 | 'brokendetector', 45 | 'brokenphone', 46 | 'housekeys', 47 | } 48 | 49 | -- list of rare items detectable 50 | Config.RareItems = { 51 | 'burriedtreasure', 52 | 'treasurekey', 53 | 'antiquecoin', 54 | 'goldennugget', 55 | 'goldcoin', 56 | 'ancientcoin', 57 | 'ww2relic', 58 | 'brokengamboy', 59 | 'pocketwatch', 60 | } 61 | 62 | -- metal detection zones 63 | Config.DetectZones = { 64 | [1] = { 65 | label = "PierBeach", 66 | zones = { 67 | vector2(-1215.8862304688, -1763.9927978516), 68 | vector2(-1261.4217529297, -1830.6840820312), 69 | vector2(-1612.1901855469, -1141.1480712891), 70 | vector2(-1586.1876220703, -1071.6724853516), 71 | vector2(-1422.1868896484, -1110.5142822266), 72 | vector2(-1405.5825195312, -1395.3377685547), 73 | vector2(-1323.0729980469, -1605.9655761719) 74 | }, 75 | }, 76 | [2] = { 77 | label = "PierBeach2", 78 | zones = { 79 | vector2(-1679.6752929688, -981.88470458984), 80 | vector2(-1679.6752929688, -981.88470458984), 81 | vector2(-1717.31640625, -1063.8728027344), 82 | vector2(-2113.6811523438, -554.88806152344), 83 | vector2(-2057.0686035156, -503.62591552734), 84 | vector2(-1848.9615478516, -657.43768310547), 85 | vector2(-1752.3885498047, -741.12536621094), 86 | vector2(-1729.9864501953, -918.60015869141) 87 | }, 88 | }, 89 | [3] = { 90 | label = "Golf Course", 91 | zones = { 92 | vector2(-1075.5496826172, -145.32153320312), 93 | vector2(-1324.7716064453, 23.515180587769), 94 | vector2(-1338.4162597656, 183.1936340332), 95 | vector2(-1109.5949707031, 219.35273742676), 96 | vector2(-975.8134765625, -25.266059875488) 97 | }, 98 | }, 99 | } 100 | 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qb-metaldetecting 2 | An in-depth & multi-feature metal detecting script made for the qbcore framework. 3 | This is my first release, I would appreciate all feedback good or bad. Feel free PR this repository with any improvements you suggest. 4 | Made by plasma#2782 & EU ENVY#9641. 5 | 6 | ## Video Preview 7 | https://www.youtube.com/watch?v=4cd9LtAMNZM 8 | 9 | ## Dependencies 10 | - **qb-core** 11 | - **qb-menu** 12 | - **qb-target** 13 | - **PolyZone** 14 | 15 | ## Features 16 | - Easy to understand config with options for script customization. 17 | - Detector Overheat Chance 18 | - Common & Rare Item Chances 19 | - Peds for Common & Rare Item Trade / Sales (can disable) 20 | - Custom Prop with animations 21 | - Easily configurable detect locations using PolyZones 22 | 23 | ## Future Updates 24 | - Add sell values to config 25 | - Add locales system 26 | 27 | ## Credits 28 | - Inspiration - **fivem-prospecting** & **al-metaldetector** 29 | - Custom Prop made by **Vartanyan** Converted to RAGE by **glitchdetector** (**CC BY-ND 3.0**) 30 | 31 | ## License 32 | **GNU General Public License v3.0** 33 | 34 | ## Inserts (Shops / Items) 35 | 36 | **1.** Insert the images located in the [IMAGES] folder into your inventories html > images directory. 37 | 38 | **2. (Optional)** If you would like the metal detector purchaseable from a shop: 39 | - Insert this line into your qb-shops > config.lua (wherever you want it), ensure you change the array index & slot #'s to match your config. 40 | 41 |
[1] = {
42 | name = "metaldetector",
43 | price = 500,
44 | amount = 50,
45 | info = {},
46 | type = "item",
47 | slot = 1
48 | },
49 |
50 | **3.** Insert this list of items in your qb-core > shared > items.lua
51 | -- qb-metaldetecting
52 |
53 | ["metaldetector"] = {
54 | ["name"] = "metaldetector",
55 | ["label"] = "Metal Detector",
56 | ["weight"] = 200,
57 | ["type"] = "item",
58 | ["image"] = "metaldetector.png",
59 | ["unique"] = false,
60 | ["useable"] = true,
61 | ["shouldClose"] = true,
62 | ["combinable"] = nil,
63 | ["description"] = "Detect Metal beep"
64 | },
65 |
66 | -- common detectable items
67 | ["metaltrash"] = {
68 | ["name"] = "metaltrash",
69 | ["label"] = "Metal Trash",
70 | ["weight"] = 200,
71 | ["type"] = "item",
72 | ["image"] = "metaltrash.png",
73 | ["unique"] = false,
74 | ["useable"] = false,
75 | ["shouldClose"] = false,
76 | ["combinable"] = nil,
77 | ["description"] = "Trashed Metal"
78 | },
79 | ["irontrash"] = {
80 | ["name"] = "irontrash",
81 | ["label"] = "Iron Trash",
82 | ["weight"] = 200,
83 | ["type"] = "item",
84 | ["image"] = "irontrash.png",
85 | ["unique"] = false,
86 | ["useable"] = false,
87 | ["shouldClose"] = false,
88 | ["combinable"] = nil,
89 | ["description"] = "Trashed Iron"
90 | },
91 | ["bulletcasings"] = {
92 | ["name"] = "bulletcasings",
93 | ["label"] = "Bullet Casings",
94 | ["weight"] = 200,
95 | ["type"] = "item",
96 | ["image"] = "bulletcasings.png",
97 | ["unique"] = false,
98 | ["useable"] = false,
99 | ["shouldClose"] = false,
100 | ["combinable"] = nil,
101 | ["description"] = "Bullet Casings"
102 | },
103 | ["aluminumcan"] = {
104 | ["name"] = "aluminumcan",
105 | ["label"] = "Aluminium Can",
106 | ["weight"] = 200,
107 | ["type"] = "item",
108 | ["image"] = "aluminiumcan.png",
109 | ["unique"] = false,
110 | ["useable"] = false,
111 | ["shouldClose"] = false,
112 | ["combinable"] = nil,
113 | ["description"] = "Alumunim Cans"
114 | },
115 | ["brokenknife"] = {
116 | ["name"] = "brokenknife",
117 | ["label"] = "Broken Knife",
118 | ["weight"] = 200,
119 | ["type"] = "item",
120 | ["image"] = "brokenknife.png",
121 | ["unique"] = false,
122 | ["useable"] = false,
123 | ["shouldClose"] = false,
124 | ["combinable"] = nil,
125 | ["description"] = "Rusted Knife"
126 | },
127 | ["brokendetector"] = {
128 | ["name"] = "brokendetector",
129 | ["label"] = "Broken Detector",
130 | ["weight"] = 200,
131 | ["type"] = "item",
132 | ["image"] = "brokendetector.png",
133 | ["unique"] = false,
134 | ["useable"] = false,
135 | ["shouldClose"] = false,
136 | ["combinable"] = nil,
137 | ["description"] = "A broken metal detector"
138 | },
139 | ["brokenphone"] = {
140 | ["name"] = "brokenphone",
141 | ["label"] = "Broken Phone",
142 | ["weight"] = 200,
143 | ["type"] = "item",
144 | ["image"] = "brokenphone.png",
145 | ["unique"] = false,
146 | ["useable"] = false,
147 | ["shouldClose"] = false,
148 | ["combinable"] = nil,
149 | ["description"] = "Broken Phone"
150 | },
151 | ["housekeys"] = {
152 | ["name"] = "housekeys",
153 | ["label"] = "House Keys",
154 | ["weight"] = 200,
155 | ["type"] = "item",
156 | ["image"] = "housekeys.png",
157 | ["unique"] = false,
158 | ["useable"] = false,
159 | ["shouldClose"] = false,
160 | ["combinable"] = nil,
161 | ["description"] = "Random House Keys"
162 | },
163 |
164 | -- rare detectable items
165 |
166 | ["brokengameboy"] = {
167 | ["name"] = "brokengameboy",
168 | ["label"] = "Broken Gameboy",
169 | ["weight"] = 200,
170 | ["type"] = "item",
171 | ["image"] = "brokengameboy.png",
172 | ["unique"] = false,
173 | ["useable"] = false,
174 | ["shouldClose"] = false,
175 | ["combinable"] = nil,
176 | ["description"] = "A Broken Gameboy"
177 | },
178 | ["burriedtreasure"] = {
179 | ["name"] = "burriedtreasure",
180 | ["label"] = "Burried treasure",
181 | ["weight"] = 200,
182 | ["type"] = "item",
183 | ["image"] = "burriedtreasure.png",
184 | ["unique"] = false,
185 | ["useable"] = false,
186 | ["shouldClose"] = false,
187 | ["combinable"] = nil,
188 | ["description"] = "Burried Treasure, woah"
189 | },
190 | ["treasurekey"] = {
191 | ["name"] = "treasurekey",
192 | ["label"] = "Treasure key",
193 | ["weight"] = 200,
194 | ["type"] = "item",
195 | ["image"] = "treasurekey.png",
196 | ["unique"] = false,
197 | ["useable"] = false,
198 | ["shouldClose"] = false,
199 | ["combinable"] = nil,
200 | ["description"] = "A key? Maybe for treasure"
201 | },
202 | ["antiquecoin"] = {
203 | ["name"] = "antiquecoin",
204 | ["label"] = "Antique Coin",
205 | ["weight"] = 200,
206 | ["type"] = "item",
207 | ["image"] = "antiquecoin.png",
208 | ["unique"] = false,
209 | ["useable"] = false,
210 | ["shouldClose"] = false,
211 | ["combinable"] = nil,
212 | ["description"] = "This seems old..."
213 | },
214 | ["goldennugget"] = {
215 | ["name"] = "goldennugget",
216 | ["label"] = "The Mojave Nugget",
217 | ["weight"] = 200,
218 | ["type"] = "item",
219 | ["image"] = "goldnugget.png",
220 | ["unique"] = false,
221 | ["useable"] = false,
222 | ["shouldClose"] = false,
223 | ["combinable"] = nil,
224 | ["description"] = "This seems valuable, hmm"
225 | },
226 | ["goldcoin"] = {
227 | ["name"] = "goldcoin",
228 | ["label"] = "Gold coin",
229 | ["weight"] = 200,
230 | ["type"] = "item",
231 | ["image"] = "goldcoin.png",
232 | ["unique"] = false,
233 | ["useable"] = false,
234 | ["shouldClose"] = false,
235 | ["combinable"] = nil,
236 | ["description"] = "o.O GOLD!"
237 | },
238 | ["ancientcoin"] = {
239 | ["name"] = "ancientcoin",
240 | ["label"] = "Ancient Coin",
241 | ["weight"] = 200,
242 | ["type"] = "item",
243 | ["image"] = "aincientcoin.png",
244 | ["unique"] = false,
245 | ["useable"] = false,
246 | ["shouldClose"] = false,
247 | ["combinable"] = nil,
248 | ["description"] = "This seems really old and unique."
249 | },
250 | ["ww2relic"] = {
251 | ["name"] = "ww2relic",
252 | ["label"] = "WW2 Relic",
253 | ["weight"] = 200,
254 | ["type"] = "item",
255 | ["image"] = "ww2relic.png",
256 | ["unique"] = false,
257 | ["useable"] = false,
258 | ["shouldClose"] = false,
259 | ["combinable"] = nil,
260 | ["description"] = "I rememeber this from history class."
261 | },
262 | ["steeltrash"] = {
263 | ["name"] = "steeltrash",
264 | ["label"] = "Steel Trash",
265 | ["weight"] = 200,
266 | ["type"] = "item",
267 | ["image"] = "steelcan.png",
268 | ["unique"] = false,
269 | ["useable"] = false,
270 | ["shouldClose"] = false,
271 | ["combinable"] = nil,
272 | ["description"] = "A steel can"
273 | },
274 | ["pocketwatch"] = {
275 | ["name"] = "pocketwatch",
276 | ["label"] = "Pocket Watch",
277 | ["weight"] = 200,
278 | ["type"] = "item",
279 | ["image"] = "pocketwatch.png",
280 | ["unique"] = false,
281 | ["useable"] = false,
282 | ["shouldClose"] = true,
283 | ["combinable"] = nil,
284 | ["description"] = "A pocket watch"
285 | },
286 |
287 | -- other items
288 | ["gameboy"] = {
289 | ["name"] = "gameboy",
290 | ["label"] = "Gameboy",
291 | ["weight"] = 200,
292 | ["type"] = "item",
293 | ["image"] = "gameboy.png",
294 | ["unique"] = false,
295 | ["useable"] = false,
296 | ["shouldClose"] = true,
297 | ["combinable"] = nil,
298 | ["description"] = "A working Gameboy."
299 | }
300 |
301 |
--------------------------------------------------------------------------------
/client/cl_main.lua:
--------------------------------------------------------------------------------
1 | local QBCore = exports['qb-core']:GetCoreObject()
2 | local ent
3 | local pos
4 | local animdict
5 | local anim
6 | local breakchance
7 | local overheated = false
8 |
9 | local boneoffsets = {
10 | ["w_am_digiscanner"] = {
11 | bone = 18905,
12 | offset = vector3(0.15, 0.1, 0.0),
13 | rotation = vector3(270.0, 90.0, 80.0),
14 | },
15 | }
16 |
17 | local function AttachEntity(ped, model)
18 | if boneoffsets[model] then
19 | QBCore.Functions.LoadModel(model)
20 | pos = GetEntityCoords(PlayerPedId())
21 | ent = CreateObjectNoOffset(model, pos, 1, 1, 0)
22 | AttachEntityToEntity(ent, ped, GetPedBoneIndex(ped, boneoffsets[model].bone), boneoffsets[model].offset, boneoffsets[model].rotation, 1, 1, 0, 0, 2, 1)
23 | end
24 | end
25 |
26 | RegisterNetEvent('qb-metaldetecting:startdetect', function(data)
27 | if inZone == 1 then
28 | if not overheated then
29 | QBCore.Functions.Progressbar('start_detect', 'Detecting...', Config.DetectTime, false, true, { -- Name | Label | Time | useWhileDead | canCancel
30 | disableMovement = false,
31 | disableCarMovement = true,
32 | disableMouse = false,
33 | disableCombat = true,
34 | }, {
35 | animDict = 'mini@golfai',
36 | anim = 'wood_idle_a',
37 | flags = 49,
38 | }, {}, {}, function()
39 | TriggerServerEvent("InteractSound_SV:PlayWithinDistance", 10, 'metaldetector', 0.2)
40 | Wait(2000)
41 | TriggerServerEvent('qb-metaldetecting:DetectReward')
42 | breakchance = math.random(1,100)
43 | if breakchance <= Config.OverheatChance then
44 | overheated = true
45 | QBCore.Functions.Notify('Your metal detector has overheated! Let it cool down.', 'error', 4000)
46 | Wait(Config.OverheatTime)
47 | overheated = false
48 | QBCore.Functions.Notify('Your metal detector has cooled down.', 'primary', 4000)
49 | end
50 | end, function()
51 | Wait(100)
52 | end)
53 | else
54 | QBCore.Functions.Notify('Your metal detector is still too hot!', 'error', 5000)
55 | end
56 | else
57 | QBCore.Functions.Notify('You cannot detect here. Find a suitable location.', 'error', 5000)
58 | end
59 | end)
60 |
61 | CreateThread(function()
62 | for k, v in pairs(Config.DetectZones) do
63 | local MetalZone = PolyZone:Create(v.zones, {
64 | name = v.label,
65 | debugPoly = Config.DebugPoly
66 | })
67 |
68 | MetalZone:onPlayerInOut(function(isPointInside)
69 | if isPointInside then
70 | inZone = 1
71 | QBCore.Functions.TriggerCallback('QBCore:HasItem', function(HasItem)
72 | if HasItem then
73 | AttachEntity(PlayerPedId(), "w_am_digiscanner")
74 | end
75 | end, 'metaldetector')
76 | else
77 | inZone = 0
78 | DetachEntity(ent, 0, 0)
79 | DeleteEntity(ent)
80 | end
81 | end)
82 | end
83 | end)
84 |
85 | -- Common Trade Menu --
86 |
87 | RegisterNetEvent('qb-metaldetector:CommonTradingMenu', function(data)
88 | exports['qb-menu']:openMenu({
89 | {
90 | id = 1,
91 | header = "Common Material Trade",
92 | txt = ""
93 | },
94 | {
95 | id = 2,
96 | header = "Metal Trash",
97 | txt = "Trade 50 Metal Trash for 30 Metal Scrap!",
98 | params = {
99 | isServer = true,
100 | event = "qb-metaldetector:server:CommonTrade",
101 | args = {
102 | id = 2,
103 | item = 'metaltrash'
104 | }
105 | }
106 | },
107 | {
108 | id = 3,
109 | header = "Iron Trash",
110 | txt = "Trade 50 Iron Trash for 30 Iron",
111 | params = {
112 | isServer = true,
113 | event = "qb-metaldetector:server:CommonTrade",
114 | args = {
115 | id = 3,
116 | item = 'irontrash'
117 | }
118 | }
119 | },
120 | {
121 | id = 4,
122 | header = "Bullet Casings",
123 | txt = "Trade 50 Bullet Casings for 30 Copper!",
124 | params = {
125 | isServer = true,
126 | event = "qb-metaldetector:server:CommonTrade",
127 | args = {
128 | id = 4,
129 | item = 'bulletcasings'
130 | }
131 | }
132 | },
133 | {
134 | id = 5,
135 | header = "Aluminum Cans",
136 | txt = "Trade 50 Aluminum Cans for 30 Aluminium",
137 | params = {
138 | isServer = true,
139 | event = "qb-metaldetector:server:CommonTrade",
140 | args = {
141 | id = 5,
142 | item = 'aluminumcan'
143 | }
144 | }
145 | },
146 | {
147 | id = 6,
148 | header = "Steel Trash",
149 | txt = "Trade 50 Steel Trash for 25 Steel!",
150 | params = {
151 | isServer = true,
152 | event = "qb-metaldetector:server:CommonTrade",
153 | args = {
154 | id = 6,
155 | item = 'steeltrash'
156 | }
157 | }
158 | },
159 | {
160 | id = 7,
161 | header = "Broken Knives",
162 | txt = "Trade 5 Broken Knives for a Dagger!",
163 | params = {
164 | isServer = true,
165 | event = "qb-metaldetector:server:CommonTrade",
166 | args = {
167 | id = 7,
168 | item = 'brokenknife'
169 | }
170 | }
171 | },
172 | {
173 | id = 8,
174 | header = "Broken Metal Detectors",
175 | txt = "Trade 1 Broken Metal Detectors for $30!",
176 | params = {
177 | isServer = true,
178 | event = "qb-metaldetector:server:CommonTrade",
179 | args = {
180 | id = 8,
181 | item = 'brokendetector'
182 | }
183 | }
184 | },
185 | {
186 | id = 9,
187 | header = "House Keys",
188 | txt = "Trade 50 House Keys for 30 Copper!",
189 | params = {
190 | isServer = true,
191 | event = "qb-metaldetector:server:CommonTrade",
192 | args = {
193 | id = 9,
194 | item = 'housekeys'
195 | }
196 | }
197 | },
198 | {
199 | id = 10,
200 | header = "Broken Phones",
201 | txt = "Trade 1 Broken Phones for $25!",
202 | params = {
203 | isServer = true,
204 | event = "qb-metaldetector:server:CommonTrade",
205 | args = {
206 | id = 10,
207 | item = 'brokenphone'
208 | }
209 | }
210 | },
211 | })
212 | end)
213 |
214 | -- Rare Trade Menu --
215 |
216 | RegisterNetEvent('qb-metaldetector:RareTradingMenu', function(data)
217 | exports['qb-menu']:openMenu({
218 | {
219 | id = 1,
220 | header = "Rare Material Trade",
221 | txt = ""
222 | },
223 | {
224 | id = 2,
225 | header = "Burried Treasure",
226 | txt = "Trade 1 Burried Treasure for $10,000!",
227 | params = {
228 | isServer = true,
229 | event = "qb-metaldetector:server:RareTrade",
230 | args = {
231 | id = 2,
232 | item = 'burriedtreasure'
233 | }
234 | }
235 | },
236 | {
237 | id = 3,
238 | header = "Treasure Key",
239 | txt = "Trade 1 Treasure Key for $1,500!",
240 | params = {
241 | isServer = true,
242 | event = "qb-metaldetector:server:RareTrade",
243 | args = {
244 | id = 3,
245 | item = 'treasurekey'
246 | }
247 | }
248 | },
249 | {
250 | id = 4,
251 | header = "Antique Coin",
252 | txt = "Trade 1 Antique Coin for $500!",
253 | params = {
254 | isServer = true,
255 | event = "qb-metaldetector:server:RareTrade",
256 | args = {
257 | id = 4,
258 | item = 'antiquecoin'
259 | }
260 | }
261 | },
262 | {
263 | id = 5,
264 | header = "Golden Nuggets",
265 | txt = "Trade 1 Golden Nuggets $200!",
266 | params = {
267 | isServer = true,
268 | event = "qb-metaldetector:server:RareTrade",
269 | args = {
270 | id = 5,
271 | item = 'goldennugget'
272 | }
273 | }
274 | },
275 | {
276 | id = 6,
277 | header = "Gold Coin",
278 | txt = "Trade 1 Gold Coin for $300!",
279 | params = {
280 | isServer = true,
281 | event = "qb-metaldetector:server:RareTrade",
282 | args = {
283 | id = 6,
284 | item = 'goldcoin'
285 | }
286 | }
287 | },
288 | {
289 | id = 7,
290 | header = "Ancient Coin",
291 | txt = "Trade 1 Ancient Coin for $1000!",
292 | params = {
293 | isServer = true,
294 | event = "qb-metaldetector:server:RareTrade",
295 | args = {
296 | id = 7,
297 | item = 'ancientcoin'
298 | }
299 | }
300 | },
301 | {
302 | id = 8,
303 | header = "WW2 Relic",
304 | txt = "Trade 1 WW2 Relic for $800!",
305 | params = {
306 | isServer = true,
307 | event = "qb-metaldetector:server:RareTrade",
308 | args = {
309 | id = 8,
310 | item = 'ww2relic'
311 | }
312 | }
313 | },
314 | {
315 | id = 9,
316 | header = "Broken Gameboys",
317 | txt = "Trade 10 Broken Gameboys for 1 working Gameboy!",
318 | params = {
319 | isServer = true,
320 | event = "qb-metaldetector:server:RareTrade",
321 | args = {
322 | id = 9,
323 | item = 'brokengameboy'
324 | }
325 | }
326 | },
327 | {
328 | id = 10,
329 | header = "Pocket Watch",
330 | txt = "Trade 1 Pocket watch for $150!",
331 | params = {
332 | isServer = true,
333 | event = "qb-metaldetector:server:RareTrade",
334 | args = {
335 | id = 10,
336 | item = 'pocketwatch'
337 | }
338 | }
339 | },
340 | })
341 | end)
342 |
--------------------------------------------------------------------------------
/server/sv_main.lua:
--------------------------------------------------------------------------------
1 | local QBCore = exports['qb-core']:GetCoreObject()
2 |
3 | -- Create Usable Item --
4 |
5 | QBCore.Functions.CreateUseableItem("metaldetector", function(src, item)
6 | TriggerClientEvent('qb-metaldetecting:startdetect', src)
7 | end)
8 |
9 | -- Detecting Reward --
10 |
11 | RegisterNetEvent('qb-metaldetecting:DetectReward', function()
12 | local src = source
13 | local Player = QBCore.Functions.GetPlayer(src)
14 | local chance = math.random(1,100)
15 |
16 | if chance <= Config.CommonChance then
17 | local item = Config.CommonItems[math.random(1, #Config.CommonItems)]
18 | local amount = Config.CommonAmount
19 |
20 | Player.Functions.AddItem(item, amount)
21 | TriggerClientEvent("inventory:client:ItemBox", src, QBCore.Shared.Items[item], "add")
22 | TriggerClientEvent('QBCore:Notify', src, 'You found '.. item ..'!', 'success')
23 | elseif chance >= Config.RareChance then
24 | local item = Config.RareItems[math.random(1, #Config.RareItems)]
25 | local amount = Config.RareAmount
26 |
27 | Player.Functions.AddItem(item, amount)
28 | TriggerClientEvent("inventory:client:ItemBox", src, QBCore.Shared.Items[item], "add")
29 | TriggerClientEvent('QBCore:Notify', src, 'You found '.. item ..'!', 'success')
30 | else
31 | TriggerClientEvent('QBCore:Notify', src, 'You found nothing..', 'error')
32 | end
33 | end)
34 |
35 | -- Common Trade Event --
36 |
37 | RegisterServerEvent('qb-metaldetector:server:CommonTrade', function(data)
38 | local src = source
39 | local Player = QBCore.Functions.GetPlayer(src)
40 | local item = tostring(data.item)
41 | local check = Player.Functions.GetItemByName(item)
42 |
43 | if data.id == 2 then
44 | if check ~= nil then
45 | if check.amount >= 50 then
46 | Player.Functions.RemoveItem(item, 50)
47 | Player.Functions.AddItem('metalscrap', 30)
48 | TriggerClientEvent('QBCore:Notify', src, 'You traded 50 Metal Trash'..' for 30 Metal Scrap.', 'success')
49 | else
50 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Metal Scrap..", 'error')
51 | end
52 | else
53 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Metal Trash.", 'error')
54 | end
55 | elseif data.id == 3 then
56 | if check ~= nil then
57 | if check.amount >= 50 then
58 | Player.Functions.RemoveItem(item, 50)
59 | Player.Functions.AddItem('iron', 30)
60 | TriggerClientEvent('QBCore:Notify', src, 'You traded 50 Iron Trash'..' for 30 Iron.', 'success')
61 | else
62 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Iron Scrap..", 'error')
63 | end
64 | else
65 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Iron Trash.", 'error')
66 | end
67 | elseif data.id == 4 then
68 | if check ~= nil then
69 | if check.amount >= 50 then
70 | Player.Functions.RemoveItem(item, 50)
71 | Player.Functions.AddItem('copper', 30)
72 | TriggerClientEvent('QBCore:Notify', src, 'You traded 50 Bullet Casings'..' for 30 Bullet Casings.', 'success')
73 | else
74 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Bullet Casings..", 'error')
75 | end
76 | else
77 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Bullet Casings.", 'error')
78 | end
79 | elseif data.id == 5 then
80 | if check ~= nil then
81 | if check.amount >= 50 then
82 | Player.Functions.RemoveItem(item, 50)
83 | Player.Functions.AddItem('aluminum', 30)
84 | TriggerClientEvent('QBCore:Notify', src, 'You traded 50 Aluminum Cans'..' for 30 Aluminum.', 'success')
85 | else
86 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Aluminum Cans..", 'error')
87 | end
88 | else
89 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Aluminum Cans.", 'error')
90 | end
91 | elseif data.id == 6 then
92 | if check ~= nil then
93 | if check.amount >= 50 then
94 | Player.Functions.RemoveItem(item, 50)
95 | Player.Functions.AddItem('steel', 25)
96 | TriggerClientEvent('QBCore:Notify', src, 'You traded 50 Steel Trash'..' for 25 Steel.', 'success')
97 | else
98 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Steel Trash..", 'error')
99 | end
100 | else
101 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Steel Trash.", 'error')
102 | end
103 | elseif data.id == 7 then
104 | if check ~= nil then
105 | if check.amount >= 5 then
106 | Player.Functions.RemoveItem(item, 5)
107 | Player.Functions.AddItem('weapon_dagger', 1)
108 | TriggerClientEvent('QBCore:Notify', src, 'You traded 5 Broken Knives'..' for 1 Dagger.', 'success')
109 | else
110 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Broken Knives..", 'error')
111 | end
112 | else
113 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Broken Knives.", 'error')
114 | end
115 | elseif data.id == 8 then
116 | if check ~= nil then
117 | if check.amount >= 1 then
118 | Player.Functions.RemoveItem(item, 1)
119 | Player.Functions.AddMoney('cash', 30)
120 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 broken Metal Detector'..' for $30.', 'success')
121 | else
122 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Metal Detectors..", 'error')
123 | end
124 | else
125 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Metal Detectors.", 'error')
126 | end
127 | elseif data.id == 9 then
128 | if check ~= nil then
129 | if check.amount >= 50 then
130 | Player.Functions.RemoveItem(item, 50)
131 | Player.Functions.AddItem('copper', 30)
132 | TriggerClientEvent('QBCore:Notify', src, 'You traded 50 House Keys'..' for 30 Copper.', 'success')
133 | else
134 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough House Keys..", 'error')
135 | end
136 | else
137 | TriggerClientEvent('QBCore:Notify', src, "You do not have any House Keys.", 'error')
138 | end
139 | elseif data.id == 10 then
140 | if check ~= nil then
141 | if check.amount >= 1 then
142 | Player.Functions.RemoveItem(item, 1)
143 | Player.Functions.AddMoney('cash', 30)
144 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 Broken Phone'..' for $30.', 'success')
145 | else
146 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Broken Phones..", 'error')
147 | end
148 | else
149 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Broken Phones.", 'error')
150 | end
151 | end
152 | end)
153 |
154 | -- Rare Trade Event --
155 |
156 | RegisterServerEvent('qb-metaldetector:server:RareTrade', function(data)
157 | local src = source
158 | local Player = QBCore.Functions.GetPlayer(src)
159 | local item = tostring(data.item)
160 | local check = Player.Functions.GetItemByName(item)
161 |
162 | if data.id == 2 then
163 | if check ~= nil then
164 | if check.amount >= 1 then
165 | Player.Functions.RemoveItem(item, 1)
166 | Player.Functions.AddMoney('cash', 10000)
167 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 Burried Treasure'..' for $10,000.', 'success')
168 | else
169 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Burried Treasure..", 'error')
170 | end
171 | else
172 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Burried Treasure.", 'error')
173 | end
174 | elseif data.id == 3 then
175 | if check ~= nil then
176 | if check.amount >= 1 then
177 | Player.Functions.RemoveItem(item, 1)
178 | Player.Functions.AddMoney('cash', 1500)
179 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 Treasure Key'..' for $1500.', 'success')
180 | else
181 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Treasure Keys..", 'error')
182 | end
183 | else
184 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Treasure Keys.", 'error')
185 | end
186 | elseif data.id == 4 then
187 | if check ~= nil then
188 | if check.amount >= 1 then
189 | Player.Functions.RemoveItem(item, 1)
190 | Player.Functions.AddMoney('cash', 500)
191 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 Antique Coin'..' for $500.', 'success')
192 | else
193 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Antique Coins..", 'error')
194 | end
195 | else
196 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Antique Coins.", 'error')
197 | end
198 | elseif data.id == 5 then
199 | if check ~= nil then
200 | if check.amount >= 1 then
201 | Player.Functions.RemoveItem(item, 1)
202 | Player.Functions.AddMoney('cash', 200)
203 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 Golden Nugget'..' for $200.', 'success')
204 | else
205 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Golden Nuggets..", 'error')
206 | end
207 | else
208 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Golden Nuggets.", 'error')
209 | end
210 | elseif data.id == 6 then
211 | if check ~= nil then
212 | if check.amount >= 1 then
213 | Player.Functions.RemoveItem(item, 1)
214 | Player.Functions.AddMoney('cash', 300)
215 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 Gold Coin'..' for $300.', 'success')
216 | else
217 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Gold Coins..", 'error')
218 | end
219 | else
220 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Gold Coins.", 'error')
221 | end
222 | elseif data.id == 7 then
223 | if check ~= nil then
224 | if check.amount >= 1 then
225 | Player.Functions.RemoveItem(item, 1)
226 | Player.Functions.AddMoney('cash', 1000)
227 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 Antique Coin'..' for $1000.', 'success')
228 | else
229 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Antique Coins..", 'error')
230 | end
231 | else
232 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Antique Coins.", 'error')
233 | end
234 | elseif data.id == 8 then
235 | if check ~= nil then
236 | if check.amount >= 1 then
237 | Player.Functions.RemoveItem(item, 1)
238 | Player.Functions.AddMoney('cash', 800)
239 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 WW2 Coin'..' for $800.', 'success')
240 | else
241 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough WW2 Coins..", 'error')
242 | end
243 | else
244 | TriggerClientEvent('QBCore:Notify', src, "You do not have any WW2 Coins.", 'error')
245 | end
246 | elseif data.id == 9 then
247 | if check ~= nil then
248 | if check.amount >= 10 then
249 | Player.Functions.RemoveItem(item, 10)
250 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['gameboy'], 'add')
251 | Player.Functions.AddItem('gameboy', 1)
252 | TriggerClientEvent('QBCore:Notify', src, 'You traded 10 Broken Gameboys'..' for 1 working Gameboy.', 'success')
253 | else
254 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Broken Gameboys..", 'error')
255 | end
256 | else
257 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Broken Gameboys.", 'error')
258 | end
259 | elseif data.id == 10 then
260 | if check ~= nil then
261 | if check.amount >= 1 then
262 | Player.Functions.RemoveItem(item, 1)
263 | Player.Functions.AddMoney('cash', 150)
264 | TriggerClientEvent('QBCore:Notify', src, 'You traded 1 Pocket Watch'..' for $150.', 'success')
265 | else
266 | TriggerClientEvent('QBCore:Notify', src, "You don't have enough Pocket Watches..", 'error')
267 | end
268 | else
269 | TriggerClientEvent('QBCore:Notify', src, "You do not have any Pocket Watches.", 'error')
270 | end
271 | end
272 | end)
273 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.