dobrograd-13-06-2022/garrysmod/addons/gmod-tools/lua/entities/particlecontroller_proj.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

583 lines
25 KiB
Lua

AddCSLuaFile()
ENT.Base = "base_gmodentity"
ENT.PrintName = "Particle Controller - Projectile"
ENT.Author = ""
ENT.Spawnable = false
ENT.AdminSpawnable = false
ENT.RenderGroup = RENDERGROUP_NONE
function ENT:SetupDataTables()
self:NetworkVar( "Entity", 0, "TargetEnt" );
self:NetworkVar( "String", 0, "ProjFX_EffectName" );
self:NetworkVar( "Vector", 0, "ProjFX_UtilEffectInfo" ); //x = scale, y = magnitude, x = radius
self:NetworkVar( "Vector", 1, "ProjFX_ColorInfo" );
self:NetworkVar( "String", 1, "ImpactFX_EffectName" );
self:NetworkVar( "Vector", 2, "ImpactFX_UtilEffectInfo" ); //x = scale, y = magnitude, x = radius
self:NetworkVar( "Vector", 3, "ImpactFX_ColorInfo" );
self:NetworkVar( "Int", 0, "AttachNum" );
self:NetworkVar( "Float", 0, "RepeatRate" );
self:NetworkVar( "String", 2, "ProjModel" );
self:NetworkVar( "Int", 1, "ProjModel_AttachNum" );
self:NetworkVar( "Bool", 0, "ProjModel_Invis" );
self:NetworkVar( "Float", 1, "ImpactFX_EffectLifetime" );
self:NetworkVar( "Float", 2, "ProjEnt_Spread" );
self:NetworkVar( "Int", 2, "ProjEnt_Velocity" );
self:NetworkVar( "Bool", 1, "ProjEnt_Gravity" );
self:NetworkVar( "Int", 3, "ProjEnt_Angle" );
self:NetworkVar( "Int", 4, "ProjEnt_Spin" );
self:NetworkVar( "Bool", 2, "ProjEnt_DemomanFix" );
self:NetworkVar( "Float", 3, "ProjEnt_Lifetime_PreHit" );
self:NetworkVar( "Float", 4, "ProjEnt_Lifetime_PostHit" );
self:NetworkVar( "Bool", 3, "ProjEnt_Serverside" );
self:NetworkVar( "Bool", 4, "Active" );
self:NetworkVar( "Bool", 5, "Toggle" );
self:NetworkVar( "Int", 5, "NumpadKey" );
self:NetworkVar( "String", 3, "NumpadState" );
end
function ENT:Initialize()
util.PrecacheModel(self:GetProjModel())
local target = self:GetTargetEnt()
if SERVER then
//Use ourselves as the target - we'll fire projectiles from our own position and angles
local attachment1 = target:GetAttachment( self:GetAttachNum() )
if attachment1 != nil then
self:SetPos( attachment1.Pos )
self:SetAngles( attachment1.Ang )
self:Fire("setparentattachment", target:GetAttachments()[self:GetAttachNum()].name, 0.01)
self:SetTargetEnt(self)
end
else
//Set things up for a particlesystem effect
local projfx_effectname = self:GetProjFX_EffectName()
if projfx_effectname != "" and !string.StartWith( projfx_effectname, "!UTILEFFECT!" ) then
PrecacheParticleSystem(projfx_effectname)
end
local impactfx_effectname = self:GetImpactFX_EffectName()
if impactfx_effectname != "" and !string.StartWith( impactfx_effectname, "!UTILEFFECT!" ) then
PrecacheParticleSystem(impactfx_effectname)
end
end
//super niche bug fix: if we're in multiplayer and our model has any attachment points, then we'll cause visual jittering in the buildbonepositions callback of
//the entity we're parented to. originally we were using our own model to store the projectile model, but that was causing the aforementioned bug, so now we're
//storing the projectile model separately and having this entity use a neutral model that won't cause problems.
self:SetModel("models/hunter/plates/plate.mdl")
self:SetNoDraw(true)
//Don't let players set the repeat rate to a really low amount that lets them spam tons of props every second
if self:GetRepeatRate() > 0 and self:GetRepeatRate() < 0.1 then self:SetRepeatRate(0.1) end
if self:GetRepeatRate() > 0 then
//we're going to be repeating the effect, so let's set that up and let think do the rest
self.NextRepeat = 0
else
//we won't be repeating the effect, so just attach it right now
if self:GetActive() then self:AttachParticle() end
end
end
function ENT:Think()
if self:GetProjEnt_Serverside() then
if CLIENT then return end
else
if SERVER then return end
end
if self:GetNumpadState() == "off" then
//MsgN("turn off")
self:SetNumpadState("")
end
if self:GetNumpadState() == "on" then
//MsgN("turn on")
self:SetNumpadState("")
if self:GetRepeatRate() > 0 then
//we're going to be repeating the effect, so let's set that up and let think do the rest
self.NextRepeat = 0
else
//we won't be repeating the effect, so just attach it right now
if self:GetActive() then self:AttachParticle() end
end
end
if self:GetActive() == true and self:GetRepeatRate() > 0 then
if !( self.NextRepeat > CurTime() ) then
self:AttachParticle()
self.NextRepeat = CurTime() + self:GetRepeatRate()
end
end
self:NextThink(CurTime())
return true
end
function ENT:AttachParticle()
if !self then return end
if self:GetProjEnt_Serverside() then
if CLIENT then return end
else
if SERVER then return end
end
local projent_spread = math.Clamp( self:GetProjEnt_Spread(), 0, 4)
local projent_velocity = self:GetProjEnt_Velocity()
local projent_gravity = self:GetProjEnt_Gravity()
local projent_angle = self:GetProjEnt_Angle()
local projent_spin = self:GetProjEnt_Spin()
local projent_demomanfix = self:GetProjEnt_DemomanFix()
local projent_lifetime_prehit = math.Clamp( self:GetProjEnt_Lifetime_PreHit(), 0, 10)
local projent_lifetime_posthit = math.Clamp( self:GetProjEnt_Lifetime_PostHit(), 0, 10)
local projfx_effectname = self:GetProjFX_EffectName()
local projmodel_attachnum = self:GetProjModel_AttachNum()
local impactfx_effectname = self:GetImpactFX_EffectName()
local impactfx_effectlifetime = math.Clamp( self:GetImpactFX_EffectLifetime(), 0, 10)
local impactfx_utileffectinfo = self:GetImpactFX_UtilEffectInfo()
local impactfx_colorinfo = self:GetImpactFX_ColorInfo()
//Create the projectile entity
local proj = nil
if SERVER then
proj = ents.Create("parctrl_dummyent")
proj:SetModel(self:GetProjModel())
end
if CLIENT then
proj = octolib.createDummy(self:GetProjModel())
end
if !util.IsValidProp(self:GetProjModel()) then
proj:PhysicsInitBox(proj:GetModelBounds())
else
proj:PhysicsInit(SOLID_VPHYSICS)
end
proj:GetPhysicsObject():Wake()
proj:SetNoDraw(self:GetProjModel_Invis())
proj:SetSkin(self:GetSkin())
proj:SetMaterial(self:GetMaterial())
proj:SetPos(self:GetPos())
proj:Spawn()
proj:Activate()
local projphys = proj:GetPhysicsObject()
local selfang = self:GetAngles()
//a lot of attachment points are oriented at an angle on the roll axis - correct this, we want the default projectile angle to be upright
if self:GetParent() != NULL then //this returns a null entity if the player is outside of the visleaf, be careful
if self:GetParent():GetAttachment( self:GetAttachNum() ) then
local _, attachang = WorldToLocal(self:GetPos(), selfang, self:GetParent():GetPos(), self:GetParent():GetAngles())
selfang = Angle(selfang.p,selfang.y,selfang.r - attachang.r)
end
end
//muzzle attachments on demoman weapons are oriented 90 degrees to the side for some reason - give players an option to fix this
if projent_demomanfix == true then selfang:RotateAroundAxis( selfang:Up(), -90 ) end
//spread
local projang = Angle(selfang.p,selfang.y,selfang.r) //self:GetAngles()
local randang = AngleRand()
projang:RotateAroundAxis( projang:Forward(), randang.r )
projang:RotateAroundAxis( projang:Right(), randang.p * (projent_spread / 2) )
projang:RotateAroundAxis( projang:Up(), randang.y * (projent_spread / 4) )
//set the velocity
projphys:SetVelocity(projang:Forward() * projent_velocity)
//now de-randomize the roll - we only needed to do that for the velocity
projang:RotateAroundAxis( projang:Forward(), -randang.r )
//change the angle of the projectile
local rotationang = Angle(0,0,0)
//0 = forward, don't change it
//1 = left
if projent_angle == 1 then projang:RotateAroundAxis( projang:Up(), 90 ) rotationang = Angle(0,-90,0)
//2 = right
elseif projent_angle == 2 then projang:RotateAroundAxis( projang:Up(), -90 ) rotationang = Angle(0,90,0)
//3 = up
elseif projent_angle == 3 then projang:RotateAroundAxis( projang:Right(), 90 ) rotationang = Angle(90,0,0)
//4 = down
elseif projent_angle == 4 then projang:RotateAroundAxis( projang:Right(), -90 ) rotationang = Angle(-90,0,0)
//5 = back
elseif projent_angle == 5 then projang:RotateAroundAxis( projang:Up(), 180 ) rotationang = Angle(0,180,0) end
proj:SetAngles(projang)
//add spin - spin should be the same regardless of which way we've oriented the prop with projent_angle
//0 - don't spin
//1 - spin pitch
if projent_spin == 1 then projphys:AddAngleVelocity( rotationang:Right() * -350 )
//2 - spin yaw
elseif projent_spin == 2 then projphys:AddAngleVelocity( rotationang:Forward() * 350 )
//3 - spin roll
elseif projent_spin == 3 then projphys:AddAngleVelocity( rotationang:Up() * -350 )
//4 - spin random
elseif projent_spin == 4 then projphys:AddAngleVelocity( VectorRand() * -350 ) end
projphys:EnableGravity(projent_gravity)
projphys:SetMaterial("gmod_silent") //don't play physics sounds
proj:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE_DEBRIS) //don't collide with other projectiles
proj:SetOwner(self:GetParent()) //don't collide with the prop that the effect ent is parented to
if SERVER then self:DeleteOnRemove(proj) end //delete the proj if the effect ent is removed - i'd love to do this for clientside projs too but this function is serverside only
//Create the projectile effect, if enabled
if projfx_effectname != "" then
local projfxent = proj
if SERVER then
//since we can't call util.Effect or CreateParticleEffect on the server, we have to get the ent to do it itself
projfxent:SetEffectName(projfx_effectname)
projfxent:SetColorInfo(self:GetProjFX_ColorInfo())
projfxent:SetUtilEffectInfo(self:GetProjFX_UtilEffectInfo())
projfxent:SetAttachNum(projmodel_attachnum)
end
if CLIENT then
if string.StartWith( projfx_effectname, "!UTILEFFECT!" ) then
//Create a util effect
//Unfortunately, we have to do all of this every single time the effect repeats, because if we do it in Initialize instead, a whole bunch of stuff doesn't work properly
local effectscale = self:GetProjFX_UtilEffectInfo().x
local effectmagnitude = self:GetProjFX_UtilEffectInfo().y
local effectradius = self:GetProjFX_UtilEffectInfo().z
local projeffectdata = EffectData()
projeffectdata:SetEntity( projfxent )
//if ( string.find(projfx_effectname, "Tracer", 0, true) != nil ) then projeffectdata:SetScale(5000) else projeffectdata:SetScale( effectscale ) end //for tracer effects, scale is the speed of the bullet, so we need to keep this high; useless for a projectile effect
projeffectdata:SetScale( effectscale )
projeffectdata:SetMagnitude( effectmagnitude )
projeffectdata:SetRadius(effectradius )
//flags can be set by typing !FLAG#! at the end of the effect name
projeffectdata:SetFlags( 0 )
if string.EndsWith( projfx_effectname, "!" ) then
if string.find( projfx_effectname, "!FLAG1!" ) then projeffectdata:SetFlags( 1 ) projfx_effectname = string.Replace( projfx_effectname, "!FLAG1!", "" ) end
if string.find( projfx_effectname, "!FLAG2!" ) then projeffectdata:SetFlags( 2 ) projfx_effectname = string.Replace( projfx_effectname, "!FLAG2!", "" ) end
if string.find( projfx_effectname, "!FLAG3!" ) then projeffectdata:SetFlags( 3 ) projfx_effectname = string.Replace( projfx_effectname, "!FLAG3!", "" ) end
if string.find( projfx_effectname, "!FLAG4!" ) then projeffectdata:SetFlags( 4 ) projfx_effectname = string.Replace( projfx_effectname, "!FLAG4!", "" ) end
if string.find( projfx_effectname, "!FLAG5!" ) then projeffectdata:SetFlags( 5 ) projfx_effectname = string.Replace( projfx_effectname, "!FLAG5!", "" ) end
if string.find( projfx_effectname, "!FLAG6!" ) then projeffectdata:SetFlags( 6 ) projfx_effectname = string.Replace( projfx_effectname, "!FLAG6!", "" ) end
if string.find( projfx_effectname, "!FLAG7!" ) then projeffectdata:SetFlags( 7 ) projfx_effectname = string.Replace( projfx_effectname, "!FLAG7!", "" ) end
if string.find( projfx_effectname, "!FLAG8!" ) then projeffectdata:SetFlags( 8 ) projfx_effectname = string.Replace( projfx_effectname, "!FLAG8!", "" ) end
if string.find( projfx_effectname, "!FLAG9!" ) then projeffectdata:SetFlags( 9 ) projfx_effectname = string.Replace( projfx_effectname, "!FLAG9!", "" ) end
end
//colors can also be set the same way
projeffectdata:SetColor(0)
if string.EndsWith( projfx_effectname, "!" ) then
if string.find( projfx_effectname, "!COLOR1!" ) then projeffectdata:SetColor( 1 ) projfx_effectname = string.Replace( projfx_effectname, "!COLOR1!", "" ) end
if string.find( projfx_effectname, "!COLOR2!" ) then projeffectdata:SetColor( 2 ) projfx_effectname = string.Replace( projfx_effectname, "!COLOR2!", "" ) end
if string.find( projfx_effectname, "!COLOR3!" ) then projeffectdata:SetColor( 3 ) projfx_effectname = string.Replace( projfx_effectname, "!COLOR3!", "" ) end
if string.find( projfx_effectname, "!COLOR4!" ) then projeffectdata:SetColor( 4 ) projfx_effectname = string.Replace( projfx_effectname, "!COLOR4!", "" ) end
if string.find( projfx_effectname, "!COLOR5!" ) then projeffectdata:SetColor( 5 ) projfx_effectname = string.Replace( projfx_effectname, "!COLOR5!", "" ) end
if string.find( projfx_effectname, "!COLOR6!" ) then projeffectdata:SetColor( 6 ) projfx_effectname = string.Replace( projfx_effectname, "!COLOR6!", "" ) end
if string.find( projfx_effectname, "!COLOR7!" ) then projeffectdata:SetColor( 7 ) projfx_effectname = string.Replace( projfx_effectname, "!COLOR7!", "" ) end
if string.find( projfx_effectname, "!COLOR8!" ) then projeffectdata:SetColor( 8 ) projfx_effectname = string.Replace( projfx_effectname, "!COLOR8!", "" ) end
if string.find( projfx_effectname, "!COLOR9!" ) then projeffectdata:SetColor( 9 ) projfx_effectname = string.Replace( projfx_effectname, "!COLOR9!", "" ) end
end
//dumb situational crap
if string.find( string.lower(projfx_effectname), "shakeropes" ) then projeffectdata:SetMagnitude( effectmagnitude * 20 ) end
if string.find( string.lower(projfx_effectname), "thumperdust" ) then projeffectdata:SetScale( effectscale * 50 ) end
if string.find( string.lower(projfx_effectname), "bloodspray" ) then projeffectdata:SetScale( effectscale * 4 ) end
//just in case someone makes a utileffect that works as a projectile effect
if projfxent:GetAttachment(projmodel_attachnum) != nil then
projeffectdata:SetStart( projfxent:GetAttachment( projmodel_attachnum ).Pos )
projeffectdata:SetOrigin( projfxent:GetAttachment( projmodel_attachnum ).Pos )
projeffectdata:SetAngles( projfxent:GetAttachment( projmodel_attachnum ).Ang )
projeffectdata:SetNormal( projfxent:GetAttachment( projmodel_attachnum ).Ang:Forward() )
else
projeffectdata:SetStart( projfxent:GetPos() )
projeffectdata:SetOrigin( projfxent:GetPos() )
projeffectdata:SetAngles( projfxent:GetAngles() )
projeffectdata:SetNormal( projfxent:GetAngles():Forward() )
end
util.Effect( string.Replace( projfx_effectname, "!UTILEFFECT!", "" ), projeffectdata )
else
//Create a particlesystem effect
//Since we can't specify attachment points with Entity:CreateParticleEffect(), create an entity there to use as a target
local attachment1 = proj:GetAttachment( projmodel_attachnum )
if attachment1 != nil then
//if SERVER then
// projfxent = ents.Create("parctrl_dummyent")
// projfxent:SetModel("models/hunter/plates/plate.mdl")
//end
if CLIENT then
projfxent = octolib.createDummy("models/hunter/plates/plate.mdl")
end
projfxent:SetParent(proj, projmodel_attachnum - 1)
projfxent:SetPos( attachment1.Pos )
projfxent:SetAngles( attachment1.Ang )
projfxent:SetNoDraw(true)
projfxent:Spawn()
projfxent:Activate()
proj:CallOnRemove("RemoveProjFX", function() if IsValid(projfxent) then projfxent:Remove() end end)
end
local clrtb = nil
if self:GetProjFX_ColorInfo() == Vector(0,0,0) then
//MsgN("color = false")
else
//MsgN("color = true")
clrtb = { position = self:GetProjFX_ColorInfo() }
end
local projcpointtable = {}
projcpointtable[1] = { entity = projfxent, attachtype = PATTACH_ABSORIGIN_FOLLOW }
for i = 2, 64 do
if clrtb then
projcpointtable[i] = clrtb
else
projcpointtable[i] = projcpointtable[1]
end
end
projfxent:CreateParticleEffect(projfx_effectname,projcpointtable)
end
end
end
local function projexpire(ent, pos, ang)
//Create the impact effect, if enabled
if impactfx_effectname != "" then
//Create a new entity to attach the impact effect to - we can't use proj since we're removing it immediately after this
local impactfxent = nil
if SERVER then
impactfxent = ents.Create("parctrl_dummyent")
impactfxent:SetModel("models/hunter/plates/plate.mdl")
end
if CLIENT then
impactfxent = octolib.createDummy("models/hunter/plates/plate.mdl")
end
impactfxent:SetPos( pos or proj:GetPos() )
impactfxent:SetAngles( ang or proj:GetAngles() )
impactfxent:SetNoDraw(true)
timer.Simple(impactfx_effectlifetime, function() if IsValid(impactfxent) then impactfxent:Remove() end; end)
impactfxent:Spawn()
impactfxent:Activate()
if SERVER then
//since we can't call util.Effect or CreateParticleEffect on the server, we have to get the ent to do it itself
impactfxent:SetEffectName(impactfx_effectname)
impactfxent:SetColorInfo(impactfx_colorinfo)
impactfxent:SetUtilEffectInfo(impactfx_utileffectinfo)
impactfxent:SetAttachNum(0)
end
if CLIENT then
if string.StartWith( impactfx_effectname, "!UTILEFFECT!" ) then
//Create a util effect
//Unfortunately, we have to do all of this every single time the effect repeats, because if we do it in Initialize instead, a whole bunch of stuff doesn't work properly
local effectscale = impactfx_utileffectinfo.x
local effectmagnitude = impactfx_utileffectinfo.y
local effectradius = impactfx_utileffectinfo.z
local impacteffectdata = EffectData()
impacteffectdata:SetEntity(impactfxent)
//if ( string.find(impactfx_effectname, "Tracer", 0, true) != nil ) then impacteffectdata:SetScale(5000) else impacteffectdata:SetScale(effectscale) end //for tracer effects, scale is the speed of the bullet, so we need to keep this high; useless for an impact effect
impacteffectdata:SetScale(effectscale)
impacteffectdata:SetMagnitude(effectmagnitude)
impacteffectdata:SetRadius(effectradius)
//flags can be set by typing !FLAG#! at the end of the effect name
impacteffectdata:SetFlags( 0 )
if string.EndsWith( impactfx_effectname, "!" ) then
if string.find( impactfx_effectname, "!FLAG1!" ) then impacteffectdata:SetFlags( 1 ) impactfx_effectname = string.Replace( impactfx_effectname, "!FLAG1!", "" ) end
if string.find( impactfx_effectname, "!FLAG2!" ) then impacteffectdata:SetFlags( 2 ) impactfx_effectname = string.Replace( impactfx_effectname, "!FLAG2!", "" ) end
if string.find( impactfx_effectname, "!FLAG3!" ) then impacteffectdata:SetFlags( 3 ) impactfx_effectname = string.Replace( impactfx_effectname, "!FLAG3!", "" ) end
if string.find( impactfx_effectname, "!FLAG4!" ) then impacteffectdata:SetFlags( 4 ) impactfx_effectname = string.Replace( impactfx_effectname, "!FLAG4!", "" ) end
if string.find( impactfx_effectname, "!FLAG5!" ) then impacteffectdata:SetFlags( 5 ) impactfx_effectname = string.Replace( impactfx_effectname, "!FLAG5!", "" ) end
if string.find( impactfx_effectname, "!FLAG6!" ) then impacteffectdata:SetFlags( 6 ) impactfx_effectname = string.Replace( impactfx_effectname, "!FLAG6!", "" ) end
if string.find( impactfx_effectname, "!FLAG7!" ) then impacteffectdata:SetFlags( 7 ) impactfx_effectname = string.Replace( impactfx_effectname, "!FLAG7!", "" ) end
if string.find( impactfx_effectname, "!FLAG8!" ) then impacteffectdata:SetFlags( 8 ) impactfx_effectname = string.Replace( impactfx_effectname, "!FLAG8!", "" ) end
if string.find( impactfx_effectname, "!FLAG9!" ) then impacteffectdata:SetFlags( 9 ) impactfx_effectname = string.Replace( impactfx_effectname, "!FLAG9!", "" ) end
end
//colors can also be set the same way
impacteffectdata:SetColor(0)
if string.EndsWith( impactfx_effectname, "!" ) then
if string.find( impactfx_effectname, "!COLOR1!" ) then impacteffectdata:SetColor( 1 ) impactfx_effectname = string.Replace( impactfx_effectname, "!COLOR1!", "" ) end
if string.find( impactfx_effectname, "!COLOR2!" ) then impacteffectdata:SetColor( 2 ) impactfx_effectname = string.Replace( impactfx_effectname, "!COLOR2!", "" ) end
if string.find( impactfx_effectname, "!COLOR3!" ) then impacteffectdata:SetColor( 3 ) impactfx_effectname = string.Replace( impactfx_effectname, "!COLOR3!", "" ) end
if string.find( impactfx_effectname, "!COLOR4!" ) then impacteffectdata:SetColor( 4 ) impactfx_effectname = string.Replace( impactfx_effectname, "!COLOR4!", "" ) end
if string.find( impactfx_effectname, "!COLOR5!" ) then impacteffectdata:SetColor( 5 ) impactfx_effectname = string.Replace( impactfx_effectname, "!COLOR5!", "" ) end
if string.find( impactfx_effectname, "!COLOR6!" ) then impacteffectdata:SetColor( 6 ) impactfx_effectname = string.Replace( impactfx_effectname, "!COLOR6!", "" ) end
if string.find( impactfx_effectname, "!COLOR7!" ) then impacteffectdata:SetColor( 7 ) impactfx_effectname = string.Replace( impactfx_effectname, "!COLOR7!", "" ) end
if string.find( impactfx_effectname, "!COLOR8!" ) then impacteffectdata:SetColor( 8 ) impactfx_effectname = string.Replace( impactfx_effectname, "!COLOR8!", "" ) end
if string.find( impactfx_effectname, "!COLOR9!" ) then impacteffectdata:SetColor( 9 ) impactfx_effectname = string.Replace( impactfx_effectname, "!COLOR9!", "" ) end
end
//dumb situational crap
if string.find( string.lower(impactfx_effectname), "shakeropes" ) then impacteffectdata:SetMagnitude( effectmagnitude * 20 ) end
if string.find( string.lower(impactfx_effectname), "thumperdust" ) then impacteffectdata:SetScale( effectscale * 50 ) end
if string.find( string.lower(impactfx_effectname), "bloodspray" ) then impacteffectdata:SetScale( effectscale * 4 ) end
impacteffectdata:SetStart( impactfxent:GetPos() )
impacteffectdata:SetOrigin( impactfxent:GetPos() )
impacteffectdata:SetAngles( impactfxent:GetAngles() )
impacteffectdata:SetNormal( impactfxent:GetAngles():Forward() )
util.Effect( string.Replace( impactfx_effectname, "!UTILEFFECT!", "" ), impacteffectdata )
else
//Create a particlesystem effect
local clrtb = nil
if impactfx_colorinfo == Vector(0,0,0) then
//MsgN("color = false")
else
//MsgN("color = true")
clrtb = { position = impactfx_colorinfo }
end
local impactcpointtable = {}
impactcpointtable[1] = { entity = impactfxent, attachtype = PATTACH_ABSORIGIN_FOLLOW }
for i = 2, 64 do
if clrtb then
impactcpointtable[i] = clrtb
else
impactcpointtable[i] = impactcpointtable[1]
end
end
impactfxent:CreateParticleEffect(impactfx_effectname,impactcpointtable)
end
end
end
ent:Remove()
end
timer.Simple(projent_lifetime_prehit, function() if IsValid(proj) then projexpire(proj) end; end)
local function projcollide(entity, data)
if IsValid(entity) then
if entity.HasHitSomething then return end //there's no reason to call this more than once
entity.HasHitSomething = true
if projent_lifetime_posthit == 0 then
//if lifetime_posthit is 0, then move the impactfx to the pos and angle of impact -
//we still need to use a timer because directly calling ent:Remove() in a PhysicsCollide callback crashes the game
timer.Simple(0, function() if IsValid(proj) then projexpire(proj, data.HitPos, -data.HitNormal:Angle()) end; end)
else
timer.Simple(projent_lifetime_posthit, function() if IsValid(proj) then projexpire(proj) end; end)
end
end
end
if CLIENT then
proj:AddCallback("PhysicsCollide", projcollide)
else
proj.PhysicsCollide = projcollide //AddCallback inexplicably won't work on our sent we're using serverside, but overriding its physicscollide function seems to do it
end
end
//numpad functions
if SERVER then
local function NumpadPress( pl, ent )
if ( !ent || ent == NULL ) then return end
if ( ent:GetToggle() ) then
if ent:GetActive() == false then
ent:SetActive(true)
ent:SetNumpadState("on")
else
ent:SetActive(false)
ent:SetNumpadState("off")
end
else
ent:SetActive( true )
ent:SetNumpadState("on")
end
end
local function NumpadRelease( pl, ent )
if ( !ent || ent == NULL ) then return end
if ( ent:GetToggle() ) then return end
ent:SetActive(false)
ent:SetNumpadState("off")
end
numpad.Register( "Particle_Press", NumpadPress )
numpad.Register( "Particle_Release", NumpadRelease )
end
//don't duplicate this
duplicator.RegisterEntityClass( "particlecontroller_proj", function( ply, data )
end, "Data" )