Files
community_bridge/lib/particles/client/particles.lua
T

182 lines
5.9 KiB
Lua
Raw Normal View History

2025-05-12 00:58:25 -05:00
Particles = {}
2025-04-08 16:47:27 -05:00
Particle = {}
2025-05-12 00:58:25 -05:00
---@diagnostic disable: duplicate-set-field
local Ids = Ids or Require("lib/utility/shared/ids.lua")
local point = Require("lib/points/client/points.lua")
2025-02-10 01:01:32 -06:00
2025-04-19 13:26:20 -05:00
---Loads a ptfx asset into memory.
---@param dict string
---@return boolean
function LoadPtfxAsset(dict)
2025-04-08 16:47:27 -05:00
local failed = 100
2025-02-10 01:01:32 -06:00
while not HasNamedPtfxAssetLoaded(dict) and failed >= 0 do
2025-04-19 13:26:20 -05:00
RequestNamedPtfxAsset(dict)
2025-02-10 01:01:32 -06:00
failed = failed - 1
2025-04-19 13:26:20 -05:00
Wait(100)
2025-02-10 01:01:32 -06:00
end
2025-04-19 13:26:20 -05:00
assert(failed > 0, "Failed to load dict asset: " .. dict)
return HasNamedPtfxAssetLoaded(dict)
2025-04-08 16:47:27 -05:00
end
2025-02-10 01:01:32 -06:00
2025-04-08 16:47:27 -05:00
--- 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.
2025-05-12 00:58:25 -05:00
function Particle.Play(dict, ptfx, pos, rot, scale, color, looped, loopLength)
2025-04-19 13:26:20 -05:00
LoadPtfxAsset(dict)
2025-04-20 18:54:27 -05:00
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()
2025-04-19 13:26:20 -05:00
if loopLength then
Wait(loopLength)
2025-04-20 18:54:27 -05:00
Particle.Remove(particle)
2025-04-19 13:26:20 -05:00
end
2025-04-20 18:54:27 -05:00
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
2025-05-12 00:58:25 -05:00
function Particle.Stop(particle)
2025-04-20 18:54:27 -05:00
if not particle then return end
StopParticleFxLooped(particle, false)
RemoveParticleFx(particle, false)
RemoveNamedPtfxAsset(particle)
2025-05-12 00:58:25 -05:00
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
2025-04-20 18:54:27 -05:00
2025-05-12 00:58:25 -05:00
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)
2025-04-19 13:26:20 -05:00
end
2025-05-12 00:58:25 -05:00
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)
2025-04-19 13:26:20 -05:00
function Particle.CreateOnEntity(dict, ptfx, entity, offset, rot, scale, color, looped, loopLength)
LoadPtfxAsset(dict)
2025-02-10 01:01:32 -06:00
UseParticleFxAssetNextCall(dict)
2025-04-19 13:26:20 -05:00
SetParticleFxNonLoopedColour(color.x, color.y, color.z)
local particle = nil
2025-02-10 01:01:32 -06:00
if looped then
2025-04-19 13:26:20 -05:00
particle = StartNetworkedParticleFxLoopedOnEntity(ptfx, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale, false, false, false)
2025-02-10 01:01:32 -06:00
if loopLength then
Wait(loopLength)
2025-04-19 13:26:20 -05:00
RemoveParticleFxFromEntity(entity)
2025-02-10 01:01:32 -06:00
end
else
2025-04-19 13:26:20 -05:00
particle = StartNetworkedParticleFxLoopedOnEntity(ptfx, entity, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, scale, false, false, false)
2025-02-10 01:01:32 -06:00
end
2025-04-19 13:26:20 -05:00
RemoveNamedPtfxAsset(ptfx)
return particle
2025-02-10 01:01:32 -06:00
end
2025-04-19 13:26:20 -05:00
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
2025-04-08 16:47:27 -05:00
return Particle