- rv-itemsonback v2.0: afișare props pe corp din inventar (medikit etc.) - Admin menu /itemsonback cu ox_lib (search items, adjust pos/rot, select bone) - Live preview cu auto-cleanup + /clearpreview emergency - Config persistent JSON (data/items.json) - Disable idle camera + idle animations (InvalidateIdleCam) - resources.cfg: safety net ensure qs-weaponsonback - fix(qs-inventory): Config.Genders[0]=Male pt QBCore compatibility
544 lines
22 KiB
Lua
544 lines
22 KiB
Lua
--[[
|
||
rv-itemsonback — Client
|
||
Afișează iteme din inventar ca props pe corpul jucătorului
|
||
+ Admin menu cu ox_lib pentru configurare
|
||
]]
|
||
|
||
local QBCore = exports['qb-core']:GetCoreObject()
|
||
local attachedProps = {}
|
||
local itemConfigs = {}
|
||
local previewProp = nil
|
||
local editingItem = nil
|
||
local isEditing = false
|
||
|
||
-----------------------------------------
|
||
-- Verifică dacă playerul are un item
|
||
-----------------------------------------
|
||
local function HasItem(itemName)
|
||
local PlayerData = QBCore.Functions.GetPlayerData()
|
||
if not PlayerData or not PlayerData.items then return false end
|
||
for _, item in pairs(PlayerData.items) do
|
||
if item and item.name == itemName and item.amount and item.amount > 0 then
|
||
return true
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- Atașează prop pe jucător
|
||
-----------------------------------------
|
||
local function AttachProp(itemName, config)
|
||
if attachedProps[itemName] then return end
|
||
|
||
local ped = PlayerPedId()
|
||
local modelHash = GetHashKey(config.model)
|
||
|
||
RequestModel(modelHash)
|
||
local timeout = 0
|
||
while not HasModelLoaded(modelHash) and timeout < 50 do
|
||
Wait(100)
|
||
timeout = timeout + 1
|
||
end
|
||
if not HasModelLoaded(modelHash) then return end
|
||
|
||
local boneIndex = GetPedBoneIndex(ped, config.bone)
|
||
local prop = CreateObject(modelHash, 0.0, 0.0, 0.0, true, true, false)
|
||
|
||
AttachEntityToEntity(prop, ped, boneIndex,
|
||
config.pos.x, config.pos.y, config.pos.z,
|
||
config.rot.x, config.rot.y, config.rot.z,
|
||
true, true, false, true, 1, true)
|
||
|
||
SetModelAsNoLongerNeeded(modelHash)
|
||
attachedProps[itemName] = prop
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- Detașează prop
|
||
-----------------------------------------
|
||
local function DetachProp(itemName)
|
||
if attachedProps[itemName] then
|
||
if DoesEntityExist(attachedProps[itemName]) then
|
||
DeleteEntity(attachedProps[itemName])
|
||
end
|
||
attachedProps[itemName] = nil
|
||
end
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- Detașează TOATE propurile
|
||
-----------------------------------------
|
||
local function DetachAll()
|
||
for itemName, _ in pairs(attachedProps) do
|
||
DetachProp(itemName)
|
||
end
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- Preview prop (pentru admin editing)
|
||
-----------------------------------------
|
||
local function ShowPreview(config)
|
||
ClearPreview()
|
||
|
||
local ped = PlayerPedId()
|
||
local modelHash = GetHashKey(config.model)
|
||
|
||
RequestModel(modelHash)
|
||
local timeout = 0
|
||
while not HasModelLoaded(modelHash) and timeout < 50 do
|
||
Wait(100)
|
||
timeout = timeout + 1
|
||
end
|
||
if not HasModelLoaded(modelHash) then return end
|
||
|
||
local boneIndex = GetPedBoneIndex(ped, config.bone)
|
||
previewProp = CreateObject(modelHash, 0.0, 0.0, 0.0, true, true, false)
|
||
|
||
AttachEntityToEntity(previewProp, ped, boneIndex,
|
||
config.pos.x, config.pos.y, config.pos.z,
|
||
config.rot.x, config.rot.y, config.rot.z,
|
||
true, true, false, true, 1, true)
|
||
|
||
-- Efect vizual: ușor transparent pentru a indica modul preview
|
||
SetEntityAlpha(previewProp, 200, false)
|
||
SetModelAsNoLongerNeeded(modelHash)
|
||
end
|
||
|
||
function ClearPreview()
|
||
if previewProp and DoesEntityExist(previewProp) then
|
||
DeleteEntity(previewProp)
|
||
end
|
||
previewProp = nil
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- Rebuild configs din tabel
|
||
-----------------------------------------
|
||
local function BuildItemConfigs()
|
||
local configs = {}
|
||
for _, data in ipairs(itemConfigs) do
|
||
configs[data.item] = {
|
||
model = data.model,
|
||
bone = data.bone,
|
||
pos = vector3(data.pos.x, data.pos.y, data.pos.z),
|
||
rot = vector3(data.rot.x, data.rot.y, data.rot.z),
|
||
}
|
||
end
|
||
return configs
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- Sync config de la server
|
||
-----------------------------------------
|
||
RegisterNetEvent('rv-itemsonback:syncConfig', function(configs)
|
||
itemConfigs = configs
|
||
-- Reattach cu config-urile noi
|
||
DetachAll()
|
||
end)
|
||
|
||
-----------------------------------------
|
||
-- ADMIN MENU: Main
|
||
-----------------------------------------
|
||
local function OpenMainMenu()
|
||
local options = {}
|
||
|
||
-- Lista itemelor configurate
|
||
for _, data in ipairs(itemConfigs) do
|
||
options[#options + 1] = {
|
||
title = '📦 ' .. data.item,
|
||
description = 'Prop: ' .. data.model,
|
||
icon = 'cube',
|
||
arrow = true,
|
||
onSelect = function()
|
||
editingItem = data
|
||
OpenEditMenu(data)
|
||
end
|
||
}
|
||
end
|
||
|
||
-- Adaugă item nou
|
||
options[#options + 1] = {
|
||
title = '➕ Adaugă Item Nou',
|
||
description = 'Configurează un item nou pe corp',
|
||
icon = 'plus',
|
||
onSelect = function()
|
||
OpenAddMenu()
|
||
end
|
||
}
|
||
|
||
lib.registerContext({
|
||
id = 'rv_itemsonback_main',
|
||
title = '🎒 Items on Back — Admin',
|
||
options = options
|
||
})
|
||
|
||
lib.showContext('rv_itemsonback_main')
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- ADMIN MENU: Add New Item
|
||
-----------------------------------------
|
||
function OpenAddMenu()
|
||
-- Step 1: Item name
|
||
local items = QBCore.Shared.Items
|
||
local itemOptions = {}
|
||
for k, v in pairs(items) do
|
||
itemOptions[#itemOptions + 1] = { value = k, label = v.label .. ' (' .. k .. ')' }
|
||
end
|
||
|
||
-- Sortează alfabetic
|
||
table.sort(itemOptions, function(a, b) return a.label < b.label end)
|
||
|
||
local input = lib.inputDialog('Adaugă Item Nou', {
|
||
{ type = 'select', label = 'Item', description = 'Selectează itemul din inventar', options = itemOptions, required = true, searchable = true },
|
||
{ type = 'input', label = 'Prop Model', description = 'Numele propului GTA (ex: prop_ld_health_pack)', required = true, default = 'prop_ld_health_pack' },
|
||
{ type = 'select', label = 'Locație (Bone)', description = 'Unde pe corp', options = Config.Bones, required = true },
|
||
})
|
||
|
||
if not input then return OpenMainMenu() end
|
||
|
||
local newData = {
|
||
item = input[1],
|
||
model = input[2],
|
||
bone = input[3],
|
||
pos = { x = 0.0, y = -0.1, z = 0.0 },
|
||
rot = { x = 0.0, y = 0.0, z = 0.0 }
|
||
}
|
||
|
||
-- Preview
|
||
ShowPreview({
|
||
model = newData.model,
|
||
bone = newData.bone,
|
||
pos = vector3(newData.pos.x, newData.pos.y, newData.pos.z),
|
||
rot = vector3(newData.rot.x, newData.rot.y, newData.rot.z),
|
||
})
|
||
|
||
editingItem = newData
|
||
OpenEditMenu(newData)
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- ADMIN MENU: Edit Item
|
||
-----------------------------------------
|
||
function OpenEditMenu(data)
|
||
isEditing = true
|
||
|
||
-- Arată preview
|
||
ShowPreview({
|
||
model = data.model,
|
||
bone = data.bone,
|
||
pos = vector3(data.pos.x, data.pos.y, data.pos.z),
|
||
rot = vector3(data.rot.x, data.rot.y, data.rot.z),
|
||
})
|
||
|
||
-- Găsește numele bone-ului
|
||
local boneName = 'Unknown'
|
||
for _, b in ipairs(Config.Bones) do
|
||
if b.value == data.bone then
|
||
boneName = b.label
|
||
break
|
||
end
|
||
end
|
||
|
||
lib.registerContext({
|
||
id = 'rv_itemsonback_edit',
|
||
title = '✏️ Edit: ' .. data.item,
|
||
menu = 'rv_itemsonback_main',
|
||
options = {
|
||
{
|
||
title = '📍 Poziție: X=' .. string.format('%.2f', data.pos.x) .. ' Y=' .. string.format('%.2f', data.pos.y) .. ' Z=' .. string.format('%.2f', data.pos.z),
|
||
description = 'Ajustează poziția propului',
|
||
icon = 'arrows-alt',
|
||
arrow = true,
|
||
onSelect = function()
|
||
OpenPositionMenu(data)
|
||
end
|
||
},
|
||
{
|
||
title = '🔄 Rotație: X=' .. string.format('%.0f', data.rot.x) .. ' Y=' .. string.format('%.0f', data.rot.y) .. ' Z=' .. string.format('%.0f', data.rot.z),
|
||
description = 'Ajustează rotația propului',
|
||
icon = 'sync-alt',
|
||
arrow = true,
|
||
onSelect = function()
|
||
OpenRotationMenu(data)
|
||
end
|
||
},
|
||
{
|
||
title = '🦴 Bone: ' .. boneName,
|
||
description = 'Schimbă locația pe corp',
|
||
icon = 'bone',
|
||
arrow = true,
|
||
onSelect = function()
|
||
OpenBoneMenu(data)
|
||
end
|
||
},
|
||
{
|
||
title = '🔧 Schimbă Prop Model',
|
||
description = 'Model curent: ' .. data.model,
|
||
icon = 'cube',
|
||
onSelect = function()
|
||
local input = lib.inputDialog('Schimbă Prop Model', {
|
||
{ type = 'input', label = 'Prop Model', default = data.model, required = true }
|
||
})
|
||
if input then
|
||
data.model = input[1]
|
||
OpenEditMenu(data)
|
||
else
|
||
OpenEditMenu(data)
|
||
end
|
||
end
|
||
},
|
||
{
|
||
title = '💾 Salvează',
|
||
description = 'Salvează configurația',
|
||
icon = 'save',
|
||
onSelect = function()
|
||
ClearPreview()
|
||
local success = lib.callback.await('rv-itemsonback:saveItem', false, data)
|
||
if success then
|
||
lib.notify({ title = 'Salvat!', description = data.item .. ' configurat cu succes', type = 'success' })
|
||
else
|
||
lib.notify({ title = 'Eroare', description = 'Nu ai permisiune', type = 'error' })
|
||
end
|
||
end
|
||
},
|
||
{
|
||
title = '🗑️ Șterge',
|
||
description = 'Șterge acest item din configurare',
|
||
icon = 'trash',
|
||
onSelect = function()
|
||
ClearPreview()
|
||
local confirm = lib.alertDialog({
|
||
header = 'Confirmare ștergere',
|
||
content = 'Sigur vrei să ștergi **' .. data.item .. '**?',
|
||
centered = true,
|
||
cancel = true
|
||
})
|
||
if confirm == 'confirm' then
|
||
lib.callback.await('rv-itemsonback:deleteItem', false, data.item)
|
||
lib.notify({ title = 'Șters!', description = data.item .. ' eliminat', type = 'success' })
|
||
OpenMainMenu()
|
||
else
|
||
OpenEditMenu(data)
|
||
end
|
||
end
|
||
},
|
||
}
|
||
})
|
||
|
||
lib.showContext('rv_itemsonback_edit')
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- ADMIN MENU: Position Adjustment
|
||
-----------------------------------------
|
||
function OpenPositionMenu(data)
|
||
local step = Config.PosStep
|
||
local bigStep = Config.PosStepBig
|
||
|
||
lib.registerContext({
|
||
id = 'rv_itemsonback_pos',
|
||
title = '📍 Poziție: ' .. string.format('X=%.2f Y=%.2f Z=%.2f', data.pos.x, data.pos.y, data.pos.z),
|
||
menu = 'rv_itemsonback_edit',
|
||
options = {
|
||
-- X axis
|
||
{ title = '➡️ X +' .. step, icon = 'arrow-right', onSelect = function() data.pos.x = data.pos.x + step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenPositionMenu(data) end },
|
||
{ title = '⬅️ X -' .. step, icon = 'arrow-left', onSelect = function() data.pos.x = data.pos.x - step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenPositionMenu(data) end },
|
||
-- Y axis
|
||
{ title = '⬆️ Y +' .. step, icon = 'arrow-up', onSelect = function() data.pos.y = data.pos.y + step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenPositionMenu(data) end },
|
||
{ title = '⬇️ Y -' .. step, icon = 'arrow-down', onSelect = function() data.pos.y = data.pos.y - step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenPositionMenu(data) end },
|
||
-- Z axis
|
||
{ title = '🔼 Z +' .. step, icon = 'chevron-up', onSelect = function() data.pos.z = data.pos.z + step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenPositionMenu(data) end },
|
||
{ title = '🔽 Z -' .. step, icon = 'chevron-down', onSelect = function() data.pos.z = data.pos.z - step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenPositionMenu(data) end },
|
||
-- Big steps
|
||
{ title = '⏩ X +' .. bigStep .. ' (mare)', icon = 'fast-forward', onSelect = function() data.pos.x = data.pos.x + bigStep; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenPositionMenu(data) end },
|
||
{ title = '⏪ X -' .. bigStep .. ' (mare)', icon = 'fast-backward', onSelect = function() data.pos.x = data.pos.x - bigStep; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenPositionMenu(data) end },
|
||
-- Manual input
|
||
{
|
||
title = '✏️ Input Manual',
|
||
description = 'Introdu valori exacte',
|
||
icon = 'keyboard',
|
||
onSelect = function()
|
||
local input = lib.inputDialog('Poziție Manuală', {
|
||
{ type = 'number', label = 'X', default = data.pos.x, step = 0.01 },
|
||
{ type = 'number', label = 'Y', default = data.pos.y, step = 0.01 },
|
||
{ type = 'number', label = 'Z', default = data.pos.z, step = 0.01 },
|
||
})
|
||
if input then
|
||
data.pos.x = input[1] or data.pos.x
|
||
data.pos.y = input[2] or data.pos.y
|
||
data.pos.z = input[3] or data.pos.z
|
||
ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) })
|
||
end
|
||
OpenPositionMenu(data)
|
||
end
|
||
},
|
||
}
|
||
})
|
||
|
||
lib.showContext('rv_itemsonback_pos')
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- ADMIN MENU: Rotation Adjustment
|
||
-----------------------------------------
|
||
function OpenRotationMenu(data)
|
||
local step = Config.RotStep
|
||
local bigStep = Config.RotStepBig
|
||
|
||
lib.registerContext({
|
||
id = 'rv_itemsonback_rot',
|
||
title = '🔄 Rotație: ' .. string.format('X=%.0f Y=%.0f Z=%.0f', data.rot.x, data.rot.y, data.rot.z),
|
||
menu = 'rv_itemsonback_edit',
|
||
options = {
|
||
{ title = '🔄 RotX +' .. step, icon = 'redo', onSelect = function() data.rot.x = data.rot.x + step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenRotationMenu(data) end },
|
||
{ title = '🔄 RotX -' .. step, icon = 'undo', onSelect = function() data.rot.x = data.rot.x - step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenRotationMenu(data) end },
|
||
{ title = '🔄 RotY +' .. step, icon = 'redo', onSelect = function() data.rot.y = data.rot.y + step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenRotationMenu(data) end },
|
||
{ title = '🔄 RotY -' .. step, icon = 'undo', onSelect = function() data.rot.y = data.rot.y - step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenRotationMenu(data) end },
|
||
{ title = '🔄 RotZ +' .. step, icon = 'redo', onSelect = function() data.rot.z = data.rot.z + step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenRotationMenu(data) end },
|
||
{ title = '🔄 RotZ -' .. step, icon = 'undo', onSelect = function() data.rot.z = data.rot.z - step; ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) }); OpenRotationMenu(data) end },
|
||
{
|
||
title = '✏️ Input Manual',
|
||
icon = 'keyboard',
|
||
onSelect = function()
|
||
local input = lib.inputDialog('Rotație Manuală', {
|
||
{ type = 'number', label = 'Rot X', default = data.rot.x, step = 1 },
|
||
{ type = 'number', label = 'Rot Y', default = data.rot.y, step = 1 },
|
||
{ type = 'number', label = 'Rot Z', default = data.rot.z, step = 1 },
|
||
})
|
||
if input then
|
||
data.rot.x = input[1] or data.rot.x
|
||
data.rot.y = input[2] or data.rot.y
|
||
data.rot.z = input[3] or data.rot.z
|
||
ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) })
|
||
end
|
||
OpenRotationMenu(data)
|
||
end
|
||
},
|
||
}
|
||
})
|
||
|
||
lib.showContext('rv_itemsonback_rot')
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- ADMIN MENU: Bone Selection
|
||
-----------------------------------------
|
||
function OpenBoneMenu(data)
|
||
local options = {}
|
||
for _, bone in ipairs(Config.Bones) do
|
||
options[#options + 1] = {
|
||
title = bone.label,
|
||
icon = 'bone',
|
||
onSelect = function()
|
||
data.bone = bone.value
|
||
ShowPreview({ model = data.model, bone = data.bone, pos = vector3(data.pos.x, data.pos.y, data.pos.z), rot = vector3(data.rot.x, data.rot.y, data.rot.z) })
|
||
OpenEditMenu(data)
|
||
end
|
||
}
|
||
end
|
||
|
||
lib.registerContext({
|
||
id = 'rv_itemsonback_bone',
|
||
title = '🦴 Selectează Bone',
|
||
menu = 'rv_itemsonback_edit',
|
||
options = options
|
||
})
|
||
|
||
lib.showContext('rv_itemsonback_bone')
|
||
end
|
||
|
||
-----------------------------------------
|
||
-- Event: deschide meniul admin
|
||
-----------------------------------------
|
||
RegisterNetEvent('rv-itemsonback:openMenu', function()
|
||
OpenMainMenu()
|
||
end)
|
||
|
||
-----------------------------------------
|
||
-- Cleanup preview la închiderea meniului
|
||
-----------------------------------------
|
||
AddEventHandler('ox_lib:onCloseContext', function(context)
|
||
if not context then return end
|
||
if string.find(context, 'rv_itemsonback') then
|
||
ClearPreview()
|
||
isEditing = false
|
||
end
|
||
end)
|
||
|
||
-- Safety: curăță preview dacă a rămas blocat
|
||
CreateThread(function()
|
||
while true do
|
||
Wait(3000)
|
||
if previewProp and not isEditing then
|
||
ClearPreview()
|
||
end
|
||
end
|
||
end)
|
||
|
||
-- Comandă emergency cleanup
|
||
RegisterCommand('clearpreview', function()
|
||
ClearPreview()
|
||
isEditing = false
|
||
lib.notify({ title = 'Preview curățat', type = 'success' })
|
||
end, false)
|
||
|
||
-----------------------------------------
|
||
-- LOOP PRINCIPAL: atașare props din inventar
|
||
-----------------------------------------
|
||
CreateThread(function()
|
||
-- Așteaptă config de la server (retry dacă serverul nu e gata)
|
||
while #itemConfigs == 0 do
|
||
Wait(2000)
|
||
local ok, result = pcall(lib.callback.await, 'rv-itemsonback:getConfig', false)
|
||
if ok and result then
|
||
itemConfigs = result
|
||
end
|
||
end
|
||
|
||
while true do
|
||
Wait(Config.CheckInterval)
|
||
local ped = PlayerPedId()
|
||
local configs = BuildItemConfigs()
|
||
|
||
for itemName, config in pairs(configs) do
|
||
local hasIt = HasItem(itemName)
|
||
local isDead = IsEntityDead(ped)
|
||
local inVehicle = IsPedInAnyVehicle(ped, false)
|
||
|
||
if hasIt and not isDead and not inVehicle then
|
||
AttachProp(itemName, config)
|
||
else
|
||
DetachProp(itemName)
|
||
end
|
||
end
|
||
end
|
||
end)
|
||
|
||
-----------------------------------------
|
||
-- Cleanup la resource stop
|
||
-----------------------------------------
|
||
AddEventHandler('onResourceStop', function(resourceName)
|
||
if GetCurrentResourceName() ~= resourceName then return end
|
||
DetachAll()
|
||
ClearPreview()
|
||
end)
|
||
|
||
-----------------------------------------
|
||
-- Disable idle animations + idle camera
|
||
-----------------------------------------
|
||
CreateThread(function()
|
||
while true do
|
||
Wait(500)
|
||
local ped = PlayerPedId()
|
||
if DoesEntityExist(ped) then
|
||
SetPedCanPlayAmbientAnims(ped, false)
|
||
SetPedCanPlayAmbientBaseAnims(ped, false)
|
||
SetPedCanPlayGestureAnims(ped, false)
|
||
InvalidateIdleCam()
|
||
N_0xf4f2c0d4ee209e20() -- DisableIdleCamera
|
||
end
|
||
end
|
||
end)
|