· 6 years ago · Jun 17, 2019, 12:24 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(255),
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 -- sell vehicle
156 local vehicle = vehicles[vname]
157 if vehicle then
158 local price = math.ceil(vehicle[2]*cfg.sell_factor)
159
160 MySQL.query("vRP/get_vehicle", {user_id = user_id, vehicle = vname}, function(rows, affected)
161 if #rows > 0 then -- has vehicle
162 vRP.giveMoney(user_id,price)
163 MySQL.execute("vRP/remove_vehicle", {user_id = user_id, vehicle = vname})
164
165 vRPclient.notify(player,{lang.money.received({price})})
166 vRP.closeMenu(player)
167 else
168 vRPclient.notify(player,{lang.common.not_found()})
169 end
170 end)
171 end
172 end
173 end
174
175 -- get player owned vehicles (indexed by vehicle type name in lower case)
176 MySQL.query("vRP/get_vehicles", {user_id = user_id}, function(_pvehicles, affected)
177 local pvehicles = {}
178 for k,v in pairs(_pvehicles) do
179 pvehicles[string.lower(v.vehicle)] = true
180 end
181
182 -- for each existing vehicle in the garage group
183 for k,v in pairs(pvehicles) do
184 local vehicle = vehicles[k]
185 if vehicle then -- not already owned
186 local price = math.ceil(vehicle[2]*cfg.sell_factor)
187 submenu[vehicle[1]] = {choose,lang.garage.buy.info({price,vehicle[3]})}
188 kitems[vehicle[1]] = k
189 end
190 end
191
192 vRP.openMenu(player,submenu)
193 end)
194 end
195 end,lang.garage.sell.description()}
196
197 menu[lang.garage.rent.title()] = {function(player,choice)
198 local user_id = vRP.getUserId(player)
199 if user_id ~= nil then
200 -- init tmpdata for rents
201 local tmpdata = vRP.getUserTmpTable(user_id)
202 if tmpdata.rent_vehicles == nil then
203 tmpdata.rent_vehicles = {}
204 end
205
206 -- build nested menu
207 local kitems = {}
208 local submenu = {name=lang.garage.title({lang.garage.rent.title()}), css={top="75px",header_color="rgba(255,125,0,0.75)"}}
209 submenu.onclose = function()
210 vRP.openMenu(player,menu)
211 end
212
213 local choose = function(player, choice)
214 local vname = kitems[choice]
215 if vname then
216 -- rent vehicle
217 local vehicle = vehicles[vname]
218 if vehicle then
219 local price = math.ceil(vehicle[2]*cfg.rent_factor)
220 if vRP.tryPayment(user_id,price) then
221 -- add vehicle to rent tmp data
222 tmpdata.rent_vehicles[vname] = true
223
224 vRPclient.notify(player,{lang.money.paid({price})})
225 vRP.closeMenu(player)
226 else
227 vRPclient.notify(player,{lang.money.not_enough()})
228 end
229 end
230 end
231 end
232
233 -- get player owned vehicles (indexed by vehicle type name in lower case)
234 MySQL.query("vRP/get_vehicles", {user_id = user_id}, function(_pvehicles, affected)
235 local pvehicles = {}
236 for k,v in pairs(_pvehicles) do
237 pvehicles[string.lower(v.vehicle)] = true
238 end
239
240 -- add rents to blacklist
241 for k,v in pairs(tmpdata.rent_vehicles) do
242 pvehicles[string.lower(k)] = true
243 end
244
245 -- for each existing vehicle in the garage group
246 for k,v in pairs(vehicles) do
247 if k ~= "_config" and pvehicles[string.lower(k)] == nil then -- not already owned
248 local price = math.ceil(v[2]*cfg.rent_factor)
249 submenu[v[1]] = {choose,lang.garage.buy.info({price,v[3]})}
250 kitems[v[1]] = k
251 end
252 end
253
254 vRP.openMenu(player,submenu)
255 end)
256 end
257 end,lang.garage.rent.description()}
258
259 menu[lang.garage.store.title()] = {function(player,choice)
260 vRPclient.despawnGarageVehicle(player,{veh_type,15})
261 end, lang.garage.store.description()}
262end
263
264local function build_client_garages(source)
265 local user_id = vRP.getUserId(source)
266 if user_id ~= nil then
267 for k,v in pairs(garages) do
268 local gtype,x,y,z = table.unpack(v)
269
270 local group = vehicle_groups[gtype]
271 if group then
272 local gcfg = group._config
273
274 -- enter
275 local garage_enter = function(player,area)
276 local user_id = vRP.getUserId(source)
277 if user_id ~= nil and vRP.hasPermissions(user_id,gcfg.permissions or {}) then
278 local menu = garage_menus[gtype]
279 if menu then
280 vRP.openMenu(player,menu)
281 end
282 end
283 end
284
285 -- leave
286 local garage_leave = function(player,area)
287 vRP.closeMenu(player)
288 end
289
290 vRPclient.addBlip(source,{x,y,z,gcfg.blipid,gcfg.blipcolor,lang.garage.title({gtype})})
291 vRPclient.addMarker(source,{x,y,z-1,0.7,0.7,0.5,0,255,125,125,150})
292
293 vRP.setArea(source,"vRP:garage"..k,x,y,z,1,1.5,garage_enter,garage_leave)
294 end
295 end
296 end
297end
298
299AddEventHandler("vRP:playerSpawn",function(user_id,source,first_spawn)
300 if first_spawn then
301 build_client_garages(source)
302 end
303end)
304
305-- VEHICLE MENU
306
307-- define vehicle actions
308-- action => {cb(user_id,player,veh_group,veh_name),desc}
309local veh_actions = {}
310
311-- open trunk
312veh_actions[lang.vehicle.trunk.title()] = {function(user_id,player,vtype,name)
313 local chestname = "u"..user_id.."veh_"..string.lower(name)
314 local max_weight = cfg_inventory.vehicle_chest_weights[string.lower(name)] or cfg_inventory.default_vehicle_chest_weight
315
316 -- open chest
317 vRPclient.vc_openDoor(player, {vtype,5})
318 vRP.openChest(player, chestname, max_weight, function()
319 vRPclient.vc_closeDoor(player, {vtype,5})
320 end)
321end, lang.vehicle.trunk.description()}
322
323-- detach trailer
324veh_actions[lang.vehicle.detach_trailer.title()] = {function(user_id,player,vtype,name)
325 vRPclient.vc_detachTrailer(player, {vtype})
326end, lang.vehicle.detach_trailer.description()}
327
328-- detach towtruck
329veh_actions[lang.vehicle.detach_towtruck.title()] = {function(user_id,player,vtype,name)
330 vRPclient.vc_detachTowTruck(player, {vtype})
331end, lang.vehicle.detach_towtruck.description()}
332
333-- detach cargobob
334veh_actions[lang.vehicle.detach_cargobob.title()] = {function(user_id,player,vtype,name)
335 vRPclient.vc_detachCargobob(player, {vtype})
336end, lang.vehicle.detach_cargobob.description()}
337
338-- lock/unlock
339veh_actions[lang.vehicle.lock.title()] = {function(user_id,player,vtype,name)
340 vRPclient.vc_toggleLock(player, {vtype})
341end, lang.vehicle.lock.description()}
342
343-- engine on/off
344veh_actions[lang.vehicle.engine.title()] = {function(user_id,player,vtype,name)
345 vRPclient.vc_toggleEngine(player, {vtype})
346end, lang.vehicle.engine.description()}
347
348local function ch_vehicle(player,choice)
349 local user_id = vRP.getUserId(player)
350 if user_id ~= nil then
351 -- check vehicle
352 vRPclient.getNearestOwnedVehicle(player,{2},function(ok,vtype,name)
353 if ok then
354 -- build vehicle menu
355 vRP.buildMenu("vehicle", {user_id = user_id, player = player, vtype = vtype, vname = name}, function(menu)
356 menu.name=lang.vehicle.title()
357 menu.css={top="75px",header_color="rgba(255,125,0,0.75)"}
358
359 for k,v in pairs(veh_actions) do
360 menu[k] = {function(player,choice) v[1](user_id,player,vtype,name) end, v[2]}
361 end
362
363 vRP.openMenu(player,menu)
364 end)
365 else
366 vRPclient.notify(player,{lang.vehicle.no_owned_near()})
367 end
368 end)
369 end
370end
371
372-- ask trunk (open other user car chest)
373local function ch_asktrunk(player,choice)
374 vRPclient.getNearestPlayer(player,{10},function(nplayer)
375 local nuser_id = vRP.getUserId(nplayer)
376 if nuser_id ~= nil then
377 vRPclient.notify(player,{lang.vehicle.asktrunk.asked()})
378 vRP.request(nplayer,lang.vehicle.asktrunk.request(),15,function(nplayer,ok)
379 if ok then -- request accepted, open trunk
380 vRPclient.getNearestOwnedVehicle(nplayer,{7},function(ok,vtype,name)
381 if ok then
382 local chestname = "u"..nuser_id.."veh_"..string.lower(name)
383 local max_weight = cfg_inventory.vehicle_chest_weights[string.lower(name)] or cfg_inventory.default_vehicle_chest_weight
384
385 -- open chest
386 local cb_out = function(idname,amount)
387 vRPclient.notify(nplayer,{lang.inventory.give.given({vRP.getItemName(idname),amount})})
388 end
389
390 local cb_in = function(idname,amount)
391 vRPclient.notify(nplayer,{lang.inventory.give.received({vRP.getItemName(idname),amount})})
392 end
393
394 vRPclient.vc_openDoor(nplayer, {vtype,5})
395 vRP.openChest(player, chestname, max_weight, function()
396 vRPclient.vc_closeDoor(nplayer, {vtype,5})
397 end,cb_in,cb_out)
398 else
399 vRPclient.notify(player,{lang.vehicle.no_owned_near()})
400 vRPclient.notify(nplayer,{lang.vehicle.no_owned_near()})
401 end
402 end)
403 else
404 vRPclient.notify(player,{lang.common.request_refused()})
405 end
406 end)
407 else
408 vRPclient.notify(player,{lang.common.no_player_near()})
409 end
410 end)
411end
412
413-- repair nearest vehicle
414local function ch_repair(player,choice)
415 local user_id = vRP.getUserId(player)
416 if user_id ~= nil then
417 -- anim and repair
418 if vRP.tryGetInventoryItem(user_id,"repairkit",1,true) then
419 vRPclient.playAnim(player,{false,{task="WORLD_HUMAN_WELDING"},false})
420 SetTimeout(15000, function()
421 vRPclient.fixeNearestVehicle(player,{7})
422 vRPclient.stopAnim(player,{false})
423 end)
424 end
425 end
426end
427
428-- replace nearest vehicle
429local function ch_replace(player,choice)
430 vRPclient.replaceNearestVehicle(player,{7})
431end
432
433vRP.registerMenuBuilder("main", function(add, data)
434 local user_id = vRP.getUserId(data.player)
435 if user_id ~= nil then
436 -- add vehicle entry
437 local choices = {}
438 choices[lang.vehicle.title()] = {ch_vehicle}
439
440 -- add ask trunk
441 choices[lang.vehicle.asktrunk.title()] = {ch_asktrunk}
442
443 -- add repair functions
444 if vRP.hasPermission(user_id, "vehicle.repair") then
445 choices[lang.vehicle.repair.title()] = {ch_repair, lang.vehicle.repair.description()}
446 end
447
448 if vRP.hasPermission(user_id, "vehicle.replace") then
449 choices[lang.vehicle.replace.title()] = {ch_replace, lang.vehicle.replace.description()}
450 end
451
452 add(choices)
453 end
454end)