282 lines
9.3 KiB
Lua
282 lines
9.3 KiB
Lua
halloween.items = halloween.items or {}
|
||
halloween.caseItems = halloween.caseItems or {}
|
||
halloween.cases = halloween.cases or {}
|
||
|
||
function halloween.registerItem(id, data)
|
||
if istable(data) or data == nil then
|
||
halloween.items[id] = data
|
||
end
|
||
end
|
||
|
||
function halloween.registerCaseItem(id, data)
|
||
if data == nil then
|
||
halloween.caseItems[id] = nil
|
||
return
|
||
elseif not istable(data) then return end
|
||
data.maxMass, data.maxVolume = data.maxMass or 0, data.maxVolume or 0
|
||
halloween.caseItems[id] = data
|
||
end
|
||
|
||
function halloween.registerCase(id, data)
|
||
if data == nil then
|
||
halloween.cases[id] = nil
|
||
return
|
||
elseif not istable(data) then return end
|
||
data.mass = octolib.array.reduce(data.items, function(a, v) return math.max(a, halloween.caseItems[v[2]].maxMass) end, 0)
|
||
data.volume = octolib.array.reduce(data.items, function(a, v) return math.max(a, halloween.caseItems[v[2]].maxVolume) end, 0)
|
||
octolib.array.shuffle(data.items)
|
||
halloween.cases[id] = data
|
||
end
|
||
|
||
function halloween.getClaimedAmount(ply, id)
|
||
return ply:GetDBVar('hrewards', {})[id] or 0
|
||
end
|
||
|
||
function halloween.getPriceModifier(ply)
|
||
if ply:GetUserGroup() ~= 'user' then return 0.8 end -- 20% discount for staff
|
||
return 1
|
||
end
|
||
|
||
function halloween.sendItems(ply, toSend)
|
||
if #ents.FindByClass('octoinv_mailbox') < 1 then
|
||
ply:Notify('warning', 'На карте нет почтовых ящиков! Обратись к администрации')
|
||
return false
|
||
end
|
||
|
||
local itemsPretty = {}
|
||
for _, item in ipairs(toSend) do
|
||
table.insert(itemsPretty, octoinv.itemStr(item))
|
||
end
|
||
hook.Run('octoinv.shop.order', ply, ply, itemsPretty, 0, 'halloween')
|
||
|
||
timer.Simple(math.random(60, 120), function()
|
||
local box = octoinv.sendToMailbox(ply, toSend)
|
||
ply:AddMarker({
|
||
txt = 'Хэллоуинская доставка',
|
||
pos = box:GetPos() + Vector(0,0,40),
|
||
col = Color(255,92,38),
|
||
des = {'timedist', { 600, 100 }},
|
||
icon = 'octoteam/icons-16/lorry.png',
|
||
})
|
||
ply:Notify('Твой хэллоуинский заказ доставлен в почтовый ящик!')
|
||
end)
|
||
return true
|
||
|
||
end
|
||
|
||
function halloween.claimCase(ply, id, amount, func)
|
||
|
||
local case = halloween.cases[id]
|
||
if not case then return func(false) end
|
||
amount = math.min(math.Round(amount), 100, (case.max or math.huge) - halloween.getClaimedAmount(ply, id))
|
||
if amount <= 0 then return func(false) end
|
||
local cost = case.price * amount * halloween.getPriceModifier(ply)
|
||
if ply:GetNetVar('sweets', 0) < cost then
|
||
ply:Notify('warning', 'У тебя недостаточно конфет!')
|
||
return func(false)
|
||
end
|
||
|
||
local item = octolib.array.series({'h20_case', { cid = id, mass = case.mass, volume = case.volume, expire = os.time() + 86400 }}, amount)
|
||
local sent, msg = halloween.sendItems(ply, item)
|
||
|
||
if sent then
|
||
ply:Notify('hint', 'Загадочная коробка отправлена по почте и придет через пару минут')
|
||
ply:SetDBVar('sweets', ply:GetDBVar('sweets', 0) - cost)
|
||
ply:SetNetVar('sweets', ply:GetDBVar('sweets'))
|
||
else ply:Notify('warning', msg or 'Не удалось отправить загадочную коробку') end
|
||
|
||
func(sent)
|
||
|
||
end
|
||
|
||
function halloween.claim(ply, id, amount, func)
|
||
|
||
func = func or octolib.func.zero
|
||
if not (isstring(id) and isnumber(amount)) then return func(false) end
|
||
|
||
if string.StartWith(id, 'case:') then
|
||
return halloween.claimCase(ply, id:sub(6), amount, func)
|
||
end
|
||
|
||
local data = halloween.items[id]
|
||
if not data then return func(false) end
|
||
amount = math.min(math.Round(amount), 100, (data.max or math.huge) - halloween.getClaimedAmount(ply, id))
|
||
if amount <= 0 then return func(false) end
|
||
|
||
local cost = data.price * amount * halloween.getPriceModifier(ply)
|
||
if ply:GetNetVar('sweets', 0) < cost then
|
||
ply:Notify('warning', 'У тебя недостаточно конфет!')
|
||
return func(false)
|
||
end
|
||
|
||
local sid = ply:SteamID()
|
||
local function reward(succ)
|
||
if not succ then return func(false) end
|
||
octolib.getDBVar(sid, 'hrewards', {}):Then(function(items) -- get items data
|
||
items[id] = (items[id] or 0) + 1
|
||
return octolib.setDBVar(sid, 'hrewards', items) -- update items data
|
||
end):Then(function()
|
||
return octolib.getDBVar(sid, 'sweets', 0) -- get sweets amount
|
||
end):Then(function(sweets)
|
||
if IsValid(ply) then ply:SetNetVar('sweets', sweets - cost) end
|
||
return octolib.setDBVar(sid, 'sweets', sweets - cost) -- update sweets amount
|
||
end):Then(function()
|
||
func(succ) -- callback
|
||
end)
|
||
end
|
||
|
||
if data.deliver then
|
||
return reward(data.deliver(ply, amount))
|
||
end
|
||
|
||
if data.deliverAsync then
|
||
return data.deliverAsync(ply, amount, reward)
|
||
end
|
||
|
||
func(false) -- ???
|
||
|
||
end
|
||
|
||
function halloween.collectData(ply)
|
||
local items = {}
|
||
local claimed = ply:GetDBVar('hrewards', {})
|
||
local sweets = ply:GetDBVar('sweets', 0)
|
||
local priceMod = halloween.getPriceModifier(ply)
|
||
for k, v in pairs(halloween.items) do
|
||
local amount = math.min(100, (v.max or math.huge) - (claimed[k] or 0), math.floor(sweets / (v.price * priceMod)))
|
||
items[#items + 1] = {
|
||
id = k,
|
||
name = v.name,
|
||
icon = v.icon,
|
||
desc = v.desc,
|
||
max = amount,
|
||
mdl = v.mdl,
|
||
skin = v.skin,
|
||
price = v.price * priceMod,
|
||
}
|
||
end
|
||
local caseItems = octolib.table.map(halloween.caseItems, function(v, k) return { id = k, name = v.name, icon = v.icon } end)
|
||
local cases = {}
|
||
for k, v in pairs(halloween.cases) do
|
||
local amount = math.min(100, (v.max or math.huge) - (claimed[k] or 0), math.floor(sweets / (v.price * priceMod)))
|
||
cases[#cases + 1] = {
|
||
id = k,
|
||
name = v.name,
|
||
icon = v.icon,
|
||
desc = v.desc,
|
||
max = amount,
|
||
price = v.price * priceMod,
|
||
items = v.items,
|
||
}
|
||
end
|
||
return { items = items, caseItems = caseItems, cases = cases }
|
||
end
|
||
|
||
netstream.Hook('dbg-halloween.claim', function(ply, ent, id, amount)
|
||
if not IsValid(ent) or not ent:GetNetVar('Jack') then
|
||
return netstream.Start(ply, 'dbg-halloween.closeRewards')
|
||
end
|
||
local head = ply:GetShootPos()
|
||
if ent:NearestPoint(head):DistToSqr(head) > CFG.useDistSqr then
|
||
return netstream.Start(ply, 'dbg-halloween.closeRewards')
|
||
end
|
||
|
||
local responded = false
|
||
local function response()
|
||
if responded then return end
|
||
responded = true
|
||
if not IsValid(ply) then return end
|
||
if ply:GetNetVar('sweets', 0) <= 0 then
|
||
octochat.talkTo(ply, octochat.textColors.rp, 'Джек говорит: ', color_white, 'Здорово поторговались! Спасибо, приятель. Хорошего дня тебе')
|
||
netstream.Start(ply, 'dbg-halloween.closeRewards')
|
||
ply:SetNetVar('sweets')
|
||
ply:SetDBVar('sweets')
|
||
else
|
||
netstream.Start(ply, 'dbg-halloween.openRewards', ent, halloween.collectData(ply), true)
|
||
end
|
||
end
|
||
halloween.claim(ply, id, amount, response)
|
||
timer.Simple(10, response)
|
||
end)
|
||
|
||
netstream.Hook('dbg-halloween.flushRewards', function(ply, ent)
|
||
if not IsValid(ent) or not ent:GetNetVar('Jack') then
|
||
return netstream.Start(ply, 'dbg-halloween.closeRewards')
|
||
end
|
||
local head = ply:GetShootPos()
|
||
if ent:NearestPoint(head):DistToSqr(head) > CFG.useDistSqr then
|
||
return netstream.Start(ply, 'dbg-halloween.closeRewards')
|
||
end
|
||
|
||
local sweets = ply:GetDBVar('sweets')
|
||
if not sweets then
|
||
ply:SetNetVar('sweets')
|
||
return netstream.Start(ply, 'dbg-halloween.closeRewards')
|
||
end
|
||
local money = sweets * 65
|
||
ply:BankAdd(money)
|
||
ply:SetDBVar('sweets')
|
||
ply:SetNetVar('sweets')
|
||
|
||
octochat.talkTo(ply, octochat.textColors.rp, 'Джек говорит: ', color_white, 'Перевел ' .. DarkRP.formatMoney(money) .. ' тебе на банковский счет')
|
||
netstream.Start(ply, 'dbg-halloween.closeRewards')
|
||
end)
|
||
|
||
-- JACK
|
||
local function jackInteraction(self, name, _, ply)
|
||
|
||
if not (name == 'Use' and IsValid(ply) and ply:IsPlayer()) then return end
|
||
local ct = CurTime()
|
||
if (ply.nextRewardsUse or 0) > ct then return end
|
||
|
||
if ply:GetNetVar('sweets', 0) <= 0 then
|
||
ply.nextRewardsUse = ct + 60
|
||
return octochat.talkTo(ply, octochat.textColors.rp, 'Джек говорит: ', color_white, 'Нет конфет? Очень жаль. Надеюсь, увидимся на следующий Хэллоуин!')
|
||
end
|
||
ply.nextRewardsUse = ct + 2
|
||
|
||
netstream.Start(ply, 'dbg-halloween.openRewards', self, halloween.collectData(ply))
|
||
local mod = 1 - halloween.getPriceModifier(ply)
|
||
if mod > 0 then
|
||
octochat.talkTo(ply, octochat.textColors.rp, 'Джек говорит: ', color_white, ('О, мне про тебя рассказывали! Сделаю-ка я тебе скидку в %s%%'):format(mod * 100))
|
||
end
|
||
|
||
end
|
||
|
||
local jackSpawns = {
|
||
rp_eastcoast_v4c = { Vector(-1931.4, 1649.8, 1.5), Angle(0, 90, 0) },
|
||
rp_evocity_dbg_210308 = { Vector(-7851.3, -10327, 72), Angle(0, 90, 0) },
|
||
}
|
||
local function respawnJack()
|
||
|
||
for _, v in ipairs(ents.FindByClass('base_ai')) do
|
||
if v:GetNetVar('Jack') then v:Remove() end
|
||
end
|
||
|
||
local data = jackSpawns[game.GetMap()]
|
||
if not data then return end
|
||
|
||
local jack = ents.Create('base_ai')
|
||
jack:SetPos(data[1])
|
||
jack:SetAngles(data[2])
|
||
jack:SetModel('models/humans/octo/male_09_04.mdl')
|
||
jack:SetSkin(16)
|
||
|
||
jack:SetHullType(HULL_HUMAN)
|
||
jack:SetHullSizeNormal()
|
||
jack:SetNPCState(NPC_STATE_SCRIPT)
|
||
jack:SetSolid(SOLID_BBOX)
|
||
jack:CapabilitiesAdd(bit.bor(CAP_ANIMATEDFACE, CAP_TURN_HEAD))
|
||
jack:SetUseType(SIMPLE_USE)
|
||
|
||
jack:Spawn()
|
||
jack:ResetSequence('idle_all_01')
|
||
jack:SetNetVar('Jack', true)
|
||
jack.AcceptInput = jackInteraction
|
||
|
||
end
|
||
hook.Add('InitPostEntity', 'dbg-halloween.spawnJack', respawnJack)
|
||
concommand.Add('jack_reload', function(ply)
|
||
if IsValid(ply) and not ply:IsAdmin() then return end
|
||
respawnJack()
|
||
end)
|