dobrograd-13-06-2022/garrysmod/addons/feature-cars/lua/car-dealer/sv_menu.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

428 lines
14 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

netstream.Hook('car-dealer.sync', function(ply)
carDealer.sync(ply)
end)
local busyFor = {}
hook.Add('PlayerDisconnected', 'car-dealer.busy', function(ply)
busyFor[ply] = nil
end)
function carDealer.Listen(channel, handler)
netstream.Listen(channel, function(reply, ply, ...)
if busyFor[ply] then
carDealer.notify(ply, 'warning', 'Продавец машин сейчас занят, попробуй повторить попытку позже')
return reply()
end
busyFor[ply] = true
handler(function(...)
if IsValid(ply) then busyFor[ply] = nil end
reply(unpack({...}))
end, ply, unpack({...}))
end)
end
local function tryQueuedSpawn(ply, idOrClass, callback)
local queued = ply:GetLocalVar('car-dealer.queued')
queued = queued and queued[1]
if queued then
if queued ~= idOrClass then
carDealer.notify(ply, 'warning', 'Ты уже ожидаешь автомобиль. Дождись своей очереди или покинь ее')
callback()
end
if ply:GetLocalVar('car-dealer.queuedReady') then
carDealer.spawningQueuedAuto = true
ply:Notify('admin', 0)
if isnumber(queued) then
carDealer.spawnOwnedVeh(ply, queued, function(ok, veh)
carDealer.removeFromQueue(ply)
carDealer.spawningQueuedAuto = false
if not ok then
carDealer.notify(ply, 'warning', veh or 'Не получилось создать автомобиль')
return callback()
end
callback(veh)
end)
else
carDealer.spawnDepositVeh(ply, queued, function(ok, veh)
carDealer.removeFromQueue(ply)
carDealer.spawningQueuedAuto = false
if not ok then
carDealer.notify(ply, 'warning', veh or 'Не получилось создать автомобиль')
return callback()
end
callback(veh)
end)
end
else
carDealer.notify(ply, 'warning', 'Ты уже ожидаешь автомобиль. Дождись своей очереди или покинь ее')
callback()
end
end
carDealer.notify(ply, 'Твой запрос поставлен в очередь. Ожидай уведомления о готовности автомобиля')
carDealer.addToQueue(ply, idOrClass)
callback()
end
carDealer.Listen('car-dealer.spawn', function(reply, ply, id)
if ply:IsGhost() or ply:GetLocalVar('cd.cantHaveOwned') then
carDealer.notify(ply, 'warning', 'Ты не можешь пригонять автомобили сейчас')
return reply()
end
local veh = carDealer.getCurVeh(ply)
if IsValid(veh) then
carDealer.notify(ply, 'warning', 'Сначала надо загнать свой автомобиль')
carDealer.setCurVeh(ply, veh)
return reply()
end
local nextCar = ply:GetDBVar('nextCar')
if nextCar and os.time() < nextCar then
carDealer.notify(ply, 'warning', 'Твой автомобиль находится в другой части города')
return reply()
end
carDealer.getVehById(id, function(veh)
if not veh or veh.garage ~= ply:SteamID() then
carDealer.notify(ply, 'warning', 'Ты не владеешь этим автомобилем')
return reply()
end
local class = veh and veh.class
local cdData = carDealer.vehicles[class]
if not cdData then
carDealer.notify(ply, 'warning', 'Не получилось найти данные об автомобиле')
return reply()
end
local category = carDealer.categories[cdData.category]
local ok, why = carDealer.canUse(ply, class)
if not ok or not category then
carDealer.notify(ply, 'warning', why or 'Ты не можешь использовать этот автомобиль')
return reply()
end
if isfunction(category.spawnCheck) then
local can, why = category.spawnCheck(ply, class)
if can == false then
carDealer.notify(ply, why or 'Ты не можешь пригнать этот автомобиль сейчас')
return reply()
end
end
if category.queue then
tryQueuedSpawn(ply, id, function(veh)
if not veh then return reply() end
carDealer.notify(ply, (veh.cdData.name or 'Автомобиль') .. ' ждет тебя неподалеку. Забери его в течение 10 минут, или автомобиль эвакуируют')
veh.despawnAfter = CurTime() + 15 * 60
end)
else
carDealer.spawnOwnedVeh(ply, id, function(ok, veh)
if ok then
carDealer.notify(ply, (veh.cdData.name or 'Автомобиль') .. ' ждет тебя неподалеку. Забери его в течение 10 минут, или автомобиль эвакуируют')
else
carDealer.notify(ply, 'warning', veh or 'Не получилось создать автомобиль')
end
carDealer.sync(ply)
reply()
end)
end
end)
end)
carDealer.Listen('car-dealer.despawn', function(reply, ply)
local queued = ply:GetLocalVar('car-dealer.queued')
if queued then
carDealer.spawningQueuedAuto = false
carDealer.removeFromQueue(ply)
ply:Notify('admin', 0)
carDealer.notify(ply, 'Ты покинул очередь')
return reply(true)
end
local veh = carDealer.getCurVeh(ply)
if not IsValid(veh) or not veh.cdData then
carDealer.notify(ply, 'warning', 'У тебя нет автомобилей в городе')
return reply()
end
if CurTime() < (veh.despawnAfter or 0) then
carDealer.notify(ply, 'warning', 'Автомобиль можно загнать не ранее 15 минут после получения')
return reply()
end
if ply:IsGhost() then
carDealer.notify(ply, 'warning', 'Ты не можешь загонять автомобили сейчас')
return reply()
end
local catData = carDealer.categories[veh.cdData.category]
local spawns = catData.spawns[game.GetMap()]
or carDealer.civilSpawns[game.GetMap()]
if not spawns then
carDealer.notify(ply, 'warning', 'Напиши админам, что они опростоволосились, и передай привет от автодилера')
return reply()
end
octolib.func.chain({
function(done)
carDealer.nearestPos({
pPos = veh:GetPos(),
vars = spawns,
okDist = 10000,
check = function()
return IsValid(ply) and IsValid(veh)
end,
callback = done,
filter = table.Add(table.Add({ply, veh}, veh:GetChildren()), constraint.GetAllConstrainedEntities(veh)),
})
end,
function(done, pos, _, distSqr)
if not IsValid(ply) or not IsValid(veh) then return end
if not pos then
carDealer.notifty(ply, 'warning', 'Не получилось найти свободное место')
return reply(true)
end
if distSqr > 10000 then
carDealer.notify(ply, 'Оставь свой автомобиль на указанной точке и нажми "Загнать" снова. Если оно будет занято, повтори это действие')
ply:AddMarker({
id = 'car.despawn',
txt = 'Парковочное место',
pos = pos + Vector(0,0,10),
col = Color(255,92,38),
des = {'timedist', {600, 100}},
icon = 'octoteam/icons-16/car.png',
})
reply(true)
else done() end
end,
function(done)
carDealer.saveVeh(veh, done)
end,
function(done)
hook.Run('car-dealer.stored', veh, ply)
carDealer.despawnVeh(veh, done)
carDealer.notify(ply, (veh.cdData.name or 'Автомобиль') .. ' в гараже')
carDealer.clearMarkers(ply)
carDealer.sync(ply)
reply(true)
end,
})
end)
carDealer.Listen('car-dealer.rent', function(reply, ply, class)
if ply:IsGhost() then
carDealer.notify(ply, 'warning', 'Ты не можешь пригонять автомобили сейчас')
return reply()
end
local veh = carDealer.getCurVeh(ply)
if IsValid(veh) then
carDealer.notify(ply, 'warning', 'Сначала надо загнать свой автомобиль')
carDealer.setCurVeh(ply, veh)
return reply()
end
local cdData = carDealer.vehicles[class]
if not cdData then
carDealer.notify(ply, 'warning', 'Не получилось найти данные об автомобиле')
return reply()
end
local category = carDealer.categories[cdData.category]
local ok, why = carDealer.canUse(ply, class)
if not ok or not category or not cdData.deposit then
carDealer.notify(ply, 'warning', why or 'Ты не можешь арендовать этот автомобиль')
return reply()
end
if isfunction(category.spawnCheck) then
local can, why = category.spawnCheck(ply, class)
if can == false then
carDealer.notify(ply, why or 'Ты не можешь пригнать этот автомобиль сейчас')
return reply()
end
end
local price = hook.Run('car-dealer.priceOverride', ply, class) or cdData.price or carDealer.defaultDeposit
if not carDealer.hasMoney(ply, price) then
carDealer.notify(ply, 'warning', 'На банковском счете недостаточно средств')
return reply()
end
if category.queue then
tryQueuedSpawn(ply, class, function(veh)
if not veh then return reply() end
carDealer.addMoney(ply, -price)
carDealer.notify(ply, 'С твоего банковского счета снят залог за ' .. (veh.cdData.name or 'автомобиль') .. ' в размере ' .. carDealer.formatMoney(price))
carDealer.notify(ply, (cdData.name or 'Автомобиль') .. ' ждет тебя неподалеку. Забери его в течение 10 минут, или автомобиль эвакуируют')
veh.deposit = price
reply(true)
end)
else
carDealer.spawnDepositVeh(ply, class, function(ok, veh)
if not ok then
carDealer.notify(ply, 'warning', veh or 'Не получилось создать автомобиль')
return reply()
end
carDealer.addMoney(ply, -price)
carDealer.notify(ply, 'С твоего банковского счета снят залог за ' .. (veh.cdData.name or 'автомобиль') .. ' в размере ' .. carDealer.formatMoney(price))
carDealer.notify(ply, (cdData.name or 'Автомобиль') .. ' ждет тебя неподалеку. Забери его в течение 10 минут, или автомобиль эвакуируют')
veh.deposit = price
reply(true)
end)
end
end)
carDealer.Listen('car-dealer.buy', function(reply, ply, class, bg)
class = class or ''
bg = bg or {}
if ply:IsGhost() then
carDealer.notify(ply, 'warning', 'Ты не можешь покупать автомобили сейчас')
return reply()
end
local cdData = carDealer.vehicles[class]
local category = cdData and carDealer.categories[cdData.category]
local ok, why = carDealer.canBuy(ply, class)
if not ok or not category then
carDealer.notify(ply, 'warning', why or 'Ты не можешь купить этот автомобиль')
return reply()
end
if cdData.deposit then return reply() end
local pr = hook.Run('car-dealer.priceOverride', ply, class, bg) or cdData.price
local bgDefault = cdData.default and cdData.default.bg
local bgData = cdData.bodygroups
if not bgData then
bg = {}
elseif bg then
for k, v in pairs(bg) do
local variant = bgData[k] and bgData[k].variants[v + 1]
if not variant then
bg[k] = nil
continue
end
local originalVal = bgDefault and bgDefault[k] or 0
if v ~= originalVal then
pr = pr + variant[2]
end
end
end
if bgDefault then
for k, v in pairs(bgDefault) do
if not bg[k] then bg[k] = v end
end
end
if not carDealer.hasMoney(ply, pr) then
carDealer.notify(ply, 'warning', carDealer.formatMoney(pr) .. ' должны лежать у тебя в банке')
return reply()
end
carDealer.addMoney(ply, -pr)
carDealer.ownVeh(ply:SteamID(), class, function(id, plate)
carDealer.notify(ply, 'Ты приобрел ' .. (cdData.name or 'Автомобиль') .. ' с регистрационным номером ' .. plate)
hook.Run('car-dealer.bought', class, ply, pr, id)
carDealer.updateVehData(id, { bg = bg })
reply(true)
end)
end)
carDealer.Listen('car-dealer.sell', function(reply, ply, id)
if not id then return end
if ply:IsGhost() then
return reply()
end
local veh
octolib.func.chain({
function(done)
local veh = carDealer.getCurVeh(ply)
if IsValid(veh) and veh:GetNetVar('cd.id') == id then
carDealer.notify(ply, 'Сначала надо загнать свой автомобиль')
return reply()
end
carDealer.getVehById(id, done)
end,
function(done, _veh)
veh = _veh
if not veh or veh.garage ~= ply:SteamID() then
carDealer.notify(ply, 'warning', 'В твоем гараже нет этого автомобиля')
return reply()
end
carDealer.unownVeh(id, done)
end,
function(_, unowned)
if not unowned then return reply() end
local toSend = {}
for _, att in ipairs(veh.data.atts or {}) do
toSend[#toSend + 1] = {'car_att', {
name = att.name,
desc = att.desc,
icon = att.icon,
mass = att.mass,
volume = att.volume,
colorable = att.colorable,
attmdl = att.model,
model = att.model,
skin = att.skin,
scale = att.scale,
}}
end
if #toSend > 0 then
octoinv.addReturnItems(ply, toSend)
carDealer.notify(ply, 'hint', 'На автомобиле были аксессуары, ты можешь их вернуть через магазин')
end
local cdData = carDealer.vehicles[veh.class]
local price = cdData.price * carDealer.sellPrice
carDealer.addMoney(ply, price)
carDealer.notify(ply, 'Ты продал ' .. (cdData.name or 'Автомобиль') .. ' за ' .. DarkRP.formatMoney(price))
if ply:GetLocalVar('car-dealer.queued') and ply:GetLocalVar('car-dealer.queued')[1] == id then
carDealer.removeFromQueue(ply)
end
hook.Run('car-dealer.sold', veh, ply, price)
reply(true)
end,
})
end)