forked from Simnation/Main
182 lines
5.9 KiB
Lua
182 lines
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
|