1
0
Fork 0
forked from Simnation/Main
Main/resources/[inventory]/nordi_petbowl/client.lua

333 lines
10 KiB
Lua
Raw Permalink Normal View History

2025-08-02 13:24:19 +02:00
local QBCore = exports['qb-core']:GetCoreObject()
local placedBowls = {}
-- Load placed bowls from server
RegisterNetEvent('pet-bowls:client:loadBowls', function(bowls)
2025-08-02 14:02:20 +02:00
print("^2[Pet-Bowls]^7 Loading " .. #bowls .. " bowls from server")
for bowlId, bowl in pairs(bowls) do
2025-08-02 13:24:19 +02:00
local coords = json.decode(bowl.coords)
local bowlCoords = vector3(coords.x, coords.y, coords.z)
2025-08-02 14:02:20 +02:00
-- Find the closest object to these coordinates
local closestObject = nil
local closestDistance = 2.0 -- Maximum distance to consider
local objects = GetGamePool('CObject')
for _, object in pairs(objects) do
if DoesEntityExist(object) then
local objectCoords = GetEntityCoords(object)
local distance = #(objectCoords - bowlCoords)
2025-08-02 13:51:31 +02:00
2025-08-02 14:02:20 +02:00
if distance < closestDistance then
local model = GetEntityModel(object)
-- Check if this is a valid bowl model
for _, bowlConfig in pairs(Config.BowlProps) do
if GetHashKey(bowlConfig.model) == model then
closestObject = object
closestDistance = distance
break
end
end
end
2025-08-02 13:51:31 +02:00
end
2025-08-02 13:24:19 +02:00
end
2025-08-02 14:02:20 +02:00
if closestObject then
-- Store in local table
placedBowls[bowlId] = {
object = closestObject,
id = bowlId,
model = bowl.model,
type = bowl.type,
fillLevel = bowl.fill_level
}
-- Add target
AddTargetToBowl(closestObject, bowlId, bowl.type)
print("^2[Pet-Bowls]^7 Added target to bowl: " .. bowlId)
else
print("^3[Pet-Bowls]^7 Could not find object for bowl: " .. bowlId)
end
2025-08-02 13:24:19 +02:00
end
end)
-- Function to add qb-target to a bowl
function AddTargetToBowl(bowlObject, bowlId, bowlType)
2025-08-02 14:02:20 +02:00
if not DoesEntityExist(bowlObject) then
print("^1[Pet-Bowls]^7 Cannot add target to non-existent object")
return
end
-- Debug info
print("^2[Pet-Bowls]^7 Adding target to object: " .. bowlObject .. " with ID: " .. bowlId)
-- Add target with explicit options
2025-08-02 13:24:19 +02:00
exports['qb-target']:AddTargetEntity(bowlObject, {
options = {
{
type = "client",
2025-08-02 14:02:20 +02:00
event = "pet-bowls:client:useBowl",
2025-08-02 13:24:19 +02:00
icon = "fas fa-hand",
label = "Use Bowl",
2025-08-02 14:02:20 +02:00
bowlId = bowlId,
bowlType = bowlType
2025-08-02 13:24:19 +02:00
},
{
type = "client",
2025-08-02 14:02:20 +02:00
event = "pet-bowls:client:openFillMenu",
2025-08-02 13:24:19 +02:00
icon = "fas fa-fill",
label = "Fill Bowl",
2025-08-02 14:02:20 +02:00
bowlId = bowlId,
bowlType = bowlType
2025-08-02 13:24:19 +02:00
}
},
distance = 2.0
})
end
2025-08-02 14:02:20 +02:00
-- Event handlers for target interactions
RegisterNetEvent('pet-bowls:client:useBowl', function(data)
UseBowl(data.bowlId, data.bowlType)
end)
RegisterNetEvent('pet-bowls:client:openFillMenu', function(data)
OpenFillMenu(data.bowlId, data.bowlType)
end)
2025-08-02 13:24:19 +02:00
-- Function to use a bowl
function UseBowl(bowlId, bowlType)
local bowl = placedBowls[bowlId]
2025-08-02 14:02:20 +02:00
if not bowl then
print("^1[Pet-Bowls]^7 Bowl not found: " .. bowlId)
return
end
2025-08-02 13:24:19 +02:00
-- Check if bowl has content
if bowl.fillLevel <= 0 then
lib.notify(Config.Notifications.bowlEmpty)
return
end
-- Set animation and progress bar based on bowl type
local progressConfig = bowlType == 'food' and Config.ProgressBar.eating or Config.ProgressBar.drinking
-- Start progress bar
if lib.progressBar(progressConfig) then
-- Consume from bowl
TriggerServerEvent('pet-bowls:server:consumeBowl', bowlId)
end
end
-- Function to open fill menu
function OpenFillMenu(bowlId, bowlType)
local bowl = placedBowls[bowlId]
if not bowl then return end
-- Get fill items for this bowl type
local fillItems = Config.FillItems[bowlType]
local options = {}
for _, item in pairs(fillItems) do
table.insert(options, {
title = item.label,
description = 'Fill Amount: ' .. item.fillAmount .. '%',
onSelect = function()
FillBowl(bowlId, item.item, item.fillAmount)
end
})
end
lib.registerContext({
id = 'bowl_fill_menu',
title = 'Fill ' .. (bowlType == 'food' and 'Food' or 'Water') .. ' Bowl (' .. bowl.fillLevel .. '%)',
options = options
})
lib.showContext('bowl_fill_menu')
end
-- Function to fill a bowl
function FillBowl(bowlId, itemName, fillAmount)
-- Start progress bar
if lib.progressBar(Config.ProgressBar.filling) then
-- Fill the bowl
TriggerServerEvent('pet-bowls:server:fillBowl', bowlId, itemName, fillAmount)
end
end
2025-08-02 13:51:31 +02:00
-- Update bowl fill level
RegisterNetEvent('pet-bowls:client:updateBowlLevel', function(bowlId, newLevel)
if placedBowls[bowlId] then
placedBowls[bowlId].fillLevel = newLevel
2025-08-02 13:24:19 +02:00
end
end)
2025-08-02 14:02:20 +02:00
-- Register a new bowl (for props placed with ProPlacer)
RegisterNetEvent('pet-bowls:client:registerNewBowl', function(modelName, bowlType)
2025-08-02 14:43:29 +02:00
-- Check if we received parameters directly or as part of a data table
local model, type
-- Handle both direct parameters and data table format
if type(modelName) == "table" and modelName.modelName then
-- We received a data table from qb-target
model = modelName.modelName
type = modelName.bowlType
else
-- We received direct parameters
model = modelName
type = bowlType
end
-- Ensure we have valid parameters
if not model or not type then
print("^1[Pet-Bowls]^7 Missing model or type for bowl registration")
return
end
2025-08-02 14:02:20 +02:00
-- Find the closest valid prop
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
2025-08-02 13:51:31 +02:00
2025-08-02 14:02:20 +02:00
local closestObject = nil
local closestDistance = 3.0 -- Maximum distance to consider
2025-08-02 14:43:29 +02:00
local validModel = GetHashKey(model)
2025-08-02 13:51:31 +02:00
2025-08-02 14:02:20 +02:00
local objects = GetGamePool('CObject')
for _, object in pairs(objects) do
if DoesEntityExist(object) and GetEntityModel(object) == validModel then
local objectCoords = GetEntityCoords(object)
local distance = #(objectCoords - playerCoords)
if distance < closestDistance then
closestObject = object
closestDistance = distance
end
2025-08-02 13:51:31 +02:00
end
2025-08-02 13:24:19 +02:00
end
2025-08-02 14:02:20 +02:00
if closestObject then
-- Generate a unique ID for this bowl
local bowlId = 'bowl_' .. math.random(100000, 999999) .. '_' .. GetGameTimer()
-- Save to server
local coords = GetEntityCoords(closestObject)
local heading = GetEntityHeading(closestObject)
2025-08-02 14:43:29 +02:00
TriggerServerEvent('pet-bowls:server:placeBowl', bowlId, model, type, {
2025-08-02 14:02:20 +02:00
x = coords.x,
y = coords.y,
z = coords.z,
w = heading
})
-- Store locally
placedBowls[bowlId] = {
object = closestObject,
id = bowlId,
2025-08-02 14:43:29 +02:00
model = model,
type = type,
2025-08-02 14:02:20 +02:00
fillLevel = 0
}
-- Add target
2025-08-02 14:43:29 +02:00
AddTargetToBowl(closestObject, bowlId, type)
2025-08-02 14:02:20 +02:00
lib.notify(Config.Notifications.bowlPlaced)
else
lib.notify({
title = 'Bowl System',
description = 'No valid bowl prop found nearby!',
type = 'error'
})
end
end)
-- Command to register a bowl
RegisterCommand('registerbowl', function()
OpenRegisterBowlMenu()
end, false)
-- Function to open register bowl menu
function OpenRegisterBowlMenu()
local options = {}
2025-08-02 13:24:19 +02:00
2025-08-02 14:02:20 +02:00
for _, bowl in pairs(Config.BowlProps) do
table.insert(options, {
title = bowl.label,
description = 'Type: ' .. (bowl.type == 'food' and 'Food Bowl' or 'Water Bowl'),
onSelect = function()
TriggerEvent('pet-bowls:client:registerNewBowl', bowl.model, bowl.type)
end
})
end
2025-08-02 13:51:31 +02:00
2025-08-02 14:02:20 +02:00
lib.registerContext({
id = 'register_bowl_menu',
title = 'Register Bowl',
options = options
2025-08-02 13:24:19 +02:00
})
2025-08-02 14:02:20 +02:00
lib.showContext('register_bowl_menu')
end
2025-08-02 13:24:19 +02:00
-- Initialize
Citizen.CreateThread(function()
2025-08-02 14:02:20 +02:00
-- Wait for world to load
Citizen.Wait(2000)
2025-08-02 13:24:19 +02:00
-- Request all placed bowls from server
TriggerServerEvent('pet-bowls:server:requestBowls')
2025-08-02 13:51:31 +02:00
2025-08-02 14:02:20 +02:00
-- Add target to all valid bowl props in the world that aren't registered yet
Citizen.Wait(5000) -- Wait for bowls to load
2025-08-02 13:51:31 +02:00
local validModels = {}
for _, bowlConfig in pairs(Config.BowlProps) do
2025-08-02 14:02:20 +02:00
validModels[GetHashKey(bowlConfig.model)] = bowlConfig
2025-08-02 13:51:31 +02:00
end
local objects = GetGamePool('CObject')
2025-08-02 14:02:20 +02:00
local addedTargets = 0
2025-08-02 13:51:31 +02:00
for _, object in pairs(objects) do
2025-08-02 14:02:20 +02:00
if DoesEntityExist(object) then
local model = GetEntityModel(object)
2025-08-02 13:51:31 +02:00
2025-08-02 14:02:20 +02:00
if validModels[model] then
-- Check if this object is already registered as a bowl
local isRegistered = false
for _, bowl in pairs(placedBowls) do
if bowl.object == object then
isRegistered = true
break
end
end
if not isRegistered then
-- Add a register option to this unregistered bowl prop
local bowlConfig = validModels[model]
exports['qb-target']:AddTargetEntity(object, {
options = {
{
type = "client",
event = "pet-bowls:client:registerNewBowl",
icon = "fas fa-plus",
label = "Register as " .. bowlConfig.label,
modelName = bowlConfig.model,
bowlType = bowlConfig.type
}
},
distance = 2.0
})
addedTargets = addedTargets + 1
end
2025-08-02 13:51:31 +02:00
end
end
end
2025-08-02 14:02:20 +02:00
print("^2[Pet-Bowls]^7 Added registration targets to " .. addedTargets .. " unregistered bowl props")
end)