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