├── .gitattributes
├── README.md
├── client
└── client.lua
├── config.lua
├── fxmanifest.lua
├── images
├── dontblockintersectionsign.png
├── leftturnsign.png
├── noparkingsign.png
├── notrespassingsign.png
├── rightturnsign.png
├── stopsign.png
├── uturnsign.png
├── walkingmansign.png
└── yieldsign.png
└── server
└── server.lua
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | ### ps-signrobbery
4 | A unique script that gives you the ability to pick up, hold and steal signs around the map while also being able to trade them for materials.
5 |
6 | 
7 |
8 | ### Dependencies:
9 | * [qb-target](https://github.com/BerkieBb/qb-target)
10 | * [ps-ui](https://github.com/Project-Sloth/ps-ui)
11 | * [dpemotes](https://github.com/andristum/dpemotes)
12 |
13 |
14 |
15 |
16 | 
17 |
18 |
19 | ### Start installing now
20 | We will now provide you with a step-by-step guide for the installation process. Shouldn't take too long and it shouldn't be too confusing either!
21 |
22 | ### Step 1:
23 | Go ahead and start by dragging and dropping ps-signrobbery into your designated resources folder.
24 |
25 | If you are still lost, Slothy has created a few GIF's to help guide you through all the installation steps.
26 |
27 | 
28 |
29 |
30 | ### Step 2:
31 | Open the ps-signrobbery resource you just implemented in your resources folder and navigate to **ps-signrobbery/images** then copy those images inside **qb-inventory/html/images**
32 |
33 | 
34 |
35 | ### Step 3:
36 | Open your entire resources folder with Visual Studio Code (or whichever program you use) and navigate to **qb-core/shared/items.lua**
37 |
38 | ```lua
39 | ["stopsign"] = {["name"] = "stopsign", ["label"] = "Stop Sign", ["weight"] = 1, ["type"] = "item", ["image"] = "stopsign.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Stop Sign"},
40 | ["walkingmansign"] = {["name"] = "walkingmansign", ["label"] = "Pedestrian Sign", ["weight"] = 1, ["type"] = "item", ["image"] = "walkingmansign.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Pedestrian Sign"},
41 | ["dontblockintersectionsign"] = {["name"] = "dontblockintersectionsign", ["label"] = "Intersection Sign", ["weight"] = 1, ["type"] = "item", ["image"] = "dontblockintersectionsign.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Intersection Sign"},
42 | ["uturnsign"] = {["name"] = "uturnsign", ["label"] = "U Turn Sign", ["weight"] = 1, ["type"] = "item", ["image"] = "uturnsign.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "U Turn Sign"},
43 | ["noparkingsign"] = {["name"] = "noparkingsign", ["label"] = "No Parking Sign", ["weight"] = 1, ["type"] = "item", ["image"] = "noparkingsign.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "No Parking Sign"},
44 | ["leftturnsign"] = {["name"] = "leftturnsign", ["label"] = "Left Turn Sign", ["weight"] = 1, ["type"] = "item", ["image"] = "leftturnsign.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Left Turn Sign"},
45 | ["rightturnsign"] = {["name"] = "rightturnsign", ["label"] = "Right Turn Sign", ["weight"] = 1, ["type"] = "item", ["image"] = "rightturnsign.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Right Turn Sign"},
46 | ["notrespassingsign"] = {["name"] = "notrespassingsign", ["label"] = "No Trespassing Sign", ["weight"] = 1, ["type"] = "item", ["image"] = "notrespassingsign.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "No Trespassing Sign"},
47 | ["yieldsign"] = {["name"] = "yieldsign", ["label"] = "Yield Sign", ["weight"] = 1, ["type"] = "item", ["image"] = "yieldsign.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Yield Sign"},
48 | ```
49 |
50 | Then copy this snippet above and paste it at the very bottom of file as shown in the GIF
51 |
52 | 
53 |
54 |
55 |
56 |
57 |
58 | 
59 |
60 |
61 | #### Some features to mention within this ps-signrobbery:
62 | * Steal signs found around the map
63 | * Hold signs and use them as an emote
64 | * Trade signs for materials in return
65 |
66 |
67 |
68 |
69 | 
70 |
71 |
72 | ### Time to show you what it looks like!
73 | Here's a few showcased examples while using ps-signrobbery.
74 |
75 | #### Steal signs:
76 | 
77 |
78 | #### Hold signs:
79 | 
80 |
81 | #### Minigame for stealing signs:
82 | 
83 |
84 | ### Credits:
85 | Huge thanks to [Hyper](https://github.com/itsHyper) and [Snipe (pushkart2)](https://github.com/pushkart2) This release wouldn't be possible without them.
86 |
--------------------------------------------------------------------------------
/client/client.lua:
--------------------------------------------------------------------------------
1 | local QBCore = exports['qb-core']:GetCoreObject()
2 | local objects = {}
3 | local holdingSign = false
4 |
5 | AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
6 | QBCore.Functions.TriggerCallback('qb-signrobbery:server:GetObjects', function(incObjects)
7 | objects = incObjects
8 | end)
9 | end)
10 |
11 | --Functions
12 | local function AlertCops()
13 | -- README: UNCOMMENT WHICHEVER ALERT YOU WANNA USE UNLESS YOU USE A DIFFERENT ALERT SYSTEM
14 | --TriggerServerEvent('police:server:policeAlert', 'Sign being stolen') -- Default QBCore Dispatch
15 | --exports['ps-dispatch']:SignRobbery() -- ps-dispatch
16 | end
17 |
18 | local function loadAnimDict(dict)
19 | while (not HasAnimDictLoaded(dict)) do
20 | RequestAnimDict(dict)
21 | Citizen.Wait(1)
22 | end
23 | end
24 |
25 | local function LoadPropDict(model)
26 | while not HasModelLoaded(GetHashKey(model)) do
27 | RequestModel(GetHashKey(model))
28 | Wait(10)
29 | end
30 | end
31 |
32 |
33 | --Events
34 | RegisterNetEvent("qb-signrobbery:client:StopSign", function(data)
35 | local ped = PlayerPedId()
36 | exports['ps-ui']:Circle(function(success)
37 | if success then
38 | loadAnimDict("amb@prop_human_bum_bin@base")
39 | TaskPlayAnim(ped, "amb@prop_human_bum_bin@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
40 | QBCore.Functions.Progressbar("robbing_sign", "Stealing Stop Sign..", math.random(5000, 7000), false, true, {
41 | disableMovement = true,
42 | disableCarMovement = true,
43 | disableMouse = false,
44 | disableCombat = true,
45 | }, {}, {}, function()
46 | end, function()
47 | local coords = GetEntityCoords(data.entity)
48 | SetEntityAsMissionEntity(data.entity, true, true)
49 | StopAnimTask(ped, "amb@prop_human_bum_bin@base", "base", 1.0)
50 | DeleteEntity(data.entity)
51 | local object = {coords = coords, model = -949234773}
52 | TriggerServerEvent("qb-signrobbery:server:delete", object)
53 | AlertCops()
54 | end)
55 | end
56 | end, 2, 6)
57 | end)
58 |
59 | RegisterNetEvent("qb-signrobbery:client:WalkingManSign", function(data)
60 | local ped = PlayerPedId()
61 | exports['ps-ui']:Circle(function(success)
62 | if success then
63 | loadAnimDict("amb@prop_human_bum_bin@base")
64 | TaskPlayAnim(ped, "amb@prop_human_bum_bin@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
65 | QBCore.Functions.Progressbar("robbing_sign", "Stealing Pedestrian Sign..", math.random(5000, 7000), false, true, {
66 | disableMovement = true,
67 | disableCarMovement = true,
68 | disableMouse = false,
69 | disableCombat = true,
70 | }, {}, {}, function()
71 | end, function()
72 | local coords = GetEntityCoords(data.entity)
73 | SetEntityAsMissionEntity(data.entity, true, true)
74 | StopAnimTask(ped, "amb@prop_human_bum_bin@base", "base", 1.0)
75 | DeleteEntity(data.entity)
76 | local object = {coords = coords, model = 1502931467}
77 | TriggerServerEvent("qb-signrobbery:server:delete", object)
78 | AlertCops()
79 | end)
80 | end
81 | end, 2, 6)
82 | end)
83 |
84 | RegisterNetEvent("qb-signrobbery:client:DontBlockIntersectionSign", function(data)
85 | local ped = PlayerPedId()
86 | exports['ps-ui']:Circle(function(success)
87 | if success then
88 | loadAnimDict("amb@prop_human_bum_bin@base")
89 | TaskPlayAnim(ped, "amb@prop_human_bum_bin@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
90 | QBCore.Functions.Progressbar("robbing_sign", "Stealing Intersection Sign..", math.random(5000, 7000), false, true, {
91 | disableMovement = true,
92 | disableCarMovement = true,
93 | disableMouse = false,
94 | disableCombat = true,
95 | }, {}, {}, function()
96 | end, function()
97 | local coords = GetEntityCoords(data.entity)
98 | SetEntityAsMissionEntity(data.entity, true, true)
99 | StopAnimTask(ped, "amb@prop_human_bum_bin@base", "base", 1.0)
100 | DeleteEntity(data.entity)
101 | local object = {coords = coords, model = 1191039009}
102 | TriggerServerEvent("qb-signrobbery:server:delete", object)
103 | AlertCops()
104 | end)
105 | end
106 | end, 2, 6)
107 | end)
108 |
109 | RegisterNetEvent("qb-signrobbery:client:UTurnSign", function(data)
110 | local ped = PlayerPedId()
111 | exports['ps-ui']:Circle(function(success)
112 | if success then
113 | loadAnimDict("amb@prop_human_bum_bin@base")
114 | TaskPlayAnim(ped, "amb@prop_human_bum_bin@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
115 | QBCore.Functions.Progressbar("robbing_sign", "Stealing U Turn Sign..", math.random(5000, 7000), false, true, {
116 | disableMovement = true,
117 | disableCarMovement = true,
118 | disableMouse = false,
119 | disableCombat = true,
120 | }, {}, {}, function()
121 | end, function()
122 | local coords = GetEntityCoords(data.entity)
123 | SetEntityAsMissionEntity(data.entity, true, true)
124 | StopAnimTask(ped, "amb@prop_human_bum_bin@base", "base", 1.0)
125 | DeleteEntity(data.entity)
126 | local object = {coords = coords, model = 4138610559}
127 | TriggerServerEvent("qb-signrobbery:server:delete", object)
128 | AlertCops()
129 | end)
130 | end
131 | end, 2, 6)
132 | end)
133 |
134 | RegisterNetEvent("qb-signrobbery:client:NoParkingSign", function(data)
135 | local ped = PlayerPedId()
136 | exports['ps-ui']:Circle(function(success)
137 | if success then
138 | loadAnimDict("amb@prop_human_bum_bin@base")
139 | TaskPlayAnim(ped, "amb@prop_human_bum_bin@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
140 | QBCore.Functions.Progressbar("robbing_sign", "Stealing No Parking Sign..", math.random(5000, 7000), false, true, {
141 | disableMovement = true,
142 | disableCarMovement = true,
143 | disableMouse = false,
144 | disableCombat = true,
145 | }, {}, {}, function()
146 | end, function()
147 | local coords = GetEntityCoords(data.entity)
148 | SetEntityAsMissionEntity(data.entity, true, true)
149 | StopAnimTask(ped, "amb@prop_human_bum_bin@base", "base", 1.0)
150 | DeleteEntity(data.entity)
151 | local object = {coords = coords, model = 3830972543}
152 | TriggerServerEvent("qb-signrobbery:server:delete", object)
153 | AlertCops()
154 | end)
155 | end
156 | end, 2, 6)
157 | end)
158 |
159 | RegisterNetEvent("qb-signrobbery:client:LeftTurnSign", function(data)
160 | local ped = PlayerPedId()
161 | exports['ps-ui']:Circle(function(success)
162 | if success then
163 | loadAnimDict("amb@prop_human_bum_bin@base")
164 | TaskPlayAnim(ped, "amb@prop_human_bum_bin@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
165 | QBCore.Functions.Progressbar("robbing_sign", "Stealing Left Turn Sign..", math.random(5000, 7000), false, true, {
166 | disableMovement = true,
167 | disableCarMovement = true,
168 | disableMouse = false,
169 | disableCombat = true,
170 | }, {}, {}, function()
171 | end, function()
172 | local coords = GetEntityCoords(data.entity)
173 | SetEntityAsMissionEntity(data.entity, true, true)
174 | StopAnimTask(ped, "amb@prop_human_bum_bin@base", "base", 1.0)
175 | DeleteEntity(data.entity)
176 | local object = {coords = coords, model = 2643325436}
177 | TriggerServerEvent("qb-signrobbery:server:delete", object)
178 | AlertCops()
179 | end)
180 | end
181 | end, 2, 6)
182 | end)
183 |
184 | RegisterNetEvent("qb-signrobbery:client:RightTurnSign", function(data)
185 | local ped = PlayerPedId()
186 | exports['ps-ui']:Circle(function(success)
187 | if success then
188 | loadAnimDict("amb@prop_human_bum_bin@base")
189 | TaskPlayAnim(ped, "amb@prop_human_bum_bin@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
190 | QBCore.Functions.Progressbar("robbing_sign", "Stealing Right Turn Sign..", math.random(5000, 7000), false, true, {
191 | disableMovement = true,
192 | disableCarMovement = true,
193 | disableMouse = false,
194 | disableCombat = true,
195 | }, {}, {}, function()
196 | end, function()
197 | local coords = GetEntityCoords(data.entity)
198 | SetEntityAsMissionEntity(data.entity, true, true)
199 | StopAnimTask(ped, "amb@prop_human_bum_bin@base", "base", 1.0)
200 | DeleteEntity(data.entity)
201 | local object = {coords = coords, model = 793482617}
202 | TriggerServerEvent("qb-signrobbery:server:delete", object)
203 | AlertCops()
204 | end)
205 | end
206 | end, 2, 6)
207 | end)
208 |
209 | RegisterNetEvent("qb-signrobbery:client:NoTrespassingSign", function(data)
210 | local ped = PlayerPedId()
211 | exports['ps-ui']:Circle(function(success)
212 | if success then
213 | loadAnimDict("amb@prop_human_bum_bin@base")
214 | TaskPlayAnim(ped, "amb@prop_human_bum_bin@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
215 | QBCore.Functions.Progressbar("robbing_sign", "Stealing No Trespassing Sign..", math.random(5000, 7000), false, true, {
216 | disableMovement = true,
217 | disableCarMovement = true,
218 | disableMouse = false,
219 | disableCombat = true,
220 | }, {}, {}, function()
221 | end, function()
222 | local coords = GetEntityCoords(data.entity)
223 | SetEntityAsMissionEntity(data.entity, true, true)
224 | StopAnimTask(ped, "amb@prop_human_bum_bin@base", "base", 1.0)
225 | DeleteEntity(data.entity)
226 | local object = {coords = coords, model = 1021214550}
227 | TriggerServerEvent("qb-signrobbery:server:delete", object)
228 | AlertCops()
229 | end)
230 | end
231 | end, 2, 6)
232 | end)
233 |
234 | RegisterNetEvent("qb-signrobbery:client:YieldSign", function(data)
235 | local ped = PlayerPedId()
236 | exports['ps-ui']:Circle(function(success)
237 | if success then
238 | loadAnimDict("amb@prop_human_bum_bin@base")
239 | TaskPlayAnim(ped, "amb@prop_human_bum_bin@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
240 | QBCore.Functions.Progressbar("robbing_sign", "Stealing Yield Sign..", math.random(5000, 7000), false, true, {
241 | disableMovement = true,
242 | disableCarMovement = true,
243 | disableMouse = false,
244 | disableCombat = true,
245 | }, {}, {}, function()
246 | end, function()
247 | local coords = GetEntityCoords(data.entity)
248 | SetEntityAsMissionEntity(data.entity, true, true)
249 | StopAnimTask(ped, "amb@prop_human_bum_bin@base", "base", 1.0)
250 | DeleteEntity(data.entity)
251 | local object = {coords = coords, model = 3654973172}
252 | TriggerServerEvent("qb-signrobbery:server:delete", object)
253 | AlertCops()
254 | end)
255 | end
256 | end, 2, 6)
257 | end)
258 |
259 | local prop = nil
260 | function AddPropToPlayerAndAnim(prop1, bone, off1, off2, off3, rot1, rot2, rot3)
261 | loadAnimDict("amb@world_human_janitor@male@base")
262 | local Player = PlayerPedId()
263 | local x,y,z = table.unpack(GetEntityCoords(Player))
264 | if not HasModelLoaded(prop1) then
265 | LoadPropDict(prop1)
266 | end
267 | prop = CreateObject(GetHashKey(prop1), x, y, z+0.2, true, true, true)
268 | AttachEntityToEntity(prop, Player, GetPedBoneIndex(Player, bone), off1, off2, off3, rot1, rot2, rot3, true, true, false, true, 1, true)
269 | SetModelAsNoLongerNeeded(prop1)
270 | TaskPlayAnim(Player, "amb@world_human_janitor@male@base", "base", 8.0, 1.0, -1, 49, 0, 0, 0, 0)
271 |
272 | CreateThread(function()
273 | while holdingSign do
274 | Wait(1000)
275 | if not IsEntityPlayingAnim(PlayerPedId(), "amb@world_human_janitor@male@base", "base", 3) and holdingSign then
276 | holdingSign = false
277 | DeleteEntity(prop)
278 | end
279 | end
280 | end)
281 | end
282 |
283 | --Emote Events
284 | RegisterNetEvent("qb-signrobbery:use:StopSign", function(src)
285 | if not holdingSign then
286 | holdingSign = true
287 | AddPropToPlayerAndAnim("prop_sign_road_01a", 57005, 0.10, -1.0, 0.0, -90.0, -250.0, 0.0)
288 | else
289 | holdingSign = false
290 | DeleteEntity(prop)
291 | ClearPedSecondaryTask(PlayerPedId())
292 | end
293 | end)
294 |
295 | RegisterNetEvent("qb-signrobbery:use:WalkingManSign", function(src)
296 | if not holdingSign then
297 | holdingSign = true
298 | AddPropToPlayerAndAnim("prop_sign_road_05a", 57005, 0.10, -1.0, 0.0, -90.0, -250.0, 0.0)
299 | else
300 | holdingSign = false
301 | DeleteEntity(prop)
302 | ClearPedSecondaryTask(PlayerPedId())
303 | end
304 | end)
305 |
306 | RegisterNetEvent("qb-signrobbery:use:DontBlockIntersectionSign", function(src)
307 | if not holdingSign then
308 | holdingSign = true
309 | AddPropToPlayerAndAnim("prop_sign_road_03e", 57005, 0.10, -1.0, 0.0, -90.0, -250.0, 0.0)
310 | else
311 | holdingSign = false
312 | DeleteEntity(prop)
313 | ClearPedSecondaryTask(PlayerPedId())
314 | end
315 | end)
316 |
317 | RegisterNetEvent("qb-signrobbery:use:UturnSign", function(src)
318 | if not holdingSign then
319 | holdingSign = true
320 | AddPropToPlayerAndAnim("prop_sign_road_03m", 57005, 0.10, -1.0, 0.0, -90.0, -250.0, 0.0)
321 | else
322 | holdingSign = false
323 | DeleteEntity(prop)
324 | ClearPedSecondaryTask(PlayerPedId())
325 | end
326 |
327 | end)
328 |
329 | RegisterNetEvent("qb-signrobbery:use:NoParkingSign", function(src)
330 | if not holdingSign then
331 | holdingSign = true
332 | AddPropToPlayerAndAnim("prop_sign_road_04a", 57005, 0.10, -1.0, 0.0, -90.0, -250.0, 0.0)
333 | else
334 | holdingSign = false
335 | DeleteEntity(prop)
336 | ClearPedSecondaryTask(PlayerPedId())
337 | end
338 |
339 | end)
340 |
341 | RegisterNetEvent("qb-signrobbery:use:LeftTurnSign", function(src)
342 | if not holdingSign then
343 | holdingSign = true
344 | AddPropToPlayerAndAnim("prop_sign_road_05e", 57005, 0.10, -1.0, 0.0, -90.0, -250.0, 0.0)
345 | else
346 | holdingSign = false
347 | DeleteEntity(prop)
348 | ClearPedSecondaryTask(PlayerPedId())
349 | end
350 |
351 | end)
352 |
353 | RegisterNetEvent("qb-signrobbery:use:RightTurnSign", function(src)
354 | if not holdingSign then
355 | holdingSign = true
356 | AddPropToPlayerAndAnim("prop_sign_road_05f", 57005, 0.10, -1.0, 0.0, -90.0, -250.0, 0.0)
357 | else
358 | holdingSign = false
359 | DeleteEntity(prop)
360 | ClearPedSecondaryTask(PlayerPedId())
361 | end
362 |
363 | end)
364 |
365 | RegisterNetEvent("qb-signrobbery:use:NoTrespassingSign", function(src)
366 | if not holdingSign then
367 | holdingSign = true
368 | AddPropToPlayerAndAnim("prop_sign_road_restriction_10", 57005, 0.10, -1.0, 0.0, -90.0, -250.0, 0.0)
369 | else
370 | holdingSign = false
371 | DeleteEntity(prop)
372 | ClearPedSecondaryTask(PlayerPedId())
373 | end
374 |
375 | end)
376 |
377 | RegisterNetEvent("qb-signrobbery:use:YieldSign", function(src)
378 | if not holdingSign then
379 | holdingSign = true
380 | AddPropToPlayerAndAnim("prop_sign_road_02a", 57005, 0.10, -1.0, 0.0, -90.0, -250.0, 0.0)
381 | else
382 | holdingSign = false
383 | DeleteEntity(prop)
384 | ClearPedSecondaryTask(PlayerPedId())
385 | end
386 |
387 | end)
388 |
389 | --Deleting The Sign Event
390 | RegisterNetEvent("signrobbery:client:delete", function(object)
391 | objects[#objects+1] = {coords = object.coords, model = object.model}
392 | local ent = GetClosestObjectOfType(object.coords.x, object.coords.y, object.coords.z, 0.1, object.model, false, false, false)
393 | if DoesEntityExist(ent) then
394 | SetEntityAsMissionEntity(ent, 1, 1)
395 | DeleteObject(ent)
396 | SetEntityAsNoLongerNeeded(ent)
397 | end
398 | end)
399 |
400 | --Target Exports
401 | CreateThread(function()
402 | exports['qb-target']:AddTargetModel('prop_sign_road_01a', {
403 | options = {
404 | {
405 | type = 'client',
406 | event = "qb-signrobbery:client:StopSign",
407 | icon = 'fas fa-user-secret',
408 | label = 'Steal Sign',
409 | }
410 | },
411 | distance = 4.0,
412 | })
413 |
414 | exports['qb-target']:AddTargetModel('prop_sign_road_05a', {
415 | options = {
416 | {
417 | type = 'client',
418 | event = "qb-signrobbery:client:WalkingManSign",
419 | icon = 'fas fa-user-secret',
420 | label = 'Steal Sign',
421 | }
422 | },
423 | distance = 4.0,
424 | })
425 |
426 | exports['qb-target']:AddTargetModel('prop_sign_road_03e', {
427 | options = {
428 | {
429 | type = 'client',
430 | event = "qb-signrobbery:client:DontBlockIntersectionSign",
431 | icon = 'fas fa-user-secret',
432 | label = 'Steal Sign',
433 | }
434 | },
435 | distance = 4.0,
436 | })
437 |
438 | exports['qb-target']:AddTargetModel('prop_sign_road_03m', {
439 | options = {
440 | {
441 | type = 'client',
442 | event = "qb-signrobbery:client:UTurnSign",
443 | icon = 'fas fa-user-secret',
444 | label = 'Steal Sign',
445 | }
446 | },
447 | distance = 4.0,
448 | })
449 |
450 | exports['qb-target']:AddTargetModel('prop_sign_road_04a', {
451 | options = {
452 | {
453 | type = 'client',
454 | event = "qb-signrobbery:client:NoParkingSign",
455 | icon = 'fas fa-user-secret',
456 | label = 'Steal Sign',
457 | }
458 | },
459 | distance = 4.0,
460 | })
461 |
462 | exports['qb-target']:AddTargetModel('prop_sign_road_05e', {
463 | options = {
464 | {
465 | type = 'client',
466 | event = "qb-signrobbery:client:LeftTurnSign",
467 | icon = 'fas fa-user-secret',
468 | label = 'Steal Sign',
469 | }
470 | },
471 | distance = 4.0,
472 | })
473 |
474 | exports['qb-target']:AddTargetModel('prop_sign_road_05f', {
475 | options = {
476 | {
477 | type = 'client',
478 | event = "qb-signrobbery:client:RightTurnSign",
479 | icon = 'fas fa-user-secret',
480 | label = 'Steal Sign',
481 | }
482 | },
483 | distance = 4.0,
484 | })
485 |
486 | exports['qb-target']:AddTargetModel('prop_sign_road_restriction_10', {
487 | options = {
488 | {
489 | type = 'client',
490 | event = "qb-signrobbery:client:NoTrespassingSign",
491 | icon = 'fas fa-user-secret',
492 | label = 'Steal Sign',
493 | }
494 | },
495 | distance = 4.0,
496 | })
497 |
498 | exports['qb-target']:AddTargetModel('prop_sign_road_02a', {
499 | options = {
500 | {
501 | type = 'client',
502 | event = "qb-signrobbery:client:YieldSign",
503 | icon = 'fas fa-user-secret',
504 | label = 'Steal Sign',
505 | }
506 | },
507 | distance = 4.0,
508 | })
509 | end)
510 |
511 | --Sell Animation
512 | RegisterNetEvent('SignRobbery:TradeAnim', function(data)
513 | local pid = PlayerPedId()
514 | loadAnimDict("mp_common")
515 | TriggerServerEvent('SignRobbery:TradeItems', data)
516 | TaskPlayAnim(pid, "mp_common", "givetake2_a", 100.0, 200.0, 0.3, 120, 0.2, 0, 0, 0)
517 | Wait(1500)
518 | holdingSign = false
519 | TriggerEvent('animations:client:EmoteCommandStart', {"c"})
520 | StopAnimTask(pid, "mp_common", "givetake2_a", 1.0)
521 | RemoveAnimDict("mp_common")
522 | end)
523 |
524 | --Sign Robbery To Scrap Material Event
525 | RegisterNetEvent('SignRobbery:Trade:Menu', function()
526 | exports['qb-menu']:openMenu({
527 | { header = "Sign Scrapping", txt = "Trade Signs for Materials", isMenuHeader = true },
528 | { header = "Stop Signs", txt = "Trade", params = { event = "SignRobbery:TradeAnim", args = 1 } },
529 | { header = "Walking Man Signs", txt = "Trade", params = { event = "SignRobbery:TradeAnim", args = 2 } },
530 | { header = "Don't Block Intersections Signs", txt = "Trade", params = { event = "SignRobbery:TradeAnim", args = 3 } },
531 | { header = "U Turn Signs", txt = "Trade", params = { event = "SignRobbery:TradeAnim", args = 4 } },
532 | { header = "No Parking Signs", txt = "Trade", params = { event = "SignRobbery:TradeAnim", args = 5 } },
533 | { header = "Turn Left Signs", txt = "Trade", params = { event = "SignRobbery:TradeAnim", args = 6 } },
534 | { header = "Turn Right Signs", txt = "Trade", params = { event = "SignRobbery:TradeAnim", args = 7 } },
535 | { header = "No Trespassing Signs", txt = "Trade", params = { event = "SignRobbery:TradeAnim", args = 8 } },
536 | { header = "Yield Signs", txt = "Trade", params = { event = "SignRobbery:TradeAnim", args = 9 } },
537 | { header = "", txt = "❌ Close", params = { event = "SignRobbery:CloseMenu" } },
538 | })
539 | end)
540 |
541 | RegisterNetEvent("SignRobbery:CloseMenu", function() exports['qb-menu']:closeMenu() end)
542 |
543 | --Export For Scrapping The Sign
544 | exports['qb-target']:AddBoxZone("SignRobberyScrap", vector3(2332.43, 3026.89, 48.15), 1.5, 1, {
545 | name = "SignRobberyScrap",
546 | heading = 270,
547 | debugPoly = false,
548 | minZ = 44.35,
549 | maxZ = 48.35,
550 | }, {
551 | options = {
552 | {
553 | type = "client",
554 | event = "SignRobbery:Trade:Menu",
555 | icon = "fas fa-recycle",
556 | label = "Scrap Sign",
557 | },
558 | },
559 | distance = 2.5
560 | })
561 |
562 | CreateThread(function()
563 | while true do
564 | for k = 1, #objects, 1 do
565 | v = objects[k]
566 | local ent = GetClosestObjectOfType(v.coords.x, v.coords.y, v.coords.z, 0.1, v.model, false, false, false)
567 | if DoesEntityExist(ent) then
568 | SetEntityAsMissionEntity(ent, 1, 1)
569 | DeleteObject(ent)
570 | SetEntityAsNoLongerNeeded(ent)
571 | end
572 | end
573 | Wait(1000)
574 | end
575 | end)
576 |
--------------------------------------------------------------------------------
/config.lua:
--------------------------------------------------------------------------------
1 | Config = {}
2 |
3 | Config.Items = {
4 | "metalscrap",
5 | "copper",
6 | "iron",
7 | "aluminum",
8 | "steel",
9 | }
10 |
11 | Config.min = "1"
12 | Config.max = "3"
13 |
--------------------------------------------------------------------------------
/fxmanifest.lua:
--------------------------------------------------------------------------------
1 | fx_version 'cerulean'
2 | game 'gta5'
3 |
4 | author 'Obtaizen & Hyper'
5 | description 'Sign Robbery Script'
6 | version '2.0'
7 |
8 | server_script 'server/*'
9 | client_script 'client/*'
10 |
11 | shared_scripts {
12 | 'config.lua',
13 | }
14 |
15 | lua54 'yes'
--------------------------------------------------------------------------------
/images/dontblockintersectionsign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Project-Sloth/ps-signrobbery/aa0d5fca49c597f7aef834bfa7921361dd2583db/images/dontblockintersectionsign.png
--------------------------------------------------------------------------------
/images/leftturnsign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Project-Sloth/ps-signrobbery/aa0d5fca49c597f7aef834bfa7921361dd2583db/images/leftturnsign.png
--------------------------------------------------------------------------------
/images/noparkingsign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Project-Sloth/ps-signrobbery/aa0d5fca49c597f7aef834bfa7921361dd2583db/images/noparkingsign.png
--------------------------------------------------------------------------------
/images/notrespassingsign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Project-Sloth/ps-signrobbery/aa0d5fca49c597f7aef834bfa7921361dd2583db/images/notrespassingsign.png
--------------------------------------------------------------------------------
/images/rightturnsign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Project-Sloth/ps-signrobbery/aa0d5fca49c597f7aef834bfa7921361dd2583db/images/rightturnsign.png
--------------------------------------------------------------------------------
/images/stopsign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Project-Sloth/ps-signrobbery/aa0d5fca49c597f7aef834bfa7921361dd2583db/images/stopsign.png
--------------------------------------------------------------------------------
/images/uturnsign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Project-Sloth/ps-signrobbery/aa0d5fca49c597f7aef834bfa7921361dd2583db/images/uturnsign.png
--------------------------------------------------------------------------------
/images/walkingmansign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Project-Sloth/ps-signrobbery/aa0d5fca49c597f7aef834bfa7921361dd2583db/images/walkingmansign.png
--------------------------------------------------------------------------------
/images/yieldsign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Project-Sloth/ps-signrobbery/aa0d5fca49c597f7aef834bfa7921361dd2583db/images/yieldsign.png
--------------------------------------------------------------------------------
/server/server.lua:
--------------------------------------------------------------------------------
1 | local QBCore = exports['qb-core']:GetCoreObject()
2 | local objects = {}
3 |
4 | QBCore.Functions.CreateCallback("qb-signrobbery:server:GetObjects", function(source, cb)
5 | cb(objects)
6 | end)
7 |
8 | RegisterNetEvent('qb-signrobbery:server:delete')
9 | AddEventHandler('qb-signrobbery:server:delete', function(object)
10 | local src = source
11 | local sourceCoords = GetEntityCoords(GetPlayerPed(src))
12 | if #(sourceCoords - object.coords) < 4 then
13 | local Player = QBCore.Functions.GetPlayer(tonumber(src))
14 | objects[#objects+1] = {coords = object.coords, model = object.model}
15 | TriggerClientEvent("signrobbery:client:delete", -1, object)
16 | if object.model == -949234773 then
17 | Player.Functions.AddItem("stopsign", 1, false)
18 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['stopsign'], "add")
19 | elseif object.model == 1502931467 then
20 | Player.Functions.AddItem("walkingmansign", 1, false)
21 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['walkingmansign'], "add")
22 | elseif object.model == 1191039009 then
23 | Player.Functions.AddItem("dontblockintersectionsign", 1, false)
24 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['dontblockintersectionsign'], "add")
25 | elseif object.model == 4138610559 then
26 | Player.Functions.AddItem("uturnsign", 1, false)
27 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['uturnsign'], "add")
28 | elseif object.model == 3830972543 then
29 | Player.Functions.AddItem("noparkingsign", 1, false)
30 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['noparkingsign'], "add")
31 | elseif object.model == 2643325436 then
32 | Player.Functions.AddItem("leftturnsign", 1, false)
33 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['leftturnsign'], "add")
34 | elseif object.model == 793482617 then
35 | Player.Functions.AddItem("rightturnsign", 1, false)
36 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['rightturnsign'], "add")
37 | elseif object.model == 1021214550 then
38 | Player.Functions.AddItem("notrespassingsign", 1, false)
39 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['notrespassingsign'], "add")
40 | elseif object.model == 3654973172 then
41 | Player.Functions.AddItem("yieldsign", 1, false)
42 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['yieldsign'], "add")
43 | end
44 | end
45 | end)
46 |
47 | ---------------------
48 | --- Usable Signs ----
49 | ---------------------
50 | QBCore.Functions.CreateUseableItem("stopsign", function(source, item)
51 | local src = source
52 | local Player = QBCore.Functions.GetPlayer(src)
53 | TriggerClientEvent('qb-signrobbery:use:StopSign', src, item)
54 | end)
55 |
56 | QBCore.Functions.CreateUseableItem("walkingmansign", function(source, item)
57 | local src = source
58 | local Player = QBCore.Functions.GetPlayer(src)
59 | TriggerClientEvent('qb-signrobbery:use:WalkingManSign', src, item)
60 | end)
61 |
62 | QBCore.Functions.CreateUseableItem("dontblockintersectionsign", function(source, item)
63 | local src = source
64 | local Player = QBCore.Functions.GetPlayer(src)
65 | TriggerClientEvent('qb-signrobbery:use:DontBlockIntersectionSign', src, item)
66 | end)
67 |
68 | QBCore.Functions.CreateUseableItem("uturnsign", function(source, item)
69 | local src = source
70 | local Player = QBCore.Functions.GetPlayer(src)
71 | TriggerClientEvent('qb-signrobbery:use:UturnSign', src, item)
72 | end)
73 |
74 | QBCore.Functions.CreateUseableItem("noparkingsign", function(source, item)
75 | local src = source
76 | local Player = QBCore.Functions.GetPlayer(src)
77 | TriggerClientEvent('qb-signrobbery:use:NoParkingSign', src, item)
78 | end)
79 |
80 | QBCore.Functions.CreateUseableItem("leftturnsign", function(source, item)
81 | local src = source
82 | local Player = QBCore.Functions.GetPlayer(src)
83 | TriggerClientEvent('qb-signrobbery:use:LeftTurnSign', src, item)
84 | end)
85 |
86 | QBCore.Functions.CreateUseableItem("rightturnsign", function(source, item)
87 | local src = source
88 | local Player = QBCore.Functions.GetPlayer(src)
89 | TriggerClientEvent('qb-signrobbery:use:RightTurnSign', src, item)
90 | end)
91 |
92 | QBCore.Functions.CreateUseableItem("notrespassingsign", function(source, item)
93 | local src = source
94 | local Player = QBCore.Functions.GetPlayer(src)
95 | TriggerClientEvent('qb-signrobbery:use:NoTrespassingSign', src, item)
96 | end)
97 |
98 | QBCore.Functions.CreateUseableItem("yieldsign", function(source, item)
99 | local src = source
100 | local Player = QBCore.Functions.GetPlayer(src)
101 | TriggerClientEvent('qb-signrobbery:use:YieldSign', src, item)
102 | end)
103 |
104 | RegisterServerEvent("SignRobbery:TradeItems", function(data)
105 | local src = source
106 | local Player = QBCore.Functions.GetPlayer(src)
107 | local randomItem = ""
108 | local amount = 0
109 | if data == 1 then
110 | if Player.Functions.GetItemByName('stopsign') ~= nil and Player.Functions.GetItemByName('stopsign').amount >= 1 then
111 | Player.Functions.RemoveItem("stopsign", 1)
112 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["stopsign"], 'remove', 1)
113 | Citizen.Wait(500)
114 | for i = 1, 5, math.random(1,2) do
115 | randomItem = Config.Items[math.random(1, #Config.Items)]
116 | amount = math.random(Config.min, Config.max)
117 | Player.Functions.AddItem(randomItem, amount, false, {["quality"] = nil})
118 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[randomItem], 'add', amount)
119 | Citizen.Wait(500)
120 | end
121 | else
122 | TriggerClientEvent('QBCore:Notify', src, "You Don't Have Enough Items")
123 | end
124 | elseif data == 2 then
125 | if Player.Functions.GetItemByName('walkingmansign') ~= nil and Player.Functions.GetItemByName('walkingmansign').amount >= 1 then
126 | Player.Functions.RemoveItem("walkingmansign", "1")
127 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["walkingmansign"], 'remove', 1)
128 | Citizen.Wait(500)
129 | for i = 1, 5, math.random(1,2) do
130 | randomItem = Config.Items[math.random(1, #Config.Items)]
131 | amount = math.random(Config.min, Config.max)
132 | Player.Functions.AddItem(randomItem, amount, false, {["quality"] = nil})
133 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[randomItem], 'add', amount)
134 | Citizen.Wait(500)
135 | end
136 | else
137 | TriggerClientEvent('QBCore:Notify', src, "You Do Not Have Enough Items")
138 | end
139 | elseif data == 3 then
140 | if Player.Functions.GetItemByName('dontblockintersectionsign') ~= nil and Player.Functions.GetItemByName('dontblockintersectionsign').amount >= 1 then
141 | Player.Functions.RemoveItem("dontblockintersectionsign", "1")
142 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["dontblockintersectionsign"], 'remove', 1)
143 | Citizen.Wait(500)
144 | for i = 1, 5, math.random(1,2) do
145 | randomItem = Config.Items[math.random(1, #Config.Items)]
146 | amount = math.random(Config.min, Config.max)
147 | Player.Functions.AddItem(randomItem, amount, false, {["quality"] = nil})
148 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[randomItem], 'add', amount)
149 | Citizen.Wait(500)
150 | end
151 | else
152 | TriggerClientEvent('QBCore:Notify', src, "You Do Not Have Enough Items")
153 | end
154 | elseif data == 4 then
155 | if Player.Functions.GetItemByName('uturnsign') ~= nil and Player.Functions.GetItemByName('uturnsign').amount >= 1 then
156 | Player.Functions.RemoveItem("uturnsign", "1")
157 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["uturnsign"], 'remove', 1)
158 | Citizen.Wait(500)
159 | for i = 1, 5, math.random(1,2) do
160 | randomItem = Config.Items[math.random(1, #Config.Items)]
161 | amount = math.random(Config.min, Config.max)
162 | Player.Functions.AddItem(randomItem, amount, false, {["quality"] = nil})
163 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[randomItem], 'add', amount)
164 | Citizen.Wait(500)
165 | end
166 | else
167 | TriggerClientEvent('QBCore:Notify', src, "You Do Not Have Enough Items")
168 | end
169 | elseif data == 5 then
170 | if Player.Functions.GetItemByName('noparkingsign') ~= nil and Player.Functions.GetItemByName('noparkingsign').amount >= 1 then
171 | Player.Functions.RemoveItem("noparkingsign", "1")
172 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["noparkingsign"], 'remove', 1)
173 | Citizen.Wait(500)
174 | for i = 1, 5, math.random(1,2) do
175 | randomItem = Config.Items[math.random(1, #Config.Items)]
176 | amount = math.random(Config.min, Config.max)
177 | Player.Functions.AddItem(randomItem, amount, false, {["quality"] = nil})
178 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[randomItem], 'add', amount)
179 | Citizen.Wait(500)
180 | end
181 | else
182 | TriggerClientEvent('QBCore:Notify', src, "You Do Not Have Enough Items")
183 | end
184 | elseif data == 6 then
185 | if Player.Functions.GetItemByName('leftturnsign') ~= nil and Player.Functions.GetItemByName('leftturnsign').amount >= 1 then
186 | Player.Functions.RemoveItem("leftturnsign", "1")
187 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["leftturnsign"], 'remove', 1)
188 | Citizen.Wait(500)
189 | for i = 1, 5, math.random(1,2) do
190 | randomItem = Config.Items[math.random(1, #Config.Items)]
191 | amount = math.random(Config.min, Config.max)
192 | Player.Functions.AddItem(randomItem, amount, false, {["quality"] = nil})
193 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[randomItem], 'add', amount)
194 | Citizen.Wait(500)
195 | end
196 | else
197 | TriggerClientEvent('QBCore:Notify', src, "You Do Not Have Enough Items")
198 | end
199 | elseif data == 7 then
200 | if Player.Functions.GetItemByName('rightturnsign') ~= nil and Player.Functions.GetItemByName('rightturnsign').amount >= 1 then
201 | Player.Functions.RemoveItem("rightturnsign", "1")
202 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["rightturnsign"], 'remove', 1)
203 | Citizen.Wait(500)
204 | for i = 1, 5, math.random(1,2) do
205 | randomItem = Config.Items[math.random(1, #Config.Items)]
206 | amount = math.random(Config.min, Config.max)
207 | Player.Functions.AddItem(randomItem, amount, false, {["quality"] = nil})
208 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[randomItem], 'add', amount)
209 | Citizen.Wait(500)
210 | end
211 | else
212 | TriggerClientEvent('QBCore:Notify', src, "You Do Not Have Enough Items")
213 | end
214 | elseif data == 8 then
215 | if Player.Functions.GetItemByName('notrespassingsign') ~= nil and Player.Functions.GetItemByName('notrespassingsign').amount >= 1 then
216 | Player.Functions.RemoveItem("notrespassingsign", "1")
217 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["notrespassingsign"], 'remove', 1)
218 | Citizen.Wait(500)
219 | for i = 1, 5, math.random(1,2) do
220 | randomItem = Config.Items[math.random(1, #Config.Items)]
221 | amount = math.random(Config.min, Config.max)
222 | Player.Functions.AddItem(randomItem, amount, false, {["quality"] = nil})
223 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[randomItem], 'add', amount)
224 | Citizen.Wait(500)
225 | end
226 | else
227 | TriggerClientEvent('QBCore:Notify', src, "You Do Not Have Enough Items")
228 | end
229 | elseif data == 9 then
230 | if Player.Functions.GetItemByName('yieldsign') ~= nil and Player.Functions.GetItemByName('yieldsign').amount >= 1 then
231 | Player.Functions.RemoveItem("yieldsign", "1")
232 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["yieldsign"], 'remove', 1)
233 | Citizen.Wait(500)
234 | for i = 1, 5, math.random(1,2) do
235 | randomItem = Config.Items[math.random(1, #Config.Items)]
236 | amount = math.random(Config.min, Config.max)
237 | Player.Functions.AddItem(randomItem, amount, false, {["quality"] = nil})
238 | TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[randomItem], 'add', amount)
239 | Citizen.Wait(500)
240 | end
241 | else
242 | TriggerClientEvent('QBCore:Notify', src, "You Do Not Have Enough Items")
243 | end
244 | end
245 | end)
246 |
--------------------------------------------------------------------------------