· 6 years ago · Jul 20, 2019, 07:44 AM
1-- a basic garage implementation
2
3-- vehicle db
4MySQL.createCommand("vRP/vehicles_table", [[
5CREATE TABLE IF NOT EXISTS vrp_user_vehicles(
6 user_id INTEGER,
7 vehicle VARCHAR(100),
8 CONSTRAINT pk_user_vehicles PRIMARY KEY(user_id,vehicle),
9 CONSTRAINT fk_user_vehicles_users FOREIGN KEY(user_id) REFERENCES vrp_users(id) ON DELETE CASCADE
10);
11]])
12
13MySQL.createCommand("vRP/add_vehicle","INSERT IGNORE INTO vrp_user_vehicles(user_id,vehicle) VALUES(@user_id,@vehicle)")
14MySQL.createCommand("vRP/remove_vehicle","DELETE FROM vrp_user_vehicles WHERE user_id = @user_id AND vehicle = @vehicle")
15MySQL.createCommand("vRP/get_vehicles","SELECT vehicle FROM vrp_user_vehicles WHERE user_id = @user_id")
16MySQL.createCommand("vRP/get_vehicle","SELECT vehicle FROM vrp_user_vehicles WHERE user_id = @user_id AND vehicle = @vehicle")
17MySQL.createCommand("vRP/sell_vehicle_player","UPDATE vrp_user_vehicles SET user_id = @user_id, vehicle_plate = @registration WHERE user_id = @oldUser AND vehicle = @vehicle")
18
19-- init
20MySQL.execute("vRP/vehicles_table")
21
22-- load config
23
24local cfg = module("cfg/garages")
25local cfg_inventory = module("cfg/inventory")
26local vehicle_groups = cfg.garage_types
27local lang = vRP.lang
28
29local garages = cfg.garages
30
31-- garage menus
32
33local garage_menus = {}
34
35for group,vehicles in pairs(vehicle_groups) do
36 local veh_type = vehicles._config.vtype or "default"
37
38 local menu = {
39 name=lang.garage.title({group}),
40 css={top = "75px", header_color="rgba(255,125,0,0.75)"}
41 }
42 garage_menus[group] = menu
43
44 menu[lang.garage.owned.title()] = {function(player,choice)
45 local user_id = vRP.getUserId(player)
46 if user_id ~= nil then
47 -- init tmpdata for rents
48 local tmpdata = vRP.getUserTmpTable(user_id)
49 if tmpdata.rent_vehicles == nil then
50 tmpdata.rent_vehicles = {}
51 end
52
53
54 -- build nested menu
55 local kitems = {}
56 local submenu = {name=lang.garage.title({lang.garage.owned.title()}), css={top="75px",header_color="rgba(255,125,0,0.75)"}}
57 submenu.onclose = function()
58 vRP.openMenu(player,menu)
59 end
60
61 local choose = function(player, choice)
62 local vname = kitems[choice]
63 if vname then
64 -- spawn vehicle
65 local vehicle = vehicles[vname]
66 if vehicle then
67 vRP.closeMenu(player)
68 TriggerEvent('ply_garages:CheckForSpawnBasicVeh', user_id, vname)
69 end
70 end
71 end
72
73 -- get player owned vehicles
74 MySQL.query("vRP/get_vehicles", {user_id = user_id}, function(pvehicles, affected)
75 -- add rents to whitelist
76 for k,v in pairs(tmpdata.rent_vehicles) do
77 if v then -- check true, prevent future neolua issues
78 table.insert(pvehicles,{vehicle = k})
79 end
80 end
81
82 for k,v in pairs(pvehicles) do
83 local vehicle = vehicles[v.vehicle]
84 if vehicle then
85 submenu[vehicle[1]] = {choose,vehicle[3]}
86 kitems[vehicle[1]] = v.vehicle
87 end
88 end
89
90 vRP.openMenu(player,submenu)
91 end)
92 end
93 end,lang.garage.owned.description()}
94
95 menu[lang.garage.buy.title()] = {function(player,choice)
96 local user_id = vRP.getUserId(player)
97 if user_id ~= nil then
98
99 -- build nested menu
100 local kitems = {}
101 local submenu = {name=lang.garage.title({lang.garage.buy.title()}), css={top="75px",header_color="rgba(255,125,0,0.75)"}}
102 submenu.onclose = function()
103 vRP.openMenu(player,menu)
104 end
105
106 local choose = function(player, choice)
107 local vname = kitems[choice]
108 if vname then
109 -- buy vehicle
110 local vehicle = vehicles[vname]
111 if vehicle and vRP.tryPayment(user_id,vehicle[2]) then
112 TriggerEvent('veh_SR:CheckMoneyForBasicVeh', user_id, vname, vehicle[2] ,veh_type)
113 vRP.closeMenu(player)
114 else
115 vRPclient.notify(player,{lang.money.not_enough()})
116 end
117 end
118 end
119
120 -- get player owned vehicles (indexed by vehicle type name in lower case)
121 MySQL.query("vRP/get_vehicles", {user_id = user_id}, function(_pvehicles, affected)
122 local pvehicles = {}
123 for k,v in pairs(_pvehicles) do
124 pvehicles[string.lower(v.vehicle)] = true
125 end
126
127 -- for each existing vehicle in the garage group
128 for k,v in pairs(vehicles) do
129 if k ~= "_config" and pvehicles[string.lower(k)] == nil then -- not already owned
130 submenu[v[1]] = {choose,lang.garage.buy.info({v[2],v[3]})}
131 kitems[v[1]] = k
132 end
133 end
134
135 vRP.openMenu(player,submenu)
136 end)
137 end
138 end,lang.garage.buy.description()}
139
140 menu[lang.garage.sell.title()] = {function(player,choice)
141 local user_id = vRP.getUserId(player)
142 if user_id ~= nil then
143
144 -- build nested menu
145 local kitems = {}
146 local submenu = {name=lang.garage.title({lang.garage.sell.title()}), css={top="75px",header_color="rgba(255,125,0,0.75)"}}
147 submenu.onclose = function()
148 vRP.openMenu(player,menu)
149 end
150
151 local choose = function(player, choice)
152 local vname = kitems[choice]
153 if vname then
154 -- sell vehicle
155 local vehicle = vehicles[vname]
156 if vehicle then
157 local price = math.ceil(vehicle[2]*cfg.sell_factor)
158
159 MySQL.query("vRP/get_vehicle", {user_id = user_id, vehicle = vname}, function(rows, affected)
160 if #rows > 0 then -- has vehicle
161 vRP.giveMoney(user_id,price)
162 MySQL.execute("vRP/remove_vehicle", {user_id = user_id, vehicle = vname})
163
164 vRPclient.notify(player,{lang.money.received({price})})
165 vRP.closeMenu(player)
166 else
167 vRPclient.notify(player,{lang.common.not_found()})
168 end
169 end)
170 end
171 end
172 end
173
174 -- get player owned vehicles (indexed by vehicle type name in lower case)
175 MySQL.query("vRP/get_vehicles", {user_id = user_id}, function(_pvehicles, affected)
176 local pvehicles = {}
177 for k,v in pairs(_pvehicles) do
178 pvehicles[string.lower(v.vehicle)] = true
179 end
180
181 -- for each existing vehicle in the garage group
182 for k,v in pairs(pvehicles) do
183 local vehicle = vehicles[k]
184 if vehicle then -- not already owned
185 local price = math.ceil(vehicle[2]*cfg.sell_factor)
186 submenu[vehicle[1]] = {choose,lang.garage.buy.info({price,vehicle[3]})}
187 kitems[vehicle[1]] = k
188 end
189 end
190
191 vRP.openMenu(player,submenu)
192 end)
193 end
194 end,lang.garage.sell.description()}
195
196 menu[lang.garage.rent.title()] = {function(player,choice)
197 local user_id = vRP.getUserId(player)
198 if user_id ~= nil then
199 -- init tmpdata for rents
200 local tmpdata = vRP.getUserTmpTable(user_id)
201 if tmpdata.rent_vehicles == nil then
202 tmpdata.rent_vehicles = {}
203 end
204
205 -- build nested menu
206 local kitems = {}
207 local submenu = {name=lang.garage.title({lang.garage.rent.title()}), css={top="75px",header_color="rgba(255,125,0,0.75)"}}
208 submenu.onclose = function()
209 vRP.openMenu(player,menu)
210 end
211
212 local choose = function(player, choice)
213 local vname = kitems[choice]
214 if vname then
215 -- rent vehicle
216 local vehicle = vehicles[vname]
217 if vehicle then
218 local price = math.ceil(vehicle[2]*cfg.rent_factor)
219 if vRP.tryPayment(user_id,price) then
220 -- add vehicle to rent tmp data
221 tmpdata.rent_vehicles[vname] = true
222
223 vRPclient.notify(player,{lang.money.paid({price})})
224 vRP.closeMenu(player)
225 else
226 vRPclient.notify(player,{lang.money.not_enough()})
227 end
228 end
229 end
230 end
231
232 -- get player owned vehicles (indexed by vehicle type name in lower case)
233 MySQL.query("vRP/get_vehicles", {user_id = user_id}, function(_pvehicles, affected)
234 local pvehicles = {}
235 for k,v in pairs(_pvehicles) do
236 pvehicles[string.lower(v.vehicle)] = true
237 end
238
239 -- add rents to blacklist
240 for k,v in pairs(tmpdata.rent_vehicles) do
241 pvehicles[string.lower(k)] = true
242 end
243
244 -- for each existing vehicle in the garage group
245 for k,v in pairs(vehicles) do
246 if k ~= "_config" and pvehicles[string.lower(k)] == nil then -- not already owned
247 local price = math.ceil(v[2]*cfg.rent_factor)
248 submenu[v[1]] = {choose,lang.garage.buy.info({price,v[3]})}
249 kitems[v[1]] = k
250 end
251 end
252
253 vRP.openMenu(player,submenu)
254 end)
255 end
256 end,lang.garage.rent.description()}
257
258 menu[lang.garage.store.title()] = {function(player,choice)
259 vRPclient.despawnGarageVehicle(player,{veh_type,15})
260 end, lang.garage.store.description()}
261end
262
263local function build_client_garages(source)
264 local user_id = vRP.getUserId(source)
265 if user_id ~= nil then
266 for k,v in pairs(garages) do
267 local gtype,x,y,z = table.unpack(v)
268
269 local group = vehicle_groups[gtype]
270 if group then
271 local gcfg = group._config
272
273 -- enter
274 local garage_enter = function(player,area)
275 local user_id = vRP.getUserId(source)
276 if user_id ~= nil and vRP.hasPermissions(user_id,gcfg.permissions or {}) then
277 local menu = garage_menus[gtype]
278 if menu then
279 vRP.openMenu(player,menu)
280 end
281 end
282 end
283
284 -- leave
285 local garage_leave = function(player,area)
286 vRP.closeMenu(player)
287 end
288
289 vRPclient.addBlip(source,{x,y,z,gcfg.blipid,gcfg.blipcolor,lang.garage.title({gtype})})
290 vRPclient.addMarker(source,{x,y,z-1,0.7,0.7,0.5,0,255,125,125,150})
291
292 vRP.setArea(source,"vRP:garage"..k,x,y,z,1,1.5,garage_enter,garage_leave)
293 end
294 end
295 end
296end
297
298AddEventHandler("vRP:playerSpawn",function(user_id,source,first_spawn)
299 if first_spawn then
300 build_client_garages(source)
301 end
302end)
303
304-- VEHICLE MENU
305
306-- define vehicle actions
307-- action => {cb(user_id,player,veh_group,veh_name),desc}
308local veh_actions = {}
309
310-- open trunk
311veh_actions[lang.vehicle.trunk.title()] = {function(user_id,player,vtype,name)
312 local chestname = "u"..user_id.."veh_"..string.lower(name)
313 local max_weight = cfg_inventory.vehicle_chest_weights[string.lower(name)] or cfg_inventory.default_vehicle_chest_weight
314
315 -- open chest
316 vRPclient.vc_openDoor(player, {vtype,5})
317 vRP.openChest(player, chestname, max_weight, function()
318 vRPclient.vc_closeDoor(player, {vtype,5})
319 end)
320end, lang.vehicle.trunk.description()}
321
322-- detach trailer
323veh_actions[lang.vehicle.detach_trailer.title()] = {function(user_id,player,vtype,name)
324 vRPclient.vc_detachTrailer(player, {vtype})
325end, lang.vehicle.detach_trailer.description()}
326
327-- detach towtruck
328veh_actions[lang.vehicle.detach_towtruck.title()] = {function(user_id,player,vtype,name)
329 vRPclient.vc_detachTowTruck(player, {vtype})
330end, lang.vehicle.detach_towtruck.description()}
331
332-- detach cargobob
333veh_actions[lang.vehicle.detach_cargobob.title()] = {function(user_id,player,vtype,name)
334 vRPclient.vc_detachCargobob(player, {vtype})
335end, lang.vehicle.detach_cargobob.description()}
336
337-- lock/unlock
338veh_actions[lang.vehicle.lock.title()] = {function(user_id,player,vtype,name)
339 vRPclient.vc_toggleLock(player, {vtype})
340end, lang.vehicle.lock.description()}
341
342-- engine on/off
343veh_actions[lang.vehicle.engine.title()] = {function(user_id,player,vtype,name)
344 vRPclient.vc_toggleEngine(player, {vtype})
345end, lang.vehicle.engine.description()}
346
347local function ch_vehicle(player,choice)
348 local user_id = vRP.getUserId(player)
349 if user_id ~= nil then
350 -- check vehicle
351 vRPclient.getNearestOwnedVehicle(player,{7},function(ok,vtype,name)
352 if ok then
353 -- build vehicle menu
354 vRP.buildMenu("vehicle", {user_id = user_id, player = player, vtype = vtype, vname = name}, function(menu)
355 menu.name=lang.vehicle.title()
356 menu.css={top="75px",header_color="rgba(255,125,0,0.75)"}
357
358 for k,v in pairs(veh_actions) do
359 menu[k] = {function(player,choice) v[1](user_id,player,vtype,name) end, v[2]}
360 end
361
362 vRP.openMenu(player,menu)
363 end)
364 else
365 vRPclient.notify(player,{lang.vehicle.no_owned_near()})
366 end
367 end)
368 end
369end
370
371-- ask trunk (open other user car chest)
372local function ch_asktrunk(player,choice)
373 vRPclient.getNearestPlayer(player,{10},function(nplayer)
374 local nuser_id = vRP.getUserId(nplayer)
375 if nuser_id ~= nil then
376 vRPclient.notify(player,{lang.vehicle.asktrunk.asked()})
377 vRP.request(nplayer,lang.vehicle.asktrunk.request(),15,function(nplayer,ok)
378 if ok then -- request accepted, open trunk
379 vRPclient.getNearestOwnedVehicle(nplayer,{7},function(ok,vtype,name)
380 if ok then
381 local chestname = "u"..nuser_id.."veh_"..string.lower(name)
382 local max_weight = cfg_inventory.vehicle_chest_weights[string.lower(name)] or cfg_inventory.default_vehicle_chest_weight
383
384 -- open chest
385 local cb_out = function(idname,amount)
386 vRPclient.notify(nplayer,{lang.inventory.give.given({vRP.getItemName(idname),amount})})
387 end
388
389 local cb_in = function(idname,amount)
390 vRPclient.notify(nplayer,{lang.inventory.give.received({vRP.getItemName(idname),amount})})
391 end
392
393 vRPclient.vc_openDoor(nplayer, {vtype,5})
394 vRP.openChest(player, chestname, max_weight, function()
395 vRPclient.vc_closeDoor(nplayer, {vtype,5})
396 end,cb_in,cb_out)
397 else
398 vRPclient.notify(player,{lang.vehicle.no_owned_near()})
399 vRPclient.notify(nplayer,{lang.vehicle.no_owned_near()})
400 end
401 end)
402 else
403 vRPclient.notify(player,{lang.common.request_refused()})
404 end
405 end)
406 else
407 vRPclient.notify(player,{lang.common.no_player_near()})
408 end
409 end)
410end
411
412-- repair nearest vehicle
413local function ch_repair(player,choice)
414 local user_id = vRP.getUserId(player)
415 if user_id ~= nil then
416 -- anim and repair
417 if vRP.tryGetInventoryItem(user_id,"repairkit",1,true) then
418 vRPclient.playAnim(player,{false,{task="WORLD_HUMAN_WELDING"},false})
419 SetTimeout(15000, function()
420 vRPclient.fixeNearestVehicle(player,{7})
421 vRPclient.stopAnim(player,{false})
422 end)
423 end
424 end
425end
426
427-- replace nearest vehicle
428local function ch_replace(player,choice)
429 vRPclient.replaceNearestVehicle(player,{7})
430end
431
432vRP.registerMenuBuilder("main", function(add, data)
433 local user_id = vRP.getUserId(data.player)
434 if user_id ~= nil then
435 -- add vehicle entry
436 local choices = {}
437 choices[lang.vehicle.title()] = {ch_vehicle}
438
439 -- add ask trunk
440 choices[lang.vehicle.asktrunk.title()] = {ch_asktrunk}
441
442 -- add repair functions
443 if vRP.hasPermission(user_id, "vehicle.repair") then
444 choices[lang.vehicle.repair.title()] = {ch_repair, lang.vehicle.repair.description()}
445 end
446
447 if vRP.hasPermission(user_id, "vehicle.replace") then
448 choices[lang.vehicle.replace.title()] = {ch_replace, lang.vehicle.replace.description()}
449 end
450
451 add(choices)
452 end
453end)
454
455-- sell vehicle
456veh_actions[lang.vehicle.sellTP.title()] = {function(playerID,player,vtype,name)
457 if playerID ~= nil then
458 vRPclient.getNearestPlayers(player,{15},function(nplayers)
459 --vRPclient.getNearestOwnedVehicle(nplayer,{7},function(ok,vtype,name)
460 usrList = ""
461 for k,v in pairs(nplayers) do
462 usrList = usrList .. "[" .. vRP.getUserId(k) .. "]" .. GetPlayerName(k) .. " | "
463 end
464 if usrList ~= "" then
465 vRP.prompt(player,"Players Nearby: " .. usrList .. "","",function(player,user_id)
466 user_id = user_id
467 if user_id ~= nil and user_id ~= "" then
468 local target = vRP.getUserSource(tonumber(user_id))
469 if target ~= nil then
470 vRP.prompt(player,"Price $: ","",function(player,amount)
471 if (tonumber(amount)) then
472 MySQL.query("vRP/get_vehicle", {user_id = user_id, vehicle = name}, function(pvehicle, affected)
473 if #pvehicle > 0 then
474 vRPclient.notify(player,{"~r~The player already has this vehicle type."})
475 else
476 vRP.request(target,GetPlayerName(player).." wants to sell: " ..name.. " Price: $"..amount, 10, function(target,ok)
477 if ok then
478 local pID = vRP.getUserId(target)
479 local money = vRP.getMoney(pID)
480 if (tonumber(money) >= tonumber(amount)) then
481 vRPclient.despawnGarageVehicle(player,{vtype,15})
482 vRP.getUserIdentity(pID, function(identity)
483 MySQL.execute("vRP/sell_vehicle_player", {user_id = user_id, registration = "P "..identity.registration, oldUser = playerID, vehicle = name})
484 end)
485 vRP.giveMoney(playerID, amount)
486 vRP.setMoney(pID,money-amount)
487 vRPclient.notify(player,{"~g~You have successfully sold the vehicle to ".. GetPlayerName(target).." for $"..amount.."!"})
488 vRPclient.notify(target,{"~g~"..GetPlayerName(player).." has successfully sold you the car for $"..amount.."!"})
489 else
490 vRPclient.notify(player,{"~r~".. GetPlayerName(target).." doesn't have enough money!"})
491 vRPclient.notify(target,{"~r~You don't have enough money!"})
492 end
493 else
494 vRPclient.notify(player,{"~r~"..GetPlayerName(target).." has refused to buy the car."})
495 vRPclient.notify(target,{"~r~You have refused to buy "..GetPlayerName(player).."'s car."})
496 end
497 end)
498 vRP.closeMenu(player)
499 end
500 end)
501 else
502 vRPclient.notify(player,{"~r~The price of the car has to be a number."})
503 end
504 end)
505 else
506 vRPclient.notify(player,{"~r~That ID seems invalid."})
507 end
508 else
509 vRPclient.notify(player,{"~r~No player ID selected."})
510 end
511 end)
512 else
513 vRPclient.notify(player,{"~r~No player nearby."})
514 end
515 --end)
516 end)
517 end
518end, lang.vehicle.sellTP.description()}
519
520local function ch_vehicle(player,choice)
521 local user_id = vRP.getUserId(player)
522 if user_id ~= nil then
523 -- check vehicle
524 vRPclient.getNearestOwnedVehicle(player,{7},function(ok,vtype,name)
525 if ok then
526 -- build vehicle menu
527 vRP.buildMenu("vehicle", {user_id = user_id, player = player, vtype = vtype, vname = name}, function(menu)
528 menu.name=lang.vehicle.title()
529 menu.css={top="75px",header_color="rgba(255,125,0,0.75)"}
530
531 for k,v in pairs(veh_actions) do
532 menu[k] = {function(player,choice) v[1](user_id,player,vtype,name) end, v[2]}
533 end
534
535 vRP.openMenu(player,menu)
536 end)
537 else
538 vRPclient.notify(player,{lang.vehicle.no_owned_near()})
539 end
540 end)
541 end
542end