182 lines
		
	
	
		
			No EOL
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			No EOL
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
Particles = {}
 | 
						|
Particle = {}
 | 
						|
---@diagnostic disable: duplicate-set-field
 | 
						|
local Ids = Ids or Require("lib/utility/shared/ids.lua")
 | 
						|
local point =  Require("lib/points/client/points.lua")
 | 
						|
 | 
						|
---Loads a ptfx asset into memory.
 | 
						|
---@param dict string
 | 
						|
---@return boolean
 | 
						|
function LoadPtfxAsset(dict)
 | 
						|
    local failed = 100
 | 
						|
    while not HasNamedPtfxAssetLoaded(dict) and failed >= 0 do
 | 
						|
        RequestNamedPtfxAsset(dict)
 | 
						|
        failed = failed - 1
 | 
						|
        Wait(100)
 | 
						|
    end
 | 
						|
    assert(failed > 0, "Failed to load dict asset: " .. dict)
 | 
						|
    return HasNamedPtfxAssetLoaded(dict)
 | 
						|
end
 | 
						|
 | 
						|
--- Create a particle effect at the specified position and rotation.
 | 
						|
--- @param dict string
 | 
						|
--- @param ptfx string
 | 
						|
--- @param pos vector3
 | 
						|
--- @param rot vector3
 | 
						|
--- @param scale number
 | 
						|
--- @param color vector3
 | 
						|
--- @param looped boolean
 | 
						|
--- @param loopLength number|nil
 | 
						|
--- @return number|nil ptfxHandle -- The handle of the particle effect, or nil if it failed to create.
 | 
						|
function Particle.Play(dict, ptfx, pos, rot, scale, color, looped, loopLength)
 | 
						|
    LoadPtfxAsset(dict)
 | 
						|
    UseParticleFxAssetNextCall(dict)
 | 
						|
    SetParticleFxNonLoopedColour(color.x, color.y, color.z)
 | 
						|
    local particle = nil
 | 
						|
    if looped then
 | 
						|
        particle = StartParticleFxLoopedAtCoord(ptfx, pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, scale, false, false, false, false)
 | 
						|
        CreateThread(function()
 | 
						|
            if loopLength then 
 | 
						|
                Wait(loopLength)
 | 
						|
                Particle.Remove(particle)
 | 
						|
            end
 | 
						|
        end)
 | 
						|
    else
 | 
						|
        particle = StartParticleFxNonLoopedAtCoord(ptfx, pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, scale, false, false, false, false)
 | 
						|
    end
 | 
						|
 | 
						|
    return particle
 | 
						|
end
 | 
						|
 | 
						|
function Particle.Stop(particle)
 | 
						|
    if not particle then return end
 | 
						|
    StopParticleFxLooped(particle, false)
 | 
						|
    RemoveParticleFx(particle, false)
 | 
						|
    RemoveNamedPtfxAsset(particle)
 | 
						|
end
 | 
						|
 | 
						|
function Particle.Create(data)
 | 
						|
    assert(data, "Particle data is nil")
 | 
						|
    assert(data.dict, "Invalid particle data. Must contain string dict.")
 | 
						|
    assert(data.ptfx, "Invalid particle data. Must contain string ptfx.")
 | 
						|
 | 
						|
    local _id = data.id or Ids.CreateUniqueId(Particles)
 | 
						|
    data = {
 | 
						|
        id = _id,
 | 
						|
        dict = data.dict,
 | 
						|
        ptfx = data.ptfx,
 | 
						|
        position = data.position or vector3(0.0, 0.0, 0.0),
 | 
						|
        rotation = data.rotation or vector3(0, 0, 0),
 | 
						|
        size = data.size or 1.0,
 | 
						|
        color = data.color or vector3(255, 255, 255),
 | 
						|
        looped = data.looped or false,
 | 
						|
        loopLength = data.loopLength or nil,
 | 
						|
        spawned = false,
 | 
						|
    }
 | 
						|
    Particles[_id] = data
 | 
						|
 | 
						|
    point.Register( -- checking if players in range
 | 
						|
        _id, 
 | 
						|
        data.position, 
 | 
						|
        data.drawDistance or 50.0, 
 | 
						|
        data,
 | 
						|
        function(_)     
 | 
						|
            if not Particles[_id] then return point.Remove(_id) end
 | 
						|
            local particleData = Particles[_id]
 | 
						|
            if particleData.spawned then return end
 | 
						|
            particleData.spawned = Particle.Play(
 | 
						|
                particleData.dict, 
 | 
						|
                particleData.ptfx, 
 | 
						|
                particleData.position, 
 | 
						|
                particleData.rotation, 
 | 
						|
                particleData.size, 
 | 
						|
                particleData.color, 
 | 
						|
                particleData.looped, 
 | 
						|
                particleData.loopLength
 | 
						|
            )
 | 
						|
        end,
 | 
						|
        function(markerData)  
 | 
						|
            if not Particles[_id] then return end
 | 
						|
            local particleData = Particles[_id]
 | 
						|
            if not particleData.spawned then return end
 | 
						|
            Particle.Stop(particleData.spawned)
 | 
						|
            particleData.spawned = nil
 | 
						|
        end
 | 
						|
    )
 | 
						|
    return _id
 | 
						|
end
 | 
						|
 | 
						|
function Particle.Remove(id)
 | 
						|
    if not id then return end
 | 
						|
    local particle = Particles[id]
 | 
						|
    if not particle then return end
 | 
						|
    Particle.Stop(particle.spawned)
 | 
						|
    Particles[id] = nil
 | 
						|
    point.Remove(id)
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
 | 
						|
RegisterNetEvent("community_bridge:Client:Particle", function(data)
 | 
						|
    if not data then return end
 | 
						|
    Particle.Create(data)
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent("community_bridge:Client:ParticleBulk", function(datas)
 | 
						|
    if not datas then return end
 | 
						|
    for _, data in pairs(datas) do
 | 
						|
        Particle.Create(data)
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent("community_bridge:Client:ParticleRemove", function(id)
 | 
						|
    local particle = Particles[id]
 | 
						|
    if not particle then return end
 | 
						|
    Particle.Remove(Drawing[id])
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent("community_bridge:Client:ParticleRemoveBulk", function(ids)
 | 
						|
    for _, id in pairs(ids) do
 | 
						|
        Particle.Remove(id)
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
 | 
						|
 | 
						|
function Particle.CreateOnEntity(dict, ptfx, entity, offset, rot, scale, color, looped, loopLength)
 | 
						|
    LoadPtfxAsset(dict)
 | 
						|
    UseParticleFxAssetNextCall(dict)
 | 
						|
    SetParticleFxNonLoopedColour(color.x, color.y, color.z)
 | 
						|
    local particle = nil
 | 
						|
    if looped then
 | 
						|
        particle = StartNetworkedParticleFxLoopedOnEntity(ptfx, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale, false, false, false)
 | 
						|
        if loopLength then
 | 
						|
            Wait(loopLength)
 | 
						|
            RemoveParticleFxFromEntity(entity)
 | 
						|
        end
 | 
						|
    else
 | 
						|
        particle = StartNetworkedParticleFxLoopedOnEntity(ptfx, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale, false, false, false)
 | 
						|
    end
 | 
						|
    RemoveNamedPtfxAsset(ptfx)
 | 
						|
    return particle
 | 
						|
end
 | 
						|
 | 
						|
function Particle.CreateOnEntityBone(dict, ptfx, entity, bone,  offset, rot, scale, color, looped, loopLength)
 | 
						|
    LoadPtfxAsset(dict)
 | 
						|
    UseParticleFxAssetNextCall(dict)
 | 
						|
    SetParticleFxNonLoopedColour(color.x, color.y, color.z)
 | 
						|
    local particle = nil
 | 
						|
    if looped then
 | 
						|
        particle = StartNetworkedParticleFxLoopedOnEntityBone(ptfx, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, bone, scale, false, false, false)
 | 
						|
        if loopLength then
 | 
						|
            Wait(loopLength)
 | 
						|
            RemoveParticleFxFromEntity(entity)
 | 
						|
        end
 | 
						|
    else
 | 
						|
        particle = StartNetworkedParticleFxNonLoopedOnEntityBone(ptfx, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, bone, scale, false, false, false)
 | 
						|
    end
 | 
						|
    RemoveNamedPtfxAsset(ptfx)
 | 
						|
    return particle
 | 
						|
end
 | 
						|
 | 
						|
return Particle |