Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local QBCore = exports['qb-core']:GetCoreObject()
- local LocalPotData = {}
- local PlantEntities = {}
- local PotEntitiesById = {}
- local TargetedPots = {}
- local PendingPotSync = {}
- local PlantModels = {
- [2] = "prop_weed_02",
- [3] = "prop_weed_01"
- }
- local SlotOffsets = {
- [1] = { vector3(0.0, 0.0, 0.0) },
- [2] = { vector3(-0.2, -0.2, 0.0), vector3(0.2, 0.2, 0.0) },
- [3] = { vector3(-0.3, -0.2, 0.0), vector3(0.0, 0.3, 0.0), vector3(0.3, -0.2, 0.0) }
- }
- RegisterNetEvent('weed:updatePotData', function(potId, potData)
- print("[DEBUG] updatePotData received:", potId)
- LocalPotData[potId] = potData
- if PlantEntities[potId] then
- for _, ent in pairs(PlantEntities[potId]) do
- if DoesEntityExist(ent) then DeleteEntity(ent) end
- end
- end
- PlantEntities[potId] = {}
- if not potData then return end
- local pot = PotEntitiesById[potId]
- if not pot or not DoesEntityExist(pot) then
- PendingPotSync[potId] = potData
- return
- end
- local slots = Config.PotTypes[potData.type].slots
- for i = 1, slots do
- local seed = potData.seeds[i]
- if seed then
- local offset = SlotOffsets[slots][i] or vector3(0.0, 0.0, 0.0)
- local base = GetEntityCoords(pot)
- local pos = base + offset
- if PlantModels[seed.stage] then
- local model = GetHashKey(PlantModels[seed.stage])
- RequestModel(model) while not HasModelLoaded(model) do Wait(0) end
- local obj = CreateObject(model, pos, false, true, false)
- SetEntityHeading(obj, GetEntityHeading(pot))
- FreezeEntityPosition(obj, true)
- SetEntityAlpha(obj, 220, false)
- PlantEntities[potId][i] = obj
- elseif seed.stage == 1 then
- UseParticleFxAssetNextCall("core")
- StartParticleFxNonLoopedAtCoord("ent_anim_dusty_hands", pos.x, pos.y, pos.z + 0.1, 0.0, 0.0, 0.0, 0.7, false, false, false)
- end
- end
- end
- -- 📦 Attach interaction via box zone
- if not TargetedPots[potId] then
- local coords = GetEntityCoords(pot)
- local heading = GetEntityHeading(pot)
- exports['qb-target']:AddBoxZone("pot_" .. potId, coords, 1.2, 1.2, {
- name = "pot_" .. potId,
- heading = heading,
- debugPoly = false,
- minZ = coords.z - 0.5,
- maxZ = coords.z + 1.2
- }, {
- options = {
- {
- label = "🌱 Plant Seed",
- icon = "fas fa-seedling",
- item = "weed_seed",
- canInteract = function()
- local pot = LocalPotData[potId]
- if not pot or type(pot.seeds) ~= "table" then return false end
- for i = 1, Config.PotTypes[pot.type].slots do
- local seed = pot.seeds[i]
- if not seed or seed.stage == nil then return true end
- end
- return false
- end,
- action = function()
- print("[DEBUG] Plant Seed action triggered for:", potId)
- TriggerServerEvent('weed:insertSeed', potId)
- end
- },
- {
- label = "💧 Water Plant",
- icon = "fas fa-tint",
- item = "watering_can",
- canInteract = function()
- local pot = LocalPotData[potId]
- if not pot or type(pot.seeds) ~= "table" then return false end
- for _, seed in pairs(pot.seeds) do
- if seed and not seed.watered and (seed.waterCount or 0) < 3 then return true end
- end
- return false
- end,
- action = function()
- TriggerServerEvent('weed:waterSeed', potId)
- end
- },
- {
- label = "🌿 Fertilize",
- icon = "fas fa-leaf",
- item = "weed_fertilizer",
- canInteract = function()
- local pot = LocalPotData[potId]
- if not pot or type(pot.seeds) ~= "table" then return false end
- for _, seed in pairs(pot.seeds) do
- if seed and not seed.fertilized then return true end
- end
- return false
- end,
- action = function()
- TriggerServerEvent('weed:fertilizeSeed', potId)
- end
- },
- {
- label = "💬 Check Progress",
- icon = "fas fa-leaf",
- canInteract = function()
- local pot = LocalPotData[potId]
- return pot and type(pot.seeds) == "table" and next(pot.seeds) ~= nil
- end,
- action = function()
- ShowPotStatus(potId)
- end
- },
- {
- label = "✂️ Harvest Plant",
- icon = "fas fa-cut",
- canInteract = function()
- local pot = LocalPotData[potId]
- if not pot or type(pot.seeds) ~= "table" then return false end
- for _, seed in pairs(pot.seeds) do
- if seed and seed.stage == Config.GrowthStages and (seed.waterCount or 0) >= 3 then return true end
- end
- return false
- end,
- action = function()
- TriggerServerEvent('weed:harvestPlant', potId)
- end
- },
- {
- label = "🗑️ Remove Pot",
- icon = "fas fa-trash",
- action = function()
- DeleteEntity(pot)
- TriggerServerEvent('weed:removePot', potId)
- end
- }
- },
- distance = 3.5
- })
- TargetedPots[potId] = true
- end
- end)
- RegisterNetEvent('weed:placePotFinal', function(potType, coords, heading, potId)
- local model = Config.PotTypes[potType].model
- local hash = GetHashKey(model)
- RequestModel(hash)
- while not HasModelLoaded(hash) do Wait(0) end
- local pot = CreateObject(hash, coords.x, coords.y, coords.z + 0.2, true, true, false)
- SetEntityHeading(pot, heading)
- PlaceObjectOnGroundProperly(pot)
- FreezeEntityPosition(pot, true)
- print("[DEBUG] Pot entity created:", potId, DoesEntityExist(pot))
- PotEntitiesById[potId] = pot
- if PendingPotSync[potId] then
- TriggerEvent('weed:updatePotData', potId, PendingPotSync[potId])
- PendingPotSync[potId] = nil
- end
- end)
- RegisterNetEvent('weed:previewPot', function(potType, itemSlot)
- local ped = PlayerPedId()
- local model = Config.PotTypes[potType].model
- local hash = GetHashKey(model)
- RequestModel(hash) while not HasModelLoaded(hash) do Wait(0) end
- local preview = CreateObject(hash, GetEntityCoords(ped), false, false, false)
- SetEntityAlpha(preview, 150, false)
- FreezeEntityPosition(preview, true)
- SetEntityCollision(preview, false, false)
- local placing = true
- local heading = 0.0
- CreateThread(function()
- while placing do
- Wait(0)
- local pos = GetOffsetFromEntityInWorldCoords(ped, 0.0, 1.5, -1.0)
- SetEntityCoords(preview, pos, false, false, false, false)
- heading = heading + (IsControlPressed(0, 108) and 1 or IsControlPressed(0, 109) and -1 or 0)
- SetEntityHeading(preview, heading)
- DrawText3D(pos.x, pos.y, pos.z + 1.0, "~g~[E]~s~ place | ~r~[X]~s~ cancel")
- if IsControlJustPressed(0, 38) then
- placing = false
- DeleteEntity(preview)
- TriggerServerEvent('weed:consumePotItem', potType, itemSlot, pos, heading)
- elseif IsControlJustPressed(0, 73) then
- placing = false
- DeleteEntity(preview)
- end
- end
- end)
- end)
- RegisterNetEvent('weed:tryRefillCan', function()
- local ped = PlayerPedId()
- if IsEntityInWater(ped) then
- TriggerServerEvent('weed:refillCan')
- else
- QBCore.Functions.Notify('Find water to refill the can.', 'error')
- end
- end)
- function ShowPotStatus(potId)
- local pot = LocalPotData[potId]
- if not pot then
- QBCore.Functions.Notify("Unknown pot", 'error')
- return
- end
- local msg = "🌾 Pot Progress:"
- for slot, seed in pairs(pot.seeds) do
- if seed then
- local stage = seed.stage == 1 and "Seedling"
- or seed.stage == 2 and "Growing"
- or seed.stage == 3 and "Ready"
- or "?"
- local water = seed.watered and "💧 Watered (awaiting growth)"
- or string.format("💧 %d/3", seed.waterCount or 0)
- local fert = seed.fertilized and "🌿 Fertilized" or "No Fertilizer"
- msg = msg .. ("\nSlot %d: %s | %s | %s"):format(slot, stage, water, fert)
- end
- end
- QBCore.Functions.Notify(msg, 'primary', 8000)
- end
- function DrawText3D(x, y, z, text)
- local onScreen, _x, _y = World3dToScreen2d(x, y, z)
- local p = GetGameplayCamCoords()
- local dist = #(vector3(x, y, z) - p)
- if dist > 15.0 or not onScreen then return end
- local scale = (1 / dist) * 1.7
- scale = scale * (1 / GetGameplayCamFov()) * 100
- SetTextScale(0.40, 0.40)
- SetTextFont(4)
- SetTextProportional(1)
- SetTextColour(255, 255, 255, 255)
- SetTextCentre(true)
- SetTextDropshadow(0, 0, 0, 0, 255)
- SetTextOutline()
- SetTextEntry("STRING")
- AddTextComponentString(text)
- DrawText(_x, _y)
- local factor = (string.len(text)) / 320
- DrawRect(_x, _y + 0.015, 0.035 + factor, 0.045, 0, 0, 0, 180)
- end
Add Comment
Please, Sign In to add comment