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