I need some help with making a particle spiral around a frozen entity. I feel like I am going about this the wrong way, this is the relevant piece of code. It "somewhat" works but it isn't a clean spiral.
Not very familiar with velocity in a 3d space.
pos = initial entity pos (for all intents and purposes just assume (0,0,0))
[lua]
timer.Create("ParticleVelocity", .01, 80, function()
yaw = yaw + 8
if ( yaw > 360 ) then yaw = 0; end
local yaw = yaw
if ( yaw > 360 ) then yaw = yaw - 360; end
x = radius * math.cos((yaw * math.pi) / 180) -- Just gets a point on a circle (radius 20)
y = radius * math.sin((yaw * math.pi) / 180)
local ppos = particle:GetPos()
endPos = Vector(pos.x, pos.y, ppos.z) + Vector(x,y,4) --End pos is the original pos + the pos on the circle and a little bit higher.
dx = endPos.x - ppos.x
dy = endPos.y - ppos.y
dz = endPos.z - ppos.z
d = math.sqrt(dx*dx + dy*dy + dz*dz)
vx = dx/d * 24
vy = dy/d * 24
vz = dz/d * 24
particle:SetVelocity( Vector(vx,vy,vz) );
end)
[/lua]
[B]Note that I am assuming that you want the particle to orbit around the entity, correct me if I am wrong[/B]
I would suggest using an effect for this and simply draw a sprite.
Effects are located in the [I]lua/effects/[/I] directory, or [i]entities/effects/[/i] for gamemodes.
In my example ([I]orbit.lua[/I]), I start by marking the effect for download and create a varible that points to the material the effect will use for the sprite:
[code]
AddCSLuaFile()
EFFECT.matsprite = Material("effects/select_ring")
[/code]
The functions we are interested in for this effect is [URL="http://wiki.garrysmod.com/page/EFFECT/Init"]Init[/URL], [URL="http://wiki.garrysmod.com/page/EFFECT/Think"]Think[/URL] and [URL="http://wiki.garrysmod.com/page/EFFECT/Render"]Render[/URL].
Let us start with [URL="http://wiki.garrysmod.com/page/EFFECT/Init"]Init[/URL], it gets called when the effect is created.
The first and only argument is an [URL="http://wiki.garrysmod.com/page/Category:CEffectData"]CEffectData[/URL] object, which contains data for the effect; example on that at the end.
[code]
function EFFECT:Init(data)
local ent = data:GetEntity() -- get target entity
if not IsValid(ent) then
return -- if the entity is not valid, no need to continue
end
self:SetPos(ent:GetPos()) -- set the position of the effect at the entitys position
-- NOTE: since your entity will be frozen we only set the position once here, if you plan
-- to move the entity; set the position in the Think function
-- get the render bounds of the entity
local min, max = ent:GetRenderBounds()
-- set the render bounds of the effect to be bigger than the entitys, because the sprite
-- will most likely orbit outside the entitys render bounds; 50% larger will do(?)
self:SetRenderBounds(min*1.5, max*1.5)
self.entity = ent -- store the entity
self.radius = data:GetRadius() -- store the radius
end
[/code]
[URL="http://wiki.garrysmod.com/page/EFFECT/Think"]Think[/URL], this function is used for the logic of the effect; returning anything but true removes the effect.
[code]
function EFFECT:Think()
local ent = self.entity -- use the entity specified in Init
if not IsValid(ent) then
return false -- if the entity is not valid, remove the effect
end
-- calculating the position of the sprite
local radius = self.radius -- use the radius specified in Init
local rad = RealTime() -- let us be lazy and just use the time as the radians :^)
self.spritepos = ent:GetPos() +
ent:GetRight()*math.cos(rad)*radius +
ent:GetForward()*math.sin(rad)*radius
return true --keep the effect alive
end
[/code]
[URL="http://wiki.garrysmod.com/page/EFFECT/Render"]Render[/URL], the function that renders the effect; self-explanatory:
[code]
function EFFECT:Render()
if self.spritepos then
render.SetMaterial(self.matsprite)
render.DrawSprite(self.spritepos, 16, 16, color_white)
end
end
[/code]
And that's it!
Here is the full code:
[code]
AddCSLuaFile()
EFFECT.matsprite = Material("effects/select_ring")
function EFFECT:Init(data)
local ent = data:GetEntity() -- get target entity
if not IsValid(ent) then
return -- if the entity is not valid, no need to continue
end
self:SetPos(ent:GetPos()) -- set the position of the effect at the entitys position
-- NOTE: since your entity will be frozen we only set the position once here, if you plan
-- to move the entity; set the position in the Think function
-- get the render bounds of the entity
local min, max = ent:GetRenderBounds()
-- set the render bounds of the effect to be bigger than the entitys, because the sprite
-- will most likely orbit outside the entitys render bounds; 50% larger will do(?)
self:SetRenderBounds(min*1.5, max*1.5)
self.entity = ent -- store the entity
self.radius = data:GetRadius() -- store the radius
end
function EFFECT:Think()
local ent = self.entity -- use the entity specified in Init
if not IsValid(ent) then
return false -- if the entity is not valid, remove the effect
end
-- calculating the position of the sprite
local radius = self.radius -- use the radius specified in Init
local rad = RealTime() -- let us be lazy and just use the time as the radians :^)
self.spritepos = ent:GetPos() +
ent:GetRight()*math.cos(rad)*radius +
ent:GetForward()*math.sin(rad)*radius
return true --keep the effect alive
end
function EFFECT:Render()
if self.spritepos then
render.SetMaterial(self.matsprite)
render.DrawSprite(self.spritepos, 16, 16, color_white)
end
end
[/code]
To apply the effect, use [URL="http://wiki.garrysmod.com/page/util/Effect"]util.Effect[/URL]
I suggest applying the effect CLIENTSIDE, because some clients might not have discovered the entity you are targeting, which will remove the effect for them.
Applying the effect on an entity you are looking at:
[code]
lua_run_cl local data = EffectData() data:SetEntity(Entity(1):GetEyeTrace().Entity) data:SetRadius(24) util.Effect("orbit", data)
[/code]
Applying the effect when the entity is initialized:
[code]
function ENT:Initialize()
if CLIENT then
local data = EffectData()
data:SetEntity(self)
data:SetRadius(24)
util.Effect("orbit", data)
end
end
[/code]
Good luck!
Sorry, you need to Log In to post a reply to this thread.