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