forked from Simnation/Main
226 lines
7 KiB
Lua
226 lines
7 KiB
Lua
local QBCore = exports['qb-core']:GetCoreObject()
|
|
local placedBowls = {}
|
|
local currentBowl = nil
|
|
|
|
-- Load placed bowls from server
|
|
RegisterNetEvent('pet-bowls:client:loadBowls', function(bowls)
|
|
for _, bowl in pairs(bowls) do
|
|
local coords = json.decode(bowl.coords)
|
|
local bowlCoords = vector3(coords.x, coords.y, coords.z)
|
|
|
|
-- Add target to existing bowl objects
|
|
local bowlObjects = GetGamePool('CObject')
|
|
for _, object in pairs(bowlObjects) do
|
|
local objectCoords = GetEntityCoords(object)
|
|
local distance = #(objectCoords - bowlCoords)
|
|
|
|
if distance < 0.5 and GetEntityModel(object) == GetHashKey(bowl.model) then
|
|
-- Found the bowl object
|
|
placedBowls[bowl.bowl_id] = {
|
|
object = object,
|
|
id = bowl.bowl_id,
|
|
model = bowl.model,
|
|
type = bowl.type,
|
|
fillLevel = bowl.fill_level
|
|
}
|
|
|
|
-- Add target
|
|
AddTargetToBowl(object, bowl.bowl_id, bowl.type)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- Function to add qb-target to a bowl
|
|
function AddTargetToBowl(bowlObject, bowlId, bowlType)
|
|
exports['qb-target']:AddTargetEntity(bowlObject, {
|
|
options = {
|
|
{
|
|
type = "client",
|
|
icon = "fas fa-hand",
|
|
label = "Use Bowl",
|
|
action = function()
|
|
UseBowl(bowlId, bowlType)
|
|
end,
|
|
canInteract = function()
|
|
return true
|
|
end,
|
|
},
|
|
{
|
|
type = "client",
|
|
icon = "fas fa-fill",
|
|
label = "Fill Bowl",
|
|
action = function()
|
|
OpenFillMenu(bowlId, bowlType)
|
|
end,
|
|
canInteract = function()
|
|
return true
|
|
end,
|
|
}
|
|
},
|
|
distance = 2.0
|
|
})
|
|
end
|
|
|
|
-- Function to use a bowl
|
|
function UseBowl(bowlId, bowlType)
|
|
local bowl = placedBowls[bowlId]
|
|
if not bowl then return end
|
|
|
|
-- 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
|
|
|
|
-- Update bowl fill level
|
|
RegisterNetEvent('pet-bowls:client:updateBowlLevel', function(bowlId, newLevel)
|
|
if placedBowls[bowlId] then
|
|
placedBowls[bowlId].fillLevel = newLevel
|
|
end
|
|
end)
|
|
|
|
-- Register a new bowl (called from ProPlacer)
|
|
RegisterNetEvent('pet-bowls:client:registerBowl', function(objectNetId, bowlType)
|
|
local bowlObject = NetworkGetEntityFromNetworkId(objectNetId)
|
|
if not DoesEntityExist(bowlObject) then return end
|
|
|
|
local model = GetEntityModel(bowlObject)
|
|
local modelName = nil
|
|
|
|
-- Find the model name from the hash
|
|
for _, bowlConfig in pairs(Config.BowlProps) do
|
|
if GetHashKey(bowlConfig.model) == model then
|
|
modelName = bowlConfig.model
|
|
break
|
|
end
|
|
end
|
|
|
|
if not modelName then return end
|
|
|
|
-- Generate a unique ID for this bowl
|
|
local bowlId = 'bowl_' .. math.random(100000, 999999) .. '_' .. GetGameTimer()
|
|
|
|
-- Save to server
|
|
local coords = GetEntityCoords(bowlObject)
|
|
local heading = GetEntityHeading(bowlObject)
|
|
|
|
TriggerServerEvent('pet-bowls:server:placeBowl', bowlId, modelName, bowlType, {
|
|
x = coords.x,
|
|
y = coords.y,
|
|
z = coords.z,
|
|
w = heading
|
|
})
|
|
|
|
-- Store locally
|
|
placedBowls[bowlId] = {
|
|
object = bowlObject,
|
|
id = bowlId,
|
|
model = modelName,
|
|
type = bowlType,
|
|
fillLevel = 0
|
|
}
|
|
|
|
-- Add target
|
|
AddTargetToBowl(bowlObject, bowlId, bowlType)
|
|
|
|
lib.notify(Config.Notifications.bowlPlaced)
|
|
end)
|
|
|
|
-- Initialize
|
|
Citizen.CreateThread(function()
|
|
-- Request all placed bowls from server
|
|
TriggerServerEvent('pet-bowls:server:requestBowls')
|
|
|
|
-- Add target to all valid bowl props in the world
|
|
Citizen.Wait(2000) -- Wait for world to load
|
|
|
|
local validModels = {}
|
|
for _, bowlConfig in pairs(Config.BowlProps) do
|
|
validModels[GetHashKey(bowlConfig.model)] = bowlConfig.type
|
|
end
|
|
|
|
local objects = GetGamePool('CObject')
|
|
for _, object in pairs(objects) do
|
|
local model = GetEntityModel(object)
|
|
if validModels[model] then
|
|
-- This is a valid bowl model, check if it's already registered
|
|
local isRegistered = false
|
|
for id, bowl in pairs(placedBowls) do
|
|
if bowl.object == object then
|
|
isRegistered = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if not isRegistered then
|
|
-- This bowl isn't registered yet, add interaction without database entry
|
|
exports['qb-target']:AddTargetEntity(object, {
|
|
options = {
|
|
{
|
|
type = "client",
|
|
icon = "fas fa-plus",
|
|
label = "Register as Bowl",
|
|
action = function()
|
|
local bowlType = validModels[model]
|
|
TriggerEvent('pet-bowls:client:registerBowl', NetworkGetNetworkIdFromEntity(object), bowlType)
|
|
end,
|
|
canInteract = function()
|
|
return true
|
|
end,
|
|
}
|
|
},
|
|
distance = 2.0
|
|
})
|
|
end
|
|
end
|
|
end
|
|
end)
|