

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"

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         = 300

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 + 100) then

            self:StabKill(tr, spos, sdest)

         else

            local dmg = DamageInfo()

            dmg:SetDamage(self.Primary.Damage)

            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)



            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 + 100) 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





