324 lines
No EOL
13 KiB
Lua
324 lines
No EOL
13 KiB
Lua
-- Initialize config(s)
|
|
local shared = require 'config.shared'
|
|
local sv_config = require 'config.server'
|
|
|
|
-- Initialize global state for cooldowns
|
|
GlobalState.cooldown = false
|
|
GlobalState.started = false
|
|
|
|
-- Initialize proper coordinates
|
|
local gabz = GetResourceState('cfx-gabz-247') == 'started'
|
|
local fm = GetResourceState('cfx-fm-supermarkets') == 'started'
|
|
local stores = gabz and require 'data.gabz' or fm and require 'data.fmshop' or require 'data.default'
|
|
|
|
-- Initialize table to store known locations & robbery states
|
|
local locations, states = {}, {}
|
|
|
|
-- Builds local table containing all locations categorized
|
|
local function InitializeStores()
|
|
for type, coords in pairs(stores) do
|
|
for _, location in pairs(coords) do
|
|
if not locations[type:lower()] then locations[type:lower()] = {} end
|
|
locations[type:lower()][#locations[type:lower()] + 1] = location
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Returns boolean if player is nearby defined coords based on location type
|
|
--- @param source number
|
|
--- @param location string registers, computers, safes
|
|
--- @return boolean
|
|
local function IsPlayerNearby(source, location)
|
|
if not source or not location then return false end
|
|
local playerPos = GetEntityCoords(GetPlayerPed(source))
|
|
for _, coords in pairs(locations[location]) do
|
|
if #(playerPos - coords) <= 2.5 then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Returns boolean if player can start robbery
|
|
--- @param identifier string
|
|
--- @return boolean
|
|
local function CanPlayerRob(identifier)
|
|
if not identifier then return false end
|
|
local currentTime = os.time()
|
|
if shared.setup.global.enable then
|
|
if GlobalState.cooldown or GlobalState.started then
|
|
return false
|
|
end
|
|
end
|
|
if not states[identifier] then return true end
|
|
local lastCompleted = states[identifier].completed
|
|
if lastCompleted then
|
|
if (currentTime - lastCompleted) < shared.setup.cooldown then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- Starts & ends global cooldown if enabled
|
|
local function StartCooldown()
|
|
GlobalState.cooldown = true
|
|
local wait = math.floor(shared.setup.global.duration * 1000)
|
|
SetTimeout(wait, function()
|
|
GlobalState.cooldown = false
|
|
end)
|
|
end
|
|
|
|
-- Callback to initialize store robbery
|
|
--- @param source number
|
|
--- @return boolean
|
|
lib.callback.register('lation_247robbery:StartRobbery', function(source)
|
|
if not source then
|
|
EventLog('[main.lua]: lation_247robbery:StartRobbery: unable to retrieve source', 'error')
|
|
return false
|
|
end
|
|
local source = source
|
|
local identifier = GetIdentifier(source)
|
|
if not identifier then
|
|
EventLog('[main.lua]: lation_247robbery:StartRobbery: unable to retrieve player identifier', 'error')
|
|
return false
|
|
end
|
|
local isNearRegister = IsPlayerNearby(source, 'registers')
|
|
if not isNearRegister then
|
|
EventLog('[main.lua]: lation_247robbery:StartRobbery: player not nearby any registers', 'error')
|
|
return false
|
|
end
|
|
local hasRequiredItem = GetItemCount(source, shared.registers.item) >= 1
|
|
if not hasRequiredItem then
|
|
TriggerClientEvent('lation_247robbery:Notify', source, locale('notify.missing-item'), 'error')
|
|
EventLog('[main.lua]: lation_247robbery:StartRobbery: player missing required item', 'error')
|
|
return false
|
|
end
|
|
if shared.police.count > 0 then
|
|
local police = GetPoliceCount()
|
|
if not police or police < shared.police.count then
|
|
TriggerClientEvent('lation_247robbery:Notify', source, locale('notify.no-police'), 'error')
|
|
EventLog('[main.lua]: lation_247robbery:StartRobbery: not enough police to start robbery', 'error')
|
|
return false
|
|
end
|
|
end
|
|
if not CanPlayerRob(identifier) then
|
|
TriggerClientEvent('lation_247robbery:Notify', source, locale('notify.cooldown'), 'error')
|
|
EventLog('[main.lua]: lation_247robbery:StartRobbery: cooldown is still active (for player or global)', 'error')
|
|
return false
|
|
end
|
|
GlobalState.started = true
|
|
if not states[identifier] then states[identifier] = {} end
|
|
states[identifier].state = 'in_progress'
|
|
states[identifier].started = os.time()
|
|
-- Fallback to reset states if not completed in a reasonable amount of time
|
|
SetTimeout(600000, function() -- 10 minute timeout
|
|
if states[identifier] and states[identifier].state == 'in_progress' then
|
|
states[identifier] = nil
|
|
end
|
|
if GlobalState.started then
|
|
GlobalState.started = false
|
|
end
|
|
end)
|
|
return true
|
|
end)
|
|
|
|
-- Event to handle lockpick breaking chance
|
|
RegisterNetEvent('lation_247robbery:DoesLockpickBreak', function()
|
|
if not source then
|
|
EventLog('[main.lua]: lation_247robbery:DoesLockpickBreak: unable to retrieve source', 'error')
|
|
return
|
|
end
|
|
local source = source
|
|
local identifier = GetIdentifier(source)
|
|
if not identifier then
|
|
EventLog('[main.lua]: lation_247robbery:DoesLockpickBreak: unable to retrieve player identifier', 'error')
|
|
return
|
|
end
|
|
if not GlobalState.started then
|
|
EventLog('[main.lua]: lation_247robbery:RegisterIncomplete: global state wasnt initiated', 'error')
|
|
return
|
|
end
|
|
if not states[identifier] or states[identifier].state ~= 'in_progress' then
|
|
EventLog('[main.lua]: lation_247robbery:DoesLockpickBreak: robbery wasnt initiated for player', 'error')
|
|
return
|
|
end
|
|
local isNearRegister = IsPlayerNearby(source, 'registers')
|
|
if not isNearRegister then
|
|
EventLog('[main.lua]: lation_247robbery:DoesLockpickBreak: player not nearby any registers', 'error')
|
|
return
|
|
end
|
|
if math.random(100) <= shared.registers.breakChance then
|
|
RemoveItem(source, shared.registers.item, 1)
|
|
TriggerClientEvent('lation_247robbery:Notify', source, locale('notify.item-broke'), 'error')
|
|
end
|
|
if GlobalState.started then GlobalState.started = false end
|
|
end)
|
|
|
|
-- Event to handle robbery completion and rewards
|
|
RegisterNetEvent('lation_247robbery:CompleteRegisterRobbery', function()
|
|
if not source then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteRegisterRobbery: unable to retrieve source', 'error')
|
|
return
|
|
end
|
|
local source = source
|
|
local identifier = GetIdentifier(source)
|
|
if not identifier then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteRegisterRobbery: unable to retrieve player identifier', 'error')
|
|
return
|
|
end
|
|
local name = GetName(source)
|
|
if not name then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteRegisterRobbery: unable to retrieve player name', 'error')
|
|
return
|
|
end
|
|
if not states[identifier] or states[identifier].state ~= 'in_progress' then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteRegisterRobbery: robbery wasnt initiated for player', 'error')
|
|
return
|
|
end
|
|
if not GlobalState.started then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteRegisterRobbery: global state wasnt initiated', 'error')
|
|
return
|
|
end
|
|
local isNearRegister = IsPlayerNearby(source, 'registers')
|
|
if not isNearRegister then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteRegisterRobbery: player not nearby any registers', 'error')
|
|
return
|
|
end
|
|
local police = shared.police.risk and GetPoliceCount() or 0
|
|
local items = {}
|
|
for _, add in pairs(shared.registers.reward) do
|
|
if math.random(100) <= add.chance then
|
|
local quantity = math.random(add.min, add.max)
|
|
if police > 0 then
|
|
local increase = 1 + (police * shared.police.percent / 100)
|
|
quantity = math.floor(quantity * increase)
|
|
end
|
|
if add.metadata then
|
|
AddItem(source, add.item, quantity, add.metadata)
|
|
else
|
|
if add.item == 'cash' or add.item == 'money' or add.item == 'bank' then
|
|
AddMoney(source, add.item, quantity)
|
|
else
|
|
AddItem(source, add.item, quantity)
|
|
end
|
|
end
|
|
items[#items + 1] = { item = add.item, quantity = quantity }
|
|
end
|
|
end
|
|
local rewards = ''
|
|
for _, reward in ipairs(items) do
|
|
rewards = rewards .. 'x' .. reward.quantity .. ' ' ..reward.item .. ', '
|
|
end
|
|
rewards = rewards:sub(1, -3)
|
|
states[identifier].state = 'completed'
|
|
states[identifier].completed = os.time()
|
|
if sv_config.logs.events.register_robbed and #items > 0 then
|
|
---@diagnostic disable-next-line: undefined-field
|
|
PlayerLog(source, locale('logs.register-robbed-title'), locale('logs.register-robbed-message', name, identifier, rewards))
|
|
end
|
|
end)
|
|
|
|
-- Event to handle robbery completion and rewards
|
|
RegisterNetEvent('lation_247robbery:CompleteSafeRobbery', function()
|
|
if not source then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteSafeRobbery: unable to retrieve source', 'error')
|
|
return
|
|
end
|
|
local source = source
|
|
local identifier = GetIdentifier(source)
|
|
if not identifier then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteSafeRobbery: unable to retrieve player identifier', 'error')
|
|
return
|
|
end
|
|
local name = GetName(source)
|
|
if not name then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteSafeRobbery: unable to retrieve player name', 'error')
|
|
return
|
|
end
|
|
if not GlobalState.started then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteSafeRobbery: global state wasnt initiated', 'error')
|
|
return
|
|
end
|
|
if not states[identifier] or states[identifier].state ~= 'completed' then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteSafeRobbery: player has not completed the register robbery', 'error')
|
|
return
|
|
end
|
|
local isNearSafe = IsPlayerNearby(source, 'safes')
|
|
if not isNearSafe then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteSafeRobbery: player not nearby any safes', 'error')
|
|
return
|
|
end
|
|
local police = shared.police.risk and GetPoliceCount() or 0
|
|
local items = {}
|
|
for _, add in pairs(shared.safes.reward) do
|
|
if math.random(100) <= add.chance then
|
|
local quantity = math.random(add.min, add.max)
|
|
if police > 0 then
|
|
local increase = 1 + (police * shared.police.percent / 100)
|
|
quantity = math.floor(quantity * increase)
|
|
end
|
|
if add.metadata then
|
|
AddItem(source, add.item, quantity, add.metadata)
|
|
else
|
|
if add.item == 'cash' or add.item == 'money' or add.item == 'bank' then
|
|
AddMoney(source, add.item, quantity)
|
|
else
|
|
AddItem(source, add.item, quantity)
|
|
end
|
|
end
|
|
items[#items + 1] = { item = add.item, quantity = quantity }
|
|
end
|
|
end
|
|
local rewards = ''
|
|
for _, reward in ipairs(items) do
|
|
rewards = rewards .. 'x' .. reward.quantity .. ' ' ..reward.item .. ', '
|
|
end
|
|
rewards = rewards:sub(1, -3)
|
|
GlobalState.started = false
|
|
states[identifier].state = nil
|
|
states[identifier].completed = os.time()
|
|
StartCooldown()
|
|
if sv_config.logs.events.safe_robbed and #items > 0 then
|
|
---@diagnostic disable-next-line: undefined-field
|
|
PlayerLog(source, locale('logs.safe-robbed-title'), locale('logs.safe-robbed-message', name, identifier, rewards))
|
|
end
|
|
end)
|
|
|
|
-- Event to handle failed robbery
|
|
RegisterNetEvent('lation_247robbery:FailedRobbery', function()
|
|
if not source then
|
|
EventLog('[main.lua]: lation_247robbery:FailedRobbery: unable to retrieve source', 'error')
|
|
return
|
|
end
|
|
local source = source
|
|
local identifier = GetIdentifier(source)
|
|
if not identifier then
|
|
EventLog('[main.lua]: lation_247robbery:FailedRobbery: unable to retrieve player identifier', 'error')
|
|
return
|
|
end
|
|
local name = GetName(source)
|
|
if not name then
|
|
EventLog('[main.lua]: lation_247robbery:FailedRobbery: unable to retrieve player name', 'error')
|
|
return
|
|
end
|
|
if not GlobalState.started then
|
|
EventLog('[main.lua]: lation_247robbery:FailedRobbery: global state wasnt initiated', 'error')
|
|
return
|
|
end
|
|
if not states[identifier] or states[identifier].state ~= 'completed' then
|
|
EventLog('[main.lua]: lation_247robbery:FailedRobbery: robbery wasnt initiated for player', 'error')
|
|
return
|
|
end
|
|
local isNearRegister = IsPlayerNearby(source, 'computers')
|
|
if not isNearRegister then
|
|
EventLog('[main.lua]: lation_247robbery:CompleteRegisterRobbery: player not nearby any registers', 'error')
|
|
return
|
|
end
|
|
GlobalState.started = false
|
|
states[identifier].state = nil
|
|
states[identifier].completed = os.time()
|
|
StartCooldown()
|
|
end)
|
|
|
|
InitializeStores() |