Effects and Render Bounds

So i have a couple effects that give me issues. They are parented to a prop which may possibly move between visleafs. When this actually happens, the effect gets “stuck” in the last leaf it was in, while the prop continues moving into the new visleaf. Another issue i’ve had with it is that it fails to draw completely if it is “spawned” in a visleaf that the player isn’t in (sometimes).

What i want to know is this: how can I make an effect draw indefinitely, regardless of which visleaf it is in?

I want to something similar to setting its transmit state to TRANSMIT_ALWAYS.

Here’s the code:

local matLight = Material( “models/spawn_effect2” )

function EFFECT:Init( data )

self.LifeTime = CurTime() + 30
self.Ent = data:GetEntity()

if not ValidEntity( self.Ent ) then return end

self.Entity:SetModel( self.Ent:GetModel() )
self.Entity:SetPos( self.Ent:GetPos() )
self.Entity:SetAngles( self.Ent:GetAngles() )
self.Entity:SetParent( self.Ent )


function EFFECT:DieEffect()

local min = self.Entity:LocalToWorld( self.Entity:OBBMins() )
local max = self.Entity:LocalToWorld( self.Entity:OBBMaxs() )

local emitter = ParticleEmitter( self.Entity:GetPos() )

for i=1, math.Clamp( self.Entity:BoundingRadius(), 10, 100 ) do

	local pos = Vector( math.Rand( min.x, max.x ), math.Rand( min.y, max.y ), math.Rand( min.z, max.z ) )
	local norm = ( pos - self.Entity:LocalToWorld( self.Entity:OBBCenter() ) ):Normalize()
	local particle = emitter:Add( "effects/yellowflare", pos )
	particle:SetVelocity( norm * math.random( 50, 100 ) )
	particle:SetDieTime( math.Rand( 1.5, 3.0 ) )
	particle:SetStartAlpha( 255 )
	particle:SetEndAlpha( 0 )
	particle:SetStartSize( math.Rand( 3, 6 ) )
	particle:SetEndSize( 0 )
	particle:SetRoll( 0 )
	particle:SetColor( 100, 200, 255 )
	particle:SetCollide( true )
	particle:SetBounce( 1.0 )
	particle:SetAirResistance( 50 )
	particle:SetVelocityScale( true )
	particle:SetGravity( Vector( 0, 0, 0 ) )



function EFFECT:Think( )

if not ValidEntity( self.Ent ) then self.Entity:DieEffect() return false end

if self.LifeTime > CurTime() then
	return true
	return false


function EFFECT:Render()

self.Alpha = math.sin( CurTime() * 2 ) * 50 + 50

self.Entity:SetColor( 255, 255, 255, math.Clamp( self.Alpha, 5, 255 ) )

local EyeNormal = self.Entity:GetPos() - EyePos()
local Distance = EyeNormal:Length()

local Pos = EyePos() + EyeNormal * Distance * 0.01

cam.Start3D( Pos, EyeAngles() )
	SetMaterialOverride( matLight )
	SetMaterialOverride( 0 )


I cut out the renderbounds code because I wasn’t sure if i was doing it properly. If i set its renderbounds to a huge area, would that effectively be the same as making it transmit regardless of the visleaf it is in?

The solution is to create the effect on the client. When you dispatch an effect from the server it’s fixed to the PVS that you SetOrigin() the EffectData to. This is why some people having problems with effects when they only SetEntity and don’t set the origin. (ParticleEffect is also a wrapper for an effect, so the same rules apply)

So i used a dummy effect which essentially just calls the real effect on the client. It doesn’t draw at all for me.


[lua]function EFFECT:Init( data )

self.Ent = data:GetEntity()

if not ValidEntity( self.Ent ) then return end

local ed = EffectData()
ed:SetEntity( self.Ent )
ed:SetOrigin( self.Ent:GetPos() )
util.Effect( "prop_possessed", ed, true, true )


I think he means util.Effect the effect on the client, not in the server.

Yes. If the effect should always be with the entity then call the util.Effect on the client Initialize function.

You can also (I find this more reliable) just get rid of the effect altogether and just create your emitter in the actual entity.

I gave up with fucking around with it and instead used a SENT with TRANSMIT_ALWAYS. Works well enough.