Smoke Effect (Particle Emitter)

Im pretty new to lua, Ive got a script that generates smoke and it works okay, except it only shows client side.




   if CLIENT then
   local ply = LocalPlayer()
   smokeParticle = ParticleEmitter( ply:GetPos() )
   SmokeTable = 
   {
   smokeParticle:Add( Model("particle/particle_noisesphere") , ply:GetPos()),
   smokeParticle:Add( Model("particle/particle_noisesphere") , ply:GetPos()),
   smokeParticle:Add( Model("particle/particle_noisesphere") , ply:GetPos())
   }
   for i=1,3 do
            local gray = math.random(75, 200)
            SmokeTable*:SetColor(gray, gray, gray)
            SmokeTable*:SetStartAlpha(255)
            SmokeTable*:SetEndAlpha(200)
            SmokeTable*:SetVelocity(VectorRand() * math.Rand(900, 1300))
            SmokeTable*:SetLifeTime(0)
            
            SmokeTable*:SetDieTime(math.Rand(50, 70))

            SmokeTable*:SetStartSize(math.random(140, 150))
            SmokeTable*:SetEndSize(math.random(1, 40))
            SmokeTable*:SetRoll(math.random(-180, 180))
            SmokeTable*:SetRollDelta(math.Rand(-0.1, 0.1))
            SmokeTable*:SetAirResistance(600)

            SmokeTable*:SetCollide(true)
            SmokeTable*:SetBounce(0.4)

            SmokeTable*:SetLighting(false)
	end
	
   print("lol2")
   end
    ParticleEffectAttach(Model("particle/particle_noisesphere"),PATTACH_ABSORIGIN_FOLLOW,smokeParticle,0)	


Can anyone help?

That’s normal…

You’ll need to comunicate an information saying other clients to start particle emitter.

For example, on server side entity do self:SetNWBool(“DoSmoke”, true)

Then on client check if that NWBool is true and spawn particles if that’s the case.

Second way : your particle emiter is desined to be static (always emits, never stops), then you can just spawn your particles.

I assume in your case, it’s an effect you want, so you can simply use NW bools…

Can you elaborate? I dont really understand.
Edit
Can I not just attach i to an entity ?

I changed the code around , however Ive got a new error :

This is the new code :



if(CLIENT) then
function SWEP:CreateSmoke()
		
		local smokeParticle = ParticleEmitter( self.Owner:GetPos() )
			SmokeTable = 
	   {
	   smokeParticle:Add( Model("particle/particle_noisesphere") , self.Owner:GetPos()),
	   smokeParticle:Add( Model("particle/particle_noisesphere") , self.Owner:GetPos()),
	   smokeParticle:Add( Model("particle/particle_noisesphere") , self.Owner:GetPos())
	   }
	   for i=1,3 do
				local gray = math.random(75, 200)
				SmokeTable*:SetColor(gray, gray, gray)
				SmokeTable*:SetStartAlpha(255)
				SmokeTable*:SetEndAlpha(200)
				SmokeTable*:SetVelocity(VectorRand() * math.Rand(900, 1300))
				SmokeTable*:SetLifeTime(0)
				
				SmokeTable*:SetDieTime(math.Rand(50, 70))

				SmokeTable*:SetStartSize(math.random(140, 150))
				SmokeTable*:SetEndSize(math.random(1, 40))
				SmokeTable*:SetRoll(math.random(-180, 180))
				SmokeTable*:SetRollDelta(math.Rand(-0.1, 0.1))
				SmokeTable*:SetAirResistance(600)

				SmokeTable*:SetCollide(true)
				SmokeTable*:SetBounce(0.4)

				SmokeTable*:SetLighting(false)
		end	
		print("test")
	end
end


The function above is declared in the code here :



function SWEP:StabKill(tr, spos, sdest)
   local target = tr.Entity

   local dmg = DamageInfo()
   dmg:SetDamage(2000)
   dmg:SetAttacker(self.Owner)
   dmg:SetInflictor(self.Weapon or self)
   dmg:SetDamageForce(self.Owner:GetAimVector())
   dmg:SetDamagePosition(self.Owner:GetPos())
   dmg:SetDamageType(DMG_SLASH)

   -- now that we use a hull trace, our hitpos is guaranteed to be
   -- terrible, so try to make something of it with a separate trace and
   -- hope our effect_fn trace has more luck

   -- first a straight up line trace to see if we aimed nicely
   local retr = util.TraceLine({start=spos, endpos=sdest, filter=self.Owner, mask=MASK_SHOT_HULL})

   -- if that fails, just trace to worldcenter so we have SOMETHING
   if retr.Entity != target then
      local center = target:LocalToWorld(target:OBBCenter())
      retr = util.TraceLine({start=spos, endpos=center, filter=self.Owner, mask=MASK_SHOT_HULL})
   end


   -- create knife effect creation fn
   local bone = retr.PhysicsBone
   local pos = retr.HitPos
   local norm = tr.Normal
   local ang = Angle(-28,0,0) + norm:Angle()
   ang:RotateAroundAxis(ang:Right(), -90)
   pos = pos - (ang:Forward() * 7)

   local prints = self.fingerprints
   local ignore = self.Owner

   target.effect_fn = function(rag)
                         -- we might find a better location
                         local rtr = util.TraceLine({start=pos, endpos=pos + norm * 40, filter=ignore, mask=MASK_SHOT_HULL})

                         if IsValid(rtr.Entity) and rtr.Entity == rag then
                            bone = rtr.PhysicsBone
                            pos = rtr.HitPos
                            ang = Angle(-28,0,0) + rtr.Normal:Angle()
                            ang:RotateAroundAxis(ang:Right(), -90)
                            pos = pos - (ang:Forward() * 10)

                         end

                         local knife = ents.Create("prop_physics")
                         knife:SetModel("models/weapons/w_knife_t.mdl")
                         knife:SetPos(pos)
                         knife:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
                         knife:SetAngles(ang)
                         knife.CanPickup = false

                         knife:Spawn()

                         local phys = knife:GetPhysicsObject()
                         if IsValid(phys) then
                            phys:EnableCollisions(false)
                         end

                         constraint.Weld(rag, knife, bone, 0, 0, true)

                         -- need to close over knife in order to keep a valid ref to it
                         rag:CallOnRemove("ttt_knife_cleanup", function() SafeRemoveEntity(knife) end)
                      end


   -- seems the spos and sdest are purely for effects/forces?
   target:DispatchTraceAttack(dmg, spos + (self.Owner:GetAimVector() * 3), sdest)

   -- target appears to die right there, so we could theoretically get to
   -- the ragdoll in here...

   self:Remove()
end


Can you post the whole knife file in code tags? I have a feeling that you’re not calling it serverside



AddCSLuaFile()

SWEP.HoldType = "knife"

if CLIENT then

   SWEP.PrintName    = "knife_name"
   SWEP.Slot         = 6

   SWEP.ViewModelFlip = false

   SWEP.EquipMenuData = {
      type = "item_weapon",
      desc = "knife_desc"
   };

   SWEP.Icon = "vgui/ttt/icon_knife"
   SWEP.IconLetter = "j"
end

SWEP.Base               = "weapon_tttbase"

SWEP.UseHands			= true
SWEP.ViewModelFlip		= false
SWEP.ViewModelFOV		= 54
SWEP.ViewModel          = "models/weapons/cstrike/c_knife_t.mdl"
SWEP.WorldModel         = "models/weapons/w_knife_t.mdl"

SWEP.DrawCrosshair      = false
SWEP.Primary.Damage         = 50
SWEP.Primary.ClipSize       = -1
SWEP.Primary.DefaultClip    = -1
SWEP.Primary.Automatic      = true
SWEP.Primary.Delay = 1.1
SWEP.Primary.Ammo       = "none"
SWEP.Secondary.ClipSize     = -1
SWEP.Secondary.DefaultClip  = -1
SWEP.Secondary.Automatic    = true
SWEP.Secondary.Ammo     = "none"
SWEP.Secondary.Delay = 1.4

SWEP.Kind = WEAPON_EQUIP
SWEP.CanBuy = {ROLE_TRAITOR} -- only traitors can buy
SWEP.LimitedStock = true -- only buyable once
SWEP.WeaponID = AMMO_KNIFE

SWEP.IsSilent = true

-- Pull out faster than standard guns
SWEP.DeploySpeed = 2

function SWEP:PrimaryAttack()
   self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
   self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )

   if not IsValid(self.Owner) then return end

   self.Owner:LagCompensation(true)

   local spos = self.Owner:GetShootPos()
   local sdest = spos + (self.Owner:GetAimVector() * 70)

   local kmins = Vector(1,1,1) * -10
   local kmaxs = Vector(1,1,1) * 10

   local tr = util.TraceHull({start=spos, endpos=sdest, filter=self.Owner, mask=MASK_SHOT_HULL, mins=kmins, maxs=kmaxs})

   -- Hull might hit environment stuff that line does not hit
   if not IsValid(tr.Entity) then
      tr = util.TraceLine({start=spos, endpos=sdest, filter=self.Owner, mask=MASK_SHOT_HULL})
   end

   local hitEnt = tr.Entity

   -- effects
   if IsValid(hitEnt) then
      self.Weapon:SendWeaponAnim( ACT_VM_HITCENTER )

      local edata = EffectData()
      edata:SetStart(spos)
      edata:SetOrigin(tr.HitPos)
      edata:SetNormal(tr.Normal)
      edata:SetEntity(hitEnt)

      if hitEnt:IsPlayer() or hitEnt:GetClass() == "prop_ragdoll" then
         util.Effect("BloodImpact", edata)
      end
   else
      self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER )
   end

   if SERVER then
      self.Owner:SetAnimation( PLAYER_ATTACK1 )
	  	
   end
 	
   if SERVER and tr.Hit and tr.HitNonWorld and IsValid(hitEnt) then
      if hitEnt:IsPlayer() then	
         -- knife damage is never karma'd, so don't need to take that into
         -- account we do want to avoid rounding error strangeness caused by
         -- other damage scaling, causing a death when we don't expect one, so
         -- when the target's health is close to kill-point we just kill
         if hitEnt:Health() < (self.Primary.Damage + 10) then
            self:StabKill(tr, spos, sdest)
         else
            local dmg = DamageInfo()
            dmg:SetDamage(100	)
            dmg:SetAttacker(self.Owner)
            dmg:SetInflictor(self.Weapon or self)
            dmg:SetDamageForce(self.Owner:GetAimVector() * 5)
            dmg:SetDamagePosition(self.Owner:GetPos())
            dmg:SetDamageType(DMG_SLASH)
			self.Owner:StripWeapon(self.WeaponClass	)
            hitEnt:DispatchTraceAttack(dmg, spos + (self.Owner:GetAimVector() * 3), sdest)
         end
      end
   end	

   self.Owner:LagCompensation(false)
end

	function SWEP:StabKill(tr, spos, sdest)
	   local target = tr.Entity

	   local dmg = DamageInfo()
	   dmg:SetDamage(2000)
	   dmg:SetAttacker(self.Owner)
	   dmg:SetInflictor(self.Weapon or self)
	   dmg:SetDamageForce(self.Owner:GetAimVector())
	   dmg:SetDamagePosition(self.Owner:GetPos())
	   dmg:SetDamageType(DMG_SLASH)

	   -- now that we use a hull trace, our hitpos is guaranteed to be
	   -- terrible, so try to make something of it with a separate trace and
	   -- hope our effect_fn trace has more luck

	   -- first a straight up line trace to see if we aimed nicely
	   local retr = util.TraceLine({start=spos, endpos=sdest, filter=self.Owner, mask=MASK_SHOT_HULL})

	   -- if that fails, just trace to worldcenter so we have SOMETHING
	   if retr.Entity != target then
		  local center = target:LocalToWorld(target:OBBCenter())
		  retr = util.TraceLine({start=spos, endpos=center, filter=self.Owner, mask=MASK_SHOT_HULL})
	   end


	   -- create knife effect creation fn
	   local bone = retr.PhysicsBone
	   local pos = retr.HitPos
	   local norm = tr.Normal
	   local ang = Angle(-28,0,0) + norm:Angle()
	   ang:RotateAroundAxis(ang:Right(), -90)
	   pos = pos - (ang:Forward() * 7)

	   local prints = self.fingerprints
	   local ignore = self.Owner

	   target.effect_fn = function(rag)
							 -- we might find a better location
							 local rtr = util.TraceLine({start=pos, endpos=pos + norm * 40, filter=ignore, mask=MASK_SHOT_HULL})

							 if IsValid(rtr.Entity) and rtr.Entity == rag then
								bone = rtr.PhysicsBone
								pos = rtr.HitPos
								ang = Angle(-28,0,0) + rtr.Normal:Angle()
								ang:RotateAroundAxis(ang:Right(), -90)
								pos = pos - (ang:Forward() * 10)

							 end

							 local knife = ents.Create("prop_physics")
							 knife:SetModel("models/weapons/w_knife_t.mdl")
							 knife:SetPos(pos)
							 knife:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
							 knife:SetAngles(ang)
							 knife.CanPickup = false

							 knife:Spawn()

							 local phys = knife:GetPhysicsObject()
							 if IsValid(phys) then
								phys:EnableCollisions(false)
							 end

							 constraint.Weld(rag, knife, bone, 0, 0, true)

							 -- need to close over knife in order to keep a valid ref to it
							 rag:CallOnRemove("ttt_knife_cleanup", function() SafeRemoveEntity(knife) end)
						  end


	   -- seems the spos and sdest are purely for effects/forces?
	   target:DispatchTraceAttack(dmg, spos + (self.Owner:GetAimVector() * 3), sdest)

	   -- target appears to die right there, so we could theoretically get to
	   -- the ragdoll in here...

	   self:Remove()
	end

function SWEP:SecondaryAttack()
   self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
   self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )


   self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER )

   if SERVER then
      local ply = self.Owner
      if not IsValid(ply) then return end

      ply:SetAnimation( PLAYER_ATTACK1 )

      local ang = ply:EyeAngles()

      if ang.p < 90 then
         ang.p = -10 + ang.p * ((90 + 10) / 90)
      else
         ang.p = 360 - ang.p
         ang.p = -10 + ang.p * -((90 + 10) / 90)
      end

      local vel = math.Clamp((90 - ang.p) * 5.5, 550, 800)

      local vfw = ang:Forward()
      local vrt = ang:Right()

      local src = ply:GetPos() + (ply:Crouching() and ply:GetViewOffsetDucked() or ply:GetViewOffset())

      src = src + (vfw * 1) + (vrt * 3)

      local thr = vfw * vel + ply:GetVelocity()

      local knife_ang = Angle(-28,0,0) + ang
      knife_ang:RotateAroundAxis(knife_ang:Right(), -90)

      local knife = ents.Create("ttt_knife_proj")
      if not IsValid(knife) then return end
      knife:SetPos(src)
      knife:SetAngles(knife_ang)

      knife:Spawn()

      knife.Damage = self.Primary.Damage

      knife:SetOwner(ply)

      local phys = knife:GetPhysicsObject()
      if IsValid(phys) then
         phys:SetVelocity(thr)
         phys:AddAngleVelocity(Vector(0, 1500, 0))
         phys:Wake()
      end

      self:Remove()
   end
end

function SWEP:Equip()
   self.Weapon:SetNextPrimaryFire( CurTime() + (self.Primary.Delay * 1.5) )
   self.Weapon:SetNextSecondaryFire( CurTime() + (self.Secondary.Delay * 1.5) )
end

function SWEP:PreDrop()
   -- for consistency, dropped knife should not have DNA/prints
   self.fingerprints = {}
end

function SWEP:OnRemove()
   if CLIENT and IsValid(self.Owner) and self.Owner == LocalPlayer() and self.Owner:Alive() then
      RunConsoleCommand("lastinv")
   end
end

if CLIENT then
   function SWEP:DrawHUD()
      local tr = self.Owner:GetEyeTrace(MASK_SHOT)

      if tr.HitNonWorld and IsValid(tr.Entity) and tr.Entity:IsPlayer()
         and tr.Entity:Health() < (self.Primary.Damage + 10) then

         local x = ScrW() / 2.0
         local y = ScrH() / 2.0

         surface.SetDrawColor(255, 0, 0, 255)

         local outer = 20
         local inner = 10
         surface.DrawLine(x - outer, y - outer, x - inner, y - inner)
         surface.DrawLine(x + outer, y + outer, x + inner, y + inner)

         surface.DrawLine(x - outer, y + outer, x - inner, y + inner)
         surface.DrawLine(x + outer, y - outer, x + inner, y - inner)

         draw.SimpleText("INSTANT KILL", "TabLarge", x, y - 30, COLOR_RED, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM)
      end

      return self.BaseClass.DrawHUD(self)
   end
end


Hold on I’ll start RealisticRoleplay with your weapon to see exactly where the problem is.

[editline]31st March 2015[/editline]

Your weapon has so much errors ! I got a warning everytime I hit an entity : “Trying to start a new lag compensation session while one is already active!”

And it crashs at line 114 : attempt to call method GetAimVector (a nil value).

[editline]31st March 2015[/editline]

Succeeded to correct errors and even warning, however it does not make any damage to the pointed entity.

[editline]31st March 2015[/editline]

I got that which no longer creates lua errors however I can’t test the Right-Click, because I’m not on a TTT server so it says attempted to create unknown entity type ttt_knife_proj



AddCSLuaFile()

SWEP.HoldType = "knife"

if CLIENT then

   SWEP.PrintName    = "knife_name"
   SWEP.Slot         = 6

   SWEP.ViewModelFlip = false

   SWEP.EquipMenuData = {
      type = "item_weapon",
      desc = "knife_desc"
   };

   SWEP.Icon = "vgui/ttt/icon_knife"
   SWEP.IconLetter = "j"
end

SWEP.Base               = "weapon_base"

SWEP.UseHands			= true
SWEP.ViewModelFlip		= false
SWEP.ViewModelFOV		= 54
SWEP.ViewModel          = "models/weapons/cstrike/c_knife_t.mdl"
SWEP.WorldModel         = "models/weapons/w_knife_t.mdl"

SWEP.DrawCrosshair      = false
SWEP.Primary.Damage         = 50
SWEP.Primary.ClipSize       = -1
SWEP.Primary.DefaultClip    = -1
SWEP.Primary.Automatic      = true
SWEP.Primary.Delay = 1.1
SWEP.Primary.Ammo       = "none"
SWEP.Secondary.ClipSize     = -1
SWEP.Secondary.DefaultClip  = -1
SWEP.Secondary.Automatic    = true
SWEP.Secondary.Ammo     = "none"
SWEP.Secondary.Delay = 1.4

SWEP.Kind = WEAPON_EQUIP
SWEP.CanBuy = {ROLE_TRAITOR} -- only traitors can buy
SWEP.LimitedStock = true -- only buyable once
SWEP.WeaponID = AMMO_KNIFE

SWEP.IsSilent = true

-- Pull out faster than standard guns
SWEP.DeploySpeed = 2

function SWEP:PrimaryAttack()
   self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
   self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )

   if not IsValid(self.Owner) then return end

   --self.Owner:LagCompensation(true)

   local spos = self.Owner:GetShootPos()
   local sdest = spos + (self.Owner:GetAimVector() * 70)

   local kmins = Vector(1,1,1) * -10
   local kmaxs = Vector(1,1,1) * 10

   local tr = util.TraceHull({start=spos, endpos=sdest, filter=self.Owner, mask=MASK_SHOT_HULL, mins=kmins, maxs=kmaxs})

   -- Hull might hit environment stuff that line does not hit
   if not IsValid(tr.Entity) then
      tr = util.TraceLine({start=spos, endpos=sdest, filter=self.Owner, mask=MASK_SHOT_HULL})
   end

   local hitEnt = tr.Entity

   -- effects
   if IsValid(hitEnt) then
      self.Weapon:SendWeaponAnim( ACT_VM_HITCENTER )

      local edata = EffectData()
      edata:SetStart(spos)
      edata:SetOrigin(tr.HitPos)
      edata:SetNormal(tr.Normal)
      edata:SetEntity(hitEnt)

      if hitEnt:IsPlayer() or hitEnt:GetClass() == "prop_ragdoll" then
         util.Effect("BloodImpact", edata)
      end
   else
      self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER )
   end

   if SERVER then
      self.Owner:SetAnimation( PLAYER_ATTACK1 )
	  	
   end
 	
   if SERVER and tr.Hit and tr.HitNonWorld and IsValid(hitEnt) then
      if hitEnt:IsPlayer() then	
         -- knife damage is never karma'd, so don't need to take that into
         -- account we do want to avoid rounding error strangeness caused by
         -- other damage scaling, causing a death when we don't expect one, so
         -- when the target's health is close to kill-point we just kill
         if hitEnt:Health() < (self.Primary.Damage + 10) then
            self:StabKill(tr, spos, sdest)
         else
            local dmg = DamageInfo()
            dmg:SetDamage(100	)
            dmg:SetAttacker(self.Owner)
            dmg:SetInflictor(self.Weapon or self)
            dmg:SetDamageForce(self.Owner:GetAimVector() * 5)
            dmg:SetDamagePosition(self.Owner:GetPos())
            dmg:SetDamageType(DMG_SLASH)
			self.Owner:StripWeapon("weapon_knife")
			if (IsValid(self.Owner)) then
				hitEnt:DispatchTraceAttack(dmg, spos + (self.Owner:GetAimVector() * 3), sdest)
			end
         end
      end
   end	

   --self.Owner:LagCompensation(false)
end

function SWEP:StabKill(tr, spos, sdest)
	local target = tr.Entity

	local dmg = DamageInfo()
	dmg:SetDamage(2000)
	dmg:SetAttacker(self.Owner)
	dmg:SetInflictor(self.Weapon or self)
	dmg:SetDamageForce(self.Owner:GetAimVector())
	dmg:SetDamagePosition(self.Owner:GetPos())
	dmg:SetDamageType(DMG_SLASH)

	-- now that we use a hull trace, our hitpos is guaranteed to be
	-- terrible, so try to make something of it with a separate trace and
	-- hope our effect_fn trace has more luck
	
	-- first a straight up line trace to see if we aimed nicely
	local retr = util.TraceLine({start=spos, endpos=sdest, filter=self.Owner, mask=MASK_SHOT_HULL})

	-- if that fails, just trace to worldcenter so we have SOMETHING
	if retr.Entity != target then
		local center = target:LocalToWorld(target:OBBCenter())
		retr = util.TraceLine({start=spos, endpos=center, filter=self.Owner, mask=MASK_SHOT_HULL})
	end


	-- create knife effect creation fn
	local bone = retr.PhysicsBone
	local pos = retr.HitPos
	local norm = tr.Normal
	local ang = Angle(-28, 0, 0) + norm:Angle()
	ang:RotateAroundAxis(ang:Right(), -90)
	pos = pos - (ang:Forward() * 7)

	local prints = self.fingerprints
	local ignore = self.Owner

	target.effect_fn = function(rag)
		-- we might find a better location
		local rtr = util.TraceLine({start=pos, endpos=pos + norm * 40, filter=ignore, mask=MASK_SHOT_HULL})

		if IsValid(rtr.Entity) and rtr.Entity == rag then
			bone = rtr.PhysicsBone
			pos = rtr.HitPos
			ang = Angle(-28,0,0) + rtr.Normal:Angle()
			ang:RotateAroundAxis(ang:Right(), -90)
			pos = pos - (ang:Forward() * 10)
		end

		local knife = ents.Create("prop_physics")
		knife:SetModel("models/weapons/w_knife_t.mdl")
		knife:SetPos(pos)
		knife:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
		knife:SetAngles(ang)
		knife.CanPickup = false

		knife:Spawn()

		local phys = knife:GetPhysicsObject()
		if IsValid(phys) then
			phys:EnableCollisions(false)
		end

		constraint.Weld(rag, knife, bone, 0, 0, true)

		-- need to close over knife in order to keep a valid ref to it
		rag:CallOnRemove("ttt_knife_cleanup", function() SafeRemoveEntity(knife) end)
	end


	-- seems the spos and sdest are purely for effects/forces?
	target:DispatchTraceAttack(dmg, spos + (self.Owner:GetAimVector() * 3), sdest)

	-- target appears to die right there, so we could theoretically get to
	-- the ragdoll in here...

	self:Remove()
end

function SWEP:SecondaryAttack()
   self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
   self.Weapon:SetNextSecondaryFire( CurTime() + self.Secondary.Delay )


   self.Weapon:SendWeaponAnim( ACT_VM_MISSCENTER )

   if SERVER then
      local ply = self.Owner
      if not IsValid(ply) then return end

      ply:SetAnimation( PLAYER_ATTACK1 )

      local ang = ply:EyeAngles()

      if ang.p < 90 then
         ang.p = -10 + ang.p * ((90 + 10) / 90)
      else
         ang.p = 360 - ang.p
         ang.p = -10 + ang.p * -((90 + 10) / 90)
      end

      local vel = math.Clamp((90 - ang.p) * 5.5, 550, 800)

      local vfw = ang:Forward()
      local vrt = ang:Right()

      local src = ply:GetPos() + (ply:Crouching() and ply:GetViewOffsetDucked() or ply:GetViewOffset())

      src = src + (vfw * 1) + (vrt * 3)

      local thr = vfw * vel + ply:GetVelocity()

      local knife_ang = Angle(-28,0,0) + ang
      knife_ang:RotateAroundAxis(knife_ang:Right(), -90)

      local knife = ents.Create("ttt_knife_proj")
      if not IsValid(knife) then return end
      knife:SetPos(src)
      knife:SetAngles(knife_ang)

      knife:Spawn()

      knife.Damage = self.Primary.Damage

      knife:SetOwner(ply)

      local phys = knife:GetPhysicsObject()
      if IsValid(phys) then
         phys:SetVelocity(thr)
         phys:AddAngleVelocity(Vector(0, 1500, 0))
         phys:Wake()
      end

      self:Remove()
   end
end

function SWEP:Equip()
   self.Weapon:SetNextPrimaryFire( CurTime() + (self.Primary.Delay * 1.5) )
   self.Weapon:SetNextSecondaryFire( CurTime() + (self.Secondary.Delay * 1.5) )
end

function SWEP:PreDrop()
   -- for consistency, dropped knife should not have DNA/prints
   self.fingerprints = {}
end

function SWEP:OnRemove()
   if CLIENT and IsValid(self.Owner) and self.Owner == LocalPlayer() and self.Owner:Alive() then
      RunConsoleCommand("lastinv")
   end
end

if CLIENT then
   function SWEP:DrawHUD()
      local tr = self.Owner:GetEyeTrace(MASK_SHOT)

      if tr.HitNonWorld and IsValid(tr.Entity) and tr.Entity:IsPlayer()
         and tr.Entity:Health() < (self.Primary.Damage + 10) then

         local x = ScrW() / 2.0
         local y = ScrH() / 2.0

         surface.SetDrawColor(255, 0, 0, 255)

         local outer = 20
         local inner = 10
         surface.DrawLine(x - outer, y - outer, x - inner, y - inner)
         surface.DrawLine(x + outer, y + outer, x + inner, y + inner)

         surface.DrawLine(x - outer, y + outer, x - inner, y + inner)
         surface.DrawLine(x + outer, y - outer, x + inner, y - inner)

         draw.SimpleText("INSTANT KILL", "TabLarge", x, y - 30, COLOR_RED, TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM)
      end

      return self.BaseClass.DrawHUD(self)
   end
end