Scripts/resources/[qb]/[qb_crimes]/qb-traphouse/client/main.lua
2024-12-29 21:03:28 +01:00

624 lines
22 KiB
Lua

local QBCore = exports['qb-core']:GetCoreObject()
local PlayerData = {}
local ClosestTraphouse = nil
local InsideTraphouse = false
local CurrentTraphouse = nil
local TraphouseObj = {}
local POIOffsets = nil
local IsKeyHolder = false
local IsHouseOwner = false
local CanRob = true
local IsRobbingNPC = false
local RobbingTime = 3
-- zone check
local isInsideEntranceTarget = false
local isInsideExitTarget = false
local isInsideInteractionTarget = false
-- Functions
local function RegisterTraphouseEntranceTarget(traphouseID, traphouseData)
local coords = traphouseData.coords['enter']
local boxName = 'traphouseEntrance' .. traphouseID
local boxData = traphouseData.polyzoneBoxData['enter']
exports['qb-target']:AddBoxZone(boxName, coords, boxData.length, boxData.width, {
name = boxName,
heading = boxData.heading,
debugPoly = boxData.debug,
minZ = boxData.minZ,
maxZ = boxData.maxZ,
}, {
options = {
{
type = 'client',
event = 'qb-traphouse:client:EnterTraphouse',
label = Lang:t('targetInfo.enter'),
},
},
distance = boxData.distance
})
Config.TrapHouses[traphouseID].polyzoneBoxData['enter'].created = true
end
local function RegisterTraphouseEntranceZone(traphouseID, traphouseData)
local coords = traphouseData.coords['enter']
local boxName = 'traphouseEntrance' .. traphouseID
local boxData = traphouseData.polyzoneBoxData['enter']
local zone = BoxZone:Create(coords, boxData.length, boxData.width, {
name = boxName,
heading = boxData.heading,
debugPoly = boxData.debug,
minZ = boxData.minZ,
maxZ = boxData.maxZ,
})
zone:onPlayerInOut(function (isPointInside)
if isPointInside then
exports['qb-core']:DrawText('[E] ' .. Lang:t('targetInfo.enter'), 'top')
else
exports['qb-core']:HideText()
end
isInsideEntranceTarget = isPointInside
end)
boxData.created = true
boxData.zone = zone
end
local function SetTraphouseEntranceTargets()
if Config.TrapHouses and next(Config.TrapHouses) then
for id, traphouse in pairs(Config.TrapHouses) do
if traphouse and traphouse.coords and traphouse.coords['enter'] then
if Config.UseTarget then
RegisterTraphouseEntranceTarget(id, traphouse)
else
RegisterTraphouseEntranceZone(id, traphouse)
end
end
end
end
end
local function RegisterTraphouseInteractionZone(traphouseID, traphouseData)
local coords = traphouseData.coords['interaction']
local boxName = 'traphouseInteraction' .. traphouseID
local boxData = traphouseData.polyzoneBoxData['interaction']
local zone = BoxZone:Create(coords, boxData.length, boxData.width, {
name = boxName,
heading = boxData.heading,
debugPoly = boxData.debug,
minZ = coords.z - 1.0,
maxZ = coords.z + 1.0,
})
zone:onPlayerInOut(function (isPointInside)
if isPointInside then
exports['qb-core']:DrawText('[E] ' .. Lang:t('targetInfo.options'), 'top')
else
exports['qb-core']:HideText()
TriggerEvent('qb-traphouse:client:target:CloseMenu')
end
isInsideInteractionTarget = isPointInside
end)
boxData.created = true
boxData.zone = zone
end
local function RegisterTraphouseInteractionTarget(traphouseID, traphouseData)
local coords = traphouseData.coords['interaction']
local boxName = 'traphouseInteraction' .. traphouseID
local boxData = traphouseData.polyzoneBoxData['interaction']
local options = {
{
type = "client",
event = "qb-traphouse:client:target:TakeOver",
label = Lang:t("targetInfo.take_over"),
},
}
if IsKeyHolder then
options = {
{
type = "client",
event = "qb-traphouse:client:target:ViewInventory",
label = Lang:t("targetInfo.inventory"),
traphouseData = traphouseData
},
{
type = "client",
event = "qb-traphouse:client:target:TakeMoney",
label = Lang:t('targetInfo.take_cash', {value = traphouseData.money}),
},
}
if IsHouseOwner then
options[#options+1] = {
type = "client",
event = "qb-traphouse:client:target:SeePinCode",
label = Lang:t("targetInfo.pin_code_see"),
traphouseData = traphouseData
}
end
end
exports['qb-target']:AddBoxZone(boxName, coords, boxData.length, boxData.width, {
name = boxName,
heading = boxData.heading,
debugPoly = boxData.debug,
minZ = coords.z - 1.0,
maxZ = coords.z + 1.0,
}, {
options = options,
distance = boxData.distance
})
boxData.created = true
end
local function RegisterTraphouseExitZone(coords, traphouseID, traphouseData)
local boxName = 'traphouseExit' .. traphouseID
local boxData = traphouseData.polyzoneBoxData['exit']
local zone = BoxZone:Create(coords, boxData.length, boxData.width, {
name = boxName,
heading = boxData.heading,
debugPoly = boxData.debug,
minZ = coords.z - 1.0,
maxZ = coords.z + 1.0,
})
zone:onPlayerInOut(function (isPointInside)
if isPointInside then
exports['qb-core']:DrawText('[E] ' .. Lang:t("targetInfo.leave"), 'top')
else
exports['qb-core']:HideText()
end
isInsideExitTarget = isPointInside
end)
boxData.created = true
boxData.zone = zone
end
local function RegisterTraphouseExitTarget(coords, traphouseID, traphouseData)
local boxName = 'traphouseExit' .. traphouseID
local boxData = traphouseData.polyzoneBoxData['exit']
exports['qb-target']:AddBoxZone(boxName, coords, boxData.length, boxData.width, {
name = boxName,
heading = boxData.heading,
debugPoly = boxData.debug,
minZ = coords.z - 1.0,
maxZ = coords.z + 1.0,
}, {
options = {
{
type = "client",
event = "qb-traphouse:client:target:ExitTraphouse",
label = Lang:t("targetInfo.leave"),
traphouseID = traphouseID,
},
},
distance = boxData.distance
})
boxData.created = true
end
local function OpenHeaderMenu(data)
local headerMenu = {}
headerMenu[#headerMenu+1] = {
header = Lang:t("targetInfo.options"),
isMenuHeader = true
}
if IsKeyHolder then
headerMenu[#headerMenu+1] = {
header = Lang:t("targetInfo.inventory"),
params = {
event = "qb-traphouse:client:target:ViewInventory",
args = {
traphouseData = data
}
}
}
headerMenu[#headerMenu+1] = {
header = Lang:t('targetInfo.take_cash', {value = data.money}),
params = {
event = "qb-traphouse:client:target:TakeMoney"
}
}
if IsHouseOwner then
headerMenu[#headerMenu+1] = {
header = Lang:t("targetInfo.pin_code_see"),
params = {
event = "qb-traphouse:client:target:SeePinCode",
args = {
traphouseData = data
}
}
}
end
else
headerMenu[#headerMenu+1] = {
header = Lang:t("targetInfo.take_over"),
params = {
event = "qb-traphouse:client:target:TakeOver",
}
}
end
headerMenu[#headerMenu+1] = {
header = Lang:t("targetInfo.close_menu"),
params = {
event = "qb-traphouse:client:target:CloseMenu",
}
}
exports['qb-menu']:openMenu(headerMenu)
end
local function HasKey(CitizenId)
local haskey = false
if ClosestTraphouse ~= nil then
if Config.TrapHouses[ClosestTraphouse].keyholders ~= nil and next(Config.TrapHouses[ClosestTraphouse].keyholders) ~= nil then
for _, data in pairs(Config.TrapHouses[ClosestTraphouse].keyholders) do
if data.citizenid == CitizenId then
haskey = true
end
end
end
end
return haskey
end
local function IsOwner(CitizenId)
local retval = false
if ClosestTraphouse ~= nil then
if Config.TrapHouses[ClosestTraphouse].keyholders ~= nil and next(Config.TrapHouses[ClosestTraphouse].keyholders) ~= nil then
for _, data in pairs(Config.TrapHouses[ClosestTraphouse].keyholders) do
if data.citizenid == CitizenId then
if data.owner then
retval = true
else
retval = false
end
end
end
end
end
return retval
end
local function SetClosestTraphouse()
local pos = GetEntityCoords(PlayerPedId(), true)
local current = nil
local dist = nil
for id, _ in pairs(Config.TrapHouses) do
if current ~= nil then
if #(pos - Config.TrapHouses[id].coords.enter) < dist then
current = id
dist = #(pos - Config.TrapHouses[id].coords.enter)
end
else
dist = #(pos - Config.TrapHouses[id].coords.enter)
current = id
end
end
ClosestTraphouse = current
IsKeyHolder = HasKey(PlayerData.citizenid)
IsHouseOwner = IsOwner(PlayerData.citizenid)
end
local function EnterTraphouse(data)
local coords = { x = data.coords["enter"].x, y = data.coords["enter"].y, z= data.coords["enter"].z - Config.MinZOffset}
TriggerServerEvent("InteractSound_SV:PlayOnSource", "houses_door_open", 0.25)
data = exports['qb-interior']:CreateTrevorsShell(coords)
TraphouseObj = data[1]
POIOffsets = data[2]
CurrentTraphouse = ClosestTraphouse
InsideTraphouse = true
TriggerEvent('qb-weathersync:client:DisableSync')
FreezeEntityPosition(TraphouseObj, true)
end
local function LeaveTraphouse(k, data)
local ped = PlayerPedId()
TriggerServerEvent("InteractSound_SV:PlayOnSource", "houses_door_open", 0.25)
DoScreenFadeOut(250)
Wait(250)
exports['qb-interior']:DespawnInterior(TraphouseObj, function()
TriggerEvent('qb-weathersync:client:EnableSync')
DoScreenFadeIn(250)
SetEntityCoords(ped, data.coords["enter"].x, data.coords["enter"].y, data.coords["enter"].z + 0.5)
SetEntityHeading(ped, 107.71)
TraphouseObj = nil
POIOffsets = nil
CurrentTraphouse = nil
InsideTraphouse = false
end)
if Config.UseTarget then
exports['qb-target']:RemoveZone('traphouseInteraction' .. k)
data.polyzoneBoxData['interaction'].created = false
exports['qb-target']:RemoveZone('traphouseExit' .. k)
data.polyzoneBoxData['exit'].created = false
else
if Config.TrapHouses[k] and Config.TrapHouses[k].polyzoneBoxData['interaction'] and Config.TrapHouses[k].polyzoneBoxData['interaction'].zone then
Config.TrapHouses[k].polyzoneBoxData['interaction'].zone:destroy()
Config.TrapHouses[k].polyzoneBoxData['interaction'].created = false
Config.TrapHouses[k].polyzoneBoxData['interaction'].zone = nil
end
if Config.TrapHouses[k] and Config.TrapHouses[k].polyzoneBoxData['exit'] and Config.TrapHouses[k].polyzoneBoxData['exit'].zone then
Config.TrapHouses[k].polyzoneBoxData['exit'].zone:destroy()
Config.TrapHouses[k].polyzoneBoxData['exit'].created = false
Config.TrapHouses[k].polyzoneBoxData['exit'].zone = nil
end
isInsideExitTarget = false
isInsideInteractionTarget = false
end
end
local function RobTimeout(timeout)
SetTimeout(timeout, function()
CanRob = true
end)
end
-- Events
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
end)
RegisterNetEvent('qb-traphouse:client:EnterTraphouse', function()
if ClosestTraphouse ~= nil then
local data = Config.TrapHouses[ClosestTraphouse]
if not IsKeyHolder then
SendNUIMessage({
action = "open"
})
SetNuiFocus(true, true)
else
EnterTraphouse(data)
end
end
end)
RegisterNetEvent('qb-traphouse:client:TakeoverHouse', function(TraphouseId)
QBCore.Functions.Progressbar("takeover_traphouse", Lang:t("info.taking_over"), math.random(1000, 3000), false, true, {
disableMovement = true,
disableCarMovement = true,
disableMouse = false,
disableCombat = true,
}, {}, {}, {}, function() -- Done
TriggerServerEvent('qb-traphouse:server:AddHouseKeyHolder', PlayerData.citizenid, TraphouseId, true)
end, function()
QBCore.Functions.Notify(Lang:t("error.cancelled"), "error")
end)
end)
RegisterNetEvent('qb-traphouse:client:target:ViewInventory', function (data)
local TraphouseInventory = {}
TraphouseInventory.label = "traphouse_"..CurrentTraphouse
TraphouseInventory.items = data.traphouseData.inventory
TraphouseInventory.slots = 2
TriggerServerEvent("inventory:server:OpenInventory", "traphouse", TraphouseInventory.label, TraphouseInventory)
end)
RegisterNetEvent('qb-traphouse:client:target:TakeOver', function ()
TriggerServerEvent('qb-traphouse:server:TakeoverHouse', CurrentTraphouse)
end)
RegisterNetEvent('qb-traphouse:client:target:TakeMoney', function ()
TriggerServerEvent("qb-traphouse:server:TakeMoney", CurrentTraphouse)
end)
RegisterNetEvent('qb-traphouse:client:target:SeePinCode', function (data)
QBCore.Functions.Notify(Lang:t('info.pin_code', { value = data.traphouseData.pincode }))
end)
RegisterNetEvent('qb-traphouse:client:target:ExitTraphouse', function (data)
LeaveTraphouse(data.traphouseID, Config.TrapHouses[data.traphouseID])
end)
RegisterNetEvent('qb-traphouse:client:SyncData', function(k, data)
Config.TrapHouses[k] = data
IsKeyHolder = HasKey(PlayerData.citizenid)
IsHouseOwner = IsOwner(PlayerData.citizenid)
if Config.UseTarget then
exports['qb-target']:RemoveZone('traphouseInteraction' .. k)
Config.TrapHouses[k].polyzoneBoxData['interaction'].created = false
else
if Config.TrapHouses[k] and Config.TrapHouses[k].polyzoneBoxData['interaction'] and Config.TrapHouses[k].polyzoneBoxData['interaction'].zone then
Config.TrapHouses[k].polyzoneBoxData['interaction'].zone:destroy()
Config.TrapHouses[k].polyzoneBoxData['interaction'].created = false
Config.TrapHouses[k].polyzoneBoxData['interaction'].zone = nil
end
isInsideInteractionTarget = false
end
end)
RegisterNetEvent('qb-traphouse:client:target:CloseMenu', function ()
TriggerEvent('qb-menu:client:closeMenu')
end)
-- NUI
RegisterNUICallback('PinpadClose', function(_, cb)
SetNuiFocus(false, false)
cb('ok')
end)
RegisterNUICallback('ErrorMessage', function(data, cb)
QBCore.Functions.Notify(data.message, 'error')
cb('ok')
end)
RegisterNUICallback('EnterPincode', function(d, cb)
local data = Config.TrapHouses[ClosestTraphouse]
if tonumber(d.pin) == data.pincode then
EnterTraphouse(data)
else
QBCore.Functions.Notify(Lang:t("error.incorrect_code"), 'error')
end
cb('ok')
end)
-- Threads
CreateThread(function()
while true do
local aiming, targetPed = GetEntityPlayerIsFreeAimingAt(PlayerId(-1))
if targetPed ~= 0 and not IsPedAPlayer(targetPed) then
local ped = PlayerPedId()
local pos = GetEntityCoords(ped)
if ClosestTraphouse ~= nil then
local data = Config.TrapHouses[ClosestTraphouse]
local dist = #(pos - data.coords["enter"])
if dist < 200 then
if aiming then
local pcoords = GetEntityCoords(targetPed)
local peddist = #(pos - pcoords)
local InDistance = false
if peddist < 4 then
InDistance = true
if not IsRobbingNPC and CanRob then
if IsPedInAnyVehicle(targetPed) then
TaskLeaveVehicle(targetPed, GetVehiclePedIsIn(targetPed), 1)
end
Wait(500)
InDistance = true
local dict = 'random@mugging3'
RequestAnimDict(dict)
while not HasAnimDictLoaded(dict) do
Wait(10)
end
SetEveryoneIgnorePlayer(PlayerId(), true)
TaskStandStill(targetPed, RobbingTime * 1000)
FreezeEntityPosition(targetPed, true)
SetBlockingOfNonTemporaryEvents(targetPed, true)
TaskPlayAnim(targetPed, dict, 'handsup_standing_base', 2.0, -2, 15.0, 1, 0, 0, 0, 0)
for _ = 1, RobbingTime / 2, 1 do
PlayPedAmbientSpeechNative(targetPed, "GUN_BEG", "SPEECH_PARAMS_FORCE_NORMAL_CLEAR")
Wait(2000)
end
FreezeEntityPosition(targetPed, true)
IsRobbingNPC = true
SetTimeout(RobbingTime, function()
IsRobbingNPC = false
RobTimeout(math.random(30000, 60000))
if not IsEntityDead(targetPed) then
if CanRob then
if InDistance then
SetEveryoneIgnorePlayer(PlayerId(), false)
SetBlockingOfNonTemporaryEvents(targetPed, false)
FreezeEntityPosition(targetPed, false)
ClearPedTasks(targetPed)
AddShockingEventAtPosition(99, GetEntityCoords(targetPed), 0.5)
TriggerServerEvent('qb-traphouse:server:RobNpc', ClosestTraphouse)
CanRob = false
end
end
end
end)
end
else
if InDistance then
InDistance = false
end
end
end
end
else
Wait(1000)
end
end
Wait(3)
end
end)
CreateThread(function ()
local wait = 500
while not LocalPlayer.state.isLoggedIn do
-- do nothing
Wait(wait)
end
SetTraphouseEntranceTargets()
if QBCore.Functions.GetPlayerData() ~= nil then
PlayerData = QBCore.Functions.GetPlayerData()
end
while true do
wait = 500
SetClosestTraphouse()
if ClosestTraphouse ~= nil then
if not InsideTraphouse then
if isInsideEntranceTarget then
wait = 0
if IsControlJustPressed(0, 38) then
TriggerEvent("qb-traphouse:client:EnterTraphouse")
exports['qb-core']:HideText()
end
end
else
local data = Config.TrapHouses[ClosestTraphouse]
if not data.polyzoneBoxData['exit'].created then
local exitCoords = vector3(data.coords["enter"].x + POIOffsets.exit.x, data.coords["enter"].y + POIOffsets.exit.y, data.coords["enter"].z - Config.MinZOffset + POIOffsets.exit.z)
if Config.UseTarget then
RegisterTraphouseExitTarget(exitCoords, CurrentTraphouse, data)
else
RegisterTraphouseExitZone(exitCoords, CurrentTraphouse, data)
end
end
if not data.polyzoneBoxData['interaction'].created then
if Config.UseTarget then
RegisterTraphouseInteractionTarget(CurrentTraphouse, data)
else
RegisterTraphouseInteractionZone(CurrentTraphouse, data)
end
end
if isInsideExitTarget then
wait = 0
if IsControlJustPressed(0, 38) then
LeaveTraphouse(ClosestTraphouse, data)
exports['qb-core']:HideText()
end
end
if isInsideInteractionTarget then
wait = 0
if IsControlJustPressed(0, 38) then
OpenHeaderMenu(data)
exports['qb-core']:HideText()
end
end
end
end
Wait(wait)
end
end)