1
0
Fork 0
forked from Simnation/Main
Main/resources/[Developer]/[Nordi]/0r-atmrobbery/escrow/rope/client.lua
2025-06-07 08:51:21 +02:00

373 lines
13 KiB
Lua

--[[ require ]]
local Utils = require 'modules.utils.client'
local Target = require 'modules.target.client'
--[[ state ]]
Rope = {}
local playerRopes = {}
local ownedHookObject = nil
local ownedFakeAtmObject = nil
local ownedAnchorThread = false
--[[ helper functions ]]
function deletePlayerRope(owner)
if not playerRopes[owner] then return end
if DoesPlayerRopeExist(owner) then
DeleteRope(playerRopes[owner].id)
end
cleanup_rope_textures()
playerRopes[owner] = nil
end
function deletePlayerRopes()
for _, rope in pairs(playerRopes) do
if DoesRopeExist(rope.id) then
DeleteRope(rope.id)
end
end
playerRopes = {}
end
function deleteHookObject()
if not ownedHookObject or not DoesEntityExist(ownedHookObject) then return end
SetEntityAsMissionEntity(ownedHookObject, true, true)
DeleteEntity(ownedHookObject)
ownedHookObject = nil
end
function deleteFakeAtmEntity()
if not ownedFakeAtmObject or not DoesEntityExist(ownedFakeAtmObject) then return end
SetEntityAsMissionEntity(ownedFakeAtmObject, true, true)
DeleteEntity(ownedFakeAtmObject)
ownedFakeAtmObject = nil
end
function giveHookToPedHand()
deleteHookObject()
local playerPedId = cache.ped
local hookModel = 'prop_rope_hook_01'
lib.requestModel(hookModel)
local hookCoords = GetEntityCoords(playerPedId)
ownedHookObject = Utils.CreateObject(hookModel, hookCoords, nil, true, true, false)
local boneIndex = GetPedBoneIndex(playerPedId, 57005)
AttachEntityToEntity(ownedHookObject, playerPedId, boneIndex,
0.15, 0.0, -0.05, 120.0, 0.0, 15.0, true, false, false, true, 2, true)
end
function cleanup_rope_textures()
if #GetAllRopes() == 0 then
RopeUnloadTextures()
end
end
function addRopeToPlayer(owner, attach)
while not RopeAreTexturesLoaded() do
RopeLoadTextures()
Citizen.Wait(0)
end
local coords = GetEntityCoords(cache.ped)
local rope = AddRope(
coords.x, coords.y, coords.z,
0.0, 0.0, 0.0,
1.0,
4, 7.0, 1.0, 0,
false, false, false, 0, false, 0
)
if not DoesRopeExist(rope) then
cleanup_rope_textures()
return false
end
playerRopes[owner] = { id = rope, attach = attach }
return rope
end
function attachRopeToObject(rope, ent1, ent2, offset1, offset2)
AttachEntitiesToRope(rope, ent1, ent2,
offset1.x, offset1.y, offset1.z,
offset2.x, offset2.y, offset2.z,
7.0, 0, 0, 'rope_attach_a', 'rope_attach_b')
end
function DoesPlayerRopeExist(owner, attach)
local playerRope = playerRopes[owner]
local state = playerRope and DoesRopeExist(playerRope.id)
if not state then return false end
if attach and playerRope.attach ~= attach then
state = false
end
return state
end
function onOwnedAnchorCreated()
if ownedAnchorThread then return end
Citizen.CreateThread(function()
local textUI = false
local attachedVehicle = nil
ownedAnchorThread = true
while ownedAnchorThread do
local wait = 500
local entityCoords = GetEntityCoords(cache.ped)
local closestVehicle = lib.getClosestVehicle(entityCoords, 5.0, false)
local distanceFromFakeAtm = #(entityCoords - GetEntityCoords(ownedFakeAtmObject))
if distanceFromFakeAtm < 2.0 then
wait = 5
if not textUI then
textUI = true
Utils.ShowTextUI('[E] ' .. locale('remove_rope'))
end
if IsControlJustPressed(0, 38) then
Utils.HideTextUI()
deleteHookObject()
deleteFakeAtmEntity()
TriggerServerEvent(_e('server:rope:DeletePlayerRope'))
client.setBusy(false, 'rope.removeatmrope')
ownedAnchorThread = false
return
end
elseif closestVehicle then
local offsetCoords = GetOffsetFromEntityInWorldCoords(closestVehicle, 0, -2.3, 0.0)
if #(entityCoords - offsetCoords) < 1.5 then
wait = 5
if not textUI then
textUI = true
Utils.ShowTextUI('[E] ' .. locale('attach_rope'))
end
if IsControlJustPressed(0, 38) then
Utils.HideTextUI()
attachedVehicle = closestVehicle
break
end
elseif textUI then
Utils.HideTextUI()
textUI = false
end
elseif textUI then
Utils.HideTextUI()
textUI = false
end
Citizen.Wait(wait)
end
ownedAnchorThread = false
if not attachedVehicle then return end
TriggerServerEvent(_e('server:rope:attachRopeWithVehicle'),
ObjToNet(ownedFakeAtmObject),
VehToNet(attachedVehicle))
deleteHookObject()
Citizen.SetTimeout(10000, function()
if not ownedFakeAtmObject or not DoesEntityExist(ownedFakeAtmObject) then return end
local coords = GetEntityCoords(ownedFakeAtmObject)
local model = GetEntityModel(ownedFakeAtmObject)
TriggerServerEvent(_e('server:rope:onAtmRipped'), coords, model)
SetEntityVisible(ownedFakeAtmObject, true)
FreezeEntityPosition(ownedFakeAtmObject, false)
SetObjectPhysicsParams(ownedFakeAtmObject, 170.0, -1.0, 30.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0)
local forceDirection = vector3(2.0, 2.0, 2.0)
ApplyForceToEntity(ownedAtm, 1,
forceDirection.x, forceDirection.y, forceDirection.z,
0, 0, 0, true, true, true, true, false, true)
end)
end)
end
function addRobTargetToAtm()
Target.AddLocalEntity(ownedFakeAtmObject, { {
label = locale('collect'),
icon = 'fa-solid fa-money-bill-1-wave',
distance = 2.0,
canInteract = function()
return Entity(ownedFakeAtmObject) and Entity(ownedFakeAtmObject)?.state?.robbable
end,
onSelect = function()
client.setBusy(false, 'rope.onAtmRobbed')
Target.RemoveLocalEntity(ownedFakeAtmObject)
Entity(ownedFakeAtmObject).state.robbable = false
Entity(ownedFakeAtmObject).state.robbed = true
TriggerServerEvent(_e('server:rope:DeletePlayerRope'))
SetEntityAsNoLongerNeeded(ownedFakeAtmObject)
ownedFakeAtmObject = nil
lib.playAnim(cache.ped, 'amb@medic@standing@tendtodead@idle_a', 'idle_a')
lib.progressBar({
duration = 3500,
position = 'bottom',
label = locale('collect'),
useWhileDead = false,
canCancel = false,
disable = { car = true, move = true, combat = true, sprint = true },
})
ClearPedTasks(ped)
TriggerServerEvent(_e('server:GiveItem'),
Config.Rope.reward.name,
math.random(Config.Rope.reward.min, Config.Rope.reward.max))
end
} })
end
--[[ functions ]]
function Rope.CreateAtmRope(_, model)
Utils.debug('Rope.CreateAtmRope | Selected ATM Model: ', model)
local pedCoords = GetEntityCoords(cache.ped)
local entity = GetClosestObjectOfType(pedCoords.x, pedCoords.y, pedCoords.z, 2.0,
model, false, false, false)
if not DoesEntityExist(entity) then return end
local atmCoords = GetEntityCoords(entity)
local atmRotation = GetEntityRotation(entity)
local atmModel = GetEntityModel(entity)
if Entity(entity).state.robbed then
return Utils.Notify(locale('atm_can_not_be_rob'), 'error')
end
if lib.callback.await(_e('server:IsAtmHacked'), false, atmModel, atmCoords) then
return Utils.Notify(locale('atm_can_not_be_hack'), 'error')
end
if not lib.callback.await(_e('server:HasItem'), false, Config.Rope.requiredItem.name) then
return Utils.Notify(locale('need_item', Config.Rope.requiredItem.label), 'error')
end
Utils.TriggerPoliceAlert(atmCoords)
client.setHeadingToObject(atmModel)
client.setBusy(true, 'rope.createatmrope')
lib.playAnim(cache.ped, 'missmechanic', 'work2_base', nil, nil, nil, 1)
Citizen.Wait(2500)
ClearPedTasks(cache.ped)
giveHookToPedHand()
ownedFakeAtmObject = Utils.CreateObject(atmModel, atmCoords, atmRotation, true, true, false)
Entity(ownedFakeAtmObject).state.isFakeAtm = true
SetEntityVisible(ownedFakeAtmObject, false)
local netPedId = PedToNet(cache.ped)
local netFakeAtmEntity = ObjToNet(ownedFakeAtmObject)
TriggerServerEvent(_e('server:rope:AttachAtmRopeToPed'), netPedId, netFakeAtmEntity)
TriggerServerEvent(_e('server:RemoveItem'), Config.Rope.requiredItem.name)
onOwnedAnchorCreated()
addRobTargetToAtm()
end
function Rope.Clear()
if ownedFakeAtmObject then
TriggerServerEvent(_e('server:rope:DeletePlayerRope'))
end
deleteHookObject()
deleteFakeAtmEntity()
deletePlayerRopes()
ownedAnchorThread = nil
end
--[[ events ]]
RegisterNetEvent(_e('client:rope:AttachAtmRopeToPed'), function(netPedId, netFakeAtmEntity, owner)
if not Utils.WaitForEntityWithNetworkId(netPedId) then return end
if not Utils.WaitForEntityWithNetworkId(netFakeAtmEntity) then return end
local targetPedId = NetToPed(netPedId)
local targetAtmEntity = NetToObj(netFakeAtmEntity)
if not DoesEntityExist(targetPedId) then return end
if not DoesEntityExist(targetAtmEntity) then return end
ClearPedTasksImmediately(cache.ped)
Citizen.Wait(100)
local rope = addRopeToPlayer(owner, 'ped')
local targetAtmOffset = GetOffsetFromEntityInWorldCoords(targetAtmEntity, 0.0, 0.0, 1.0)
local pedBoneCoords = GetPedBoneCoords(targetPedId, 6286, 0.0, 0.0, 0.0)
attachRopeToObject(rope, targetAtmEntity, targetPedId, targetAtmOffset, pedBoneCoords)
Citizen.CreateThread(function()
while DoesPlayerRopeExist(owner, 'ped') and DoesEntityExist(targetAtmEntity) and DoesEntityExist(targetPedId) do
targetAtmOffset = GetOffsetFromEntityInWorldCoords(targetAtmEntity, 0.0, 0.0, 1.0)
pedBoneCoords = GetPedBoneCoords(targetPedId, 6286, 0.0, 0.0, 0.0)
DetachEntity(targetAtmEntity)
DetachEntity(targetPedId)
attachRopeToObject(rope, targetAtmEntity, targetPedId, targetAtmOffset, pedBoneCoords)
Citizen.Wait(64)
end
end)
end)
RegisterNetEvent(_e('client:rope:attachRopeWithVehicle'), function(netFakeAtmEntity, netAttachedVehicle, owner)
deletePlayerRope(owner)
if not Utils.WaitForEntityWithNetworkId(netFakeAtmEntity) then return end
if not Utils.WaitForEntityWithNetworkId(netAttachedVehicle) then return end
local targetAtmEntity = NetToObj(netFakeAtmEntity)
local targetVehicleEntity = NetToVeh(netAttachedVehicle)
if not DoesEntityExist(targetAtmEntity) then return end
if not DoesEntityExist(targetVehicleEntity) then return end
local targetAtmOffset = GetOffsetFromEntityInWorldCoords(targetAtmEntity, 0, 0.0, 1.0)
local targetVehicleOffset = GetOffsetFromEntityInWorldCoords(targetVehicleEntity, 0, -2.1, -.2)
local rope = addRopeToPlayer(owner, 'vehicle')
attachRopeToObject(rope,
targetAtmEntity, targetVehicleEntity,
targetAtmOffset, targetVehicleOffset)
end)
RegisterNetEvent(_e('client:rope:onAtmRipped'), function(coords, model, owner)
local nearByObjects = lib.getNearbyObjects(coords, 0.3)
for _, v in ipairs(nearByObjects) do
if GetEntityModel(v.object) == model and not Entity(v.object).state.isFakeAtm then
SetEntityAsMissionEntity(v.object, true, true)
DeleteEntity(v.object)
break
end
end
if owner == cache.serverId then
Utils.Notify(locale('sec_active', Config.Rope.breakTime), 'inform', 5000)
Citizen.SetTimeout(Config.Rope.breakTime * 1000, function()
Utils.Notify(locale('sec_deactive'), 'success', 5000)
Entity(ownedFakeAtmObject).state.robbable = true
end)
end
end)
RegisterNetEvent(_e('client:rope:DeletePlayerRope'), function(owner)
deletePlayerRope(owner)
end)