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