Guest User

Untitled

a guest
Nov 10th, 2020
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.76 KB | None | 0 0
  1.  
  2. AddCSLuaFile()
  3.  
  4. SWEP.PrintName = "The Specialists - Kung Fu"
  5. SWEP.Author = "Knee"
  6. SWEP.Purpose = "The melee weapon from the popular Half-Life mod: The Specialists"
  7.  
  8. SWEP.Slot = 0
  9. SWEP.SlotPos = 4
  10.  
  11. SWEP.Spawnable = true
  12.  
  13. SWEP.ViewModel = Model( "models/weapons/c_arms.mdl" )
  14. SWEP.WorldModel = ""
  15. SWEP.ViewModelFOV = 54
  16. SWEP.UseHands = true
  17.  
  18. SWEP.Primary.ClipSize = -1
  19. SWEP.Primary.DefaultClip = -1
  20. SWEP.Primary.Automatic = true
  21. SWEP.Primary.Ammo = "none"
  22.  
  23. SWEP.Secondary.ClipSize = -1
  24. SWEP.Secondary.DefaultClip = -1
  25. SWEP.Secondary.Automatic = true
  26. SWEP.Secondary.Ammo = "none"
  27.  
  28. SWEP.DrawAmmo = false
  29.  
  30. SWEP.HitDistance = 48
  31.  
  32. local SwingSound = Sound( "WeaponFrag.Throw" )
  33. local HitSound = Sound( "Flesh.ImpactHard" )
  34.  
  35. local flLastDuck = 0
  36. local flNextSwing = 0
  37. local iCurrentSwing = 0
  38.  
  39.  
  40. -- Sequence of punches to be followed while holding down attack button
  41. local eSwing = {
  42.     RIGHT_PUNCH1 = 1,
  43.     LEFT_PUNCH1  = 2,
  44.     LEFT_PUNCH2  = 3,
  45.     LEFT_PUNCH3  = 4,
  46.     RIGHT_PUNCH2 = 5
  47. }
  48.  
  49. -- Grouping together information about punching sequences
  50. SwingData = {strAnimation = "null", flDamage = 0, flNextSwing = 0}
  51.  
  52. function SwingData:create(strAnim, flDmg, flNxtSwng)
  53.  
  54.     self.strAnimation   = strAnim
  55.     self.flDamage       = flDmg
  56.     self.flNextSwing    = flNxtSwng
  57.    
  58. end
  59.  
  60. local arrPunchData = {
  61.     sdPunch1 = SwingData:create("fists_right",  20.0, 0.45),
  62.     sdPunch2 = SwingData:create("fists_left" ,  15.0, 0.23),
  63.     sdPunch3 = SwingData:create("fists_left" ,  15.0, 0.23),
  64.     sdPunch4 = SwingData:create("fists_left" ,  15.0, 0.23),
  65.     sdPunch5 = SwingData:create("fists_right",  30.0, 0.55)
  66. }
  67.  
  68. function SWEP:Initialize()
  69.  
  70.     self:SetHoldType( "fist" )
  71.  
  72. end
  73.  
  74. function SWEP:SetupDataTables()
  75.  
  76.     self:NetworkVar( "Float", 0, "NextMeleeAttack" )
  77.     self:NetworkVar( "Float", 1, "NextIdle" )
  78.     self:NetworkVar( "Int", 2, "Combo" )
  79.  
  80. end
  81.  
  82. function SWEP:UpdateNextIdle()
  83.  
  84.     local vm = self.Owner:GetViewModel()
  85.     self:SetNextIdle( CurTime() + vm:SequenceDuration() / vm:GetPlaybackRate() )
  86.  
  87. end
  88.  
  89. function SWEP:PrimaryAttack( right )
  90.    
  91.     self.Owner:SetAnimation( PLAYER_ATTACK1 )
  92.    
  93.     local strAnimation      = "fists_left"
  94.     local flDamage          = 0 -- [float] how much damage is down to a target
  95.     local flMeleeCooldown   = 0 -- [seconds] cooldown between punches
  96.     local sdCurrentPunch    = arrPunchData[iCurrentSwing]
  97.    
  98.     iCurrentSwing = iCurrentSwing + 1
  99.    
  100.     if (iCurrentSwing > eSwing.RIGHT_PUNCH2)
  101.    
  102.         iCurrentSwing = eSwing.RIGHT_PUNCH1
  103.    
  104.     end
  105.    
  106.     local objViewModel = self.Owner:GetViewModel()
  107.     objViewModel:SendViewModelMatchingSequence( objViewModel:LookupSequence(sdCurrentPunch.strAnimation) )
  108.    
  109.     self:UpdateNextIdle()
  110.     self:SetNextMeleeAttack( CurTime() + sdCurrentPunch.flNextSwing )
  111.  
  112.     self:SetNextPrimaryFire( CurTime() + sdCurrentPunch.flNextSwing )
  113.     self:SetNextSecondaryFire( CurTime() + sdCurrentPunch.flNextSwing )
  114.    
  115. end
  116.  
  117. function SWEP:SecondaryAttack()
  118.  
  119.     self:PrimaryAttack( true )
  120.  
  121. end
  122.  
  123. local phys_pushscale = GetConVar( "phys_pushscale" )
  124.  
  125. function SWEP:DealDamage(flDamage)
  126.  
  127.     local anim = self:GetSequenceName(self.Owner:GetViewModel():GetSequence())
  128.  
  129.     self.Owner:LagCompensation( true )
  130.  
  131.     local tr = util.TraceLine( {
  132.         start = self.Owner:GetShootPos(),
  133.         endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * self.HitDistance,
  134.         filter = self.Owner,
  135.         mask = MASK_SHOT_HULL
  136.     } )
  137.  
  138.     if ( !IsValid( tr.Entity ) ) then
  139.         tr = util.TraceHull( {
  140.             start = self.Owner:GetShootPos(),
  141.             endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * self.HitDistance,
  142.             filter = self.Owner,
  143.             mins = Vector( -10, -10, -8 ),
  144.             maxs = Vector( 10, 10, 8 ),
  145.             mask = MASK_SHOT_HULL
  146.         } )
  147.     end
  148.  
  149.     -- We need the second part for single player because SWEP:Think is ran shared in SP
  150.     if ( tr.Hit && !( game.SinglePlayer() && CLIENT ) ) then
  151.         self:EmitSound( HitSound )
  152.     end
  153.  
  154.     local hit = false
  155.     local scale = phys_pushscale:GetFloat()
  156.  
  157.     if ( SERVER && IsValid( tr.Entity ) && ( tr.Entity:IsNPC() || tr.Entity:IsPlayer() || tr.Entity:Health() > 0 ) ) then
  158.         local dmginfo = DamageInfo()
  159.  
  160.         local attacker = self.Owner
  161.         if ( !IsValid( attacker ) ) then attacker = self end
  162.         dmginfo:SetAttacker( attacker )
  163.  
  164.         dmginfo:SetInflictor( self )
  165.         dmginfo:SetDamage( flDamage )
  166.  
  167.         if ( anim == "fists_left" ) then
  168.             dmginfo:SetDamageForce( self.Owner:GetRight() * 4912 * scale + self.Owner:GetForward() * 9998 * scale ) -- Yes we need those specific numbers
  169.         elseif ( anim == "fists_right" ) then
  170.             dmginfo:SetDamageForce( self.Owner:GetRight() * -4912 * scale + self.Owner:GetForward() * 9989 * scale )
  171.         elseif ( anim == "fists_uppercut" ) then
  172.             dmginfo:SetDamageForce( self.Owner:GetUp() * 5158 * scale + self.Owner:GetForward() * 10012 * scale )
  173.             dmginfo:SetDamage( flDamage )
  174.         end
  175.  
  176.         SuppressHostEvents( NULL ) -- Let the breakable gibs spawn in multiplayer on client
  177.         tr.Entity:TakeDamageInfo( dmginfo )
  178.         SuppressHostEvents( self.Owner )
  179.  
  180.         hit = true
  181.  
  182.     end
  183.  
  184.     if ( IsValid( tr.Entity ) ) then
  185.         local phys = tr.Entity:GetPhysicsObject()
  186.         if ( IsValid( phys ) ) then
  187.             phys:ApplyForceOffset( self.Owner:GetAimVector() * 80 * phys:GetMass() * scale, tr.HitPos )
  188.         end
  189.     end
  190.  
  191.     if ( SERVER ) then
  192.         if ( hit && anim != "fists_uppercut" ) then
  193.             self:SetCombo( self:GetCombo() + 1 )
  194.         else
  195.             self:SetCombo( 0 )
  196.         end
  197.     end
  198.  
  199.     self.Owner:LagCompensation( false )
  200.  
  201. end
  202.  
  203. function SWEP:OnDrop()
  204.  
  205.     self:Remove() -- You can't drop fists
  206.  
  207. end
  208.  
  209. function SWEP:Deploy()
  210.  
  211.     local speed = GetConVarNumber( "sv_defaultdeployspeed" )
  212.  
  213.     local vm = self.Owner:GetViewModel()
  214.     vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_draw" ) )
  215.     vm:SetPlaybackRate( speed )
  216.  
  217.     self:SetNextPrimaryFire( CurTime() + vm:SequenceDuration() / speed )
  218.     self:SetNextSecondaryFire( CurTime() + vm:SequenceDuration() / speed )
  219.     self:UpdateNextIdle()
  220.  
  221.     if ( SERVER ) then
  222.         self:SetCombo( 0 )
  223.     end
  224.  
  225.     return true
  226.  
  227. end
  228.  
  229. function SWEP:Holster()
  230.  
  231.     self:SetNextMeleeAttack( 0 )
  232.  
  233.     return true
  234.  
  235. end
  236.  
  237. function SWEP:Think()
  238.  
  239.     local vm = self.Owner:GetViewModel()
  240.     local idletime = self:GetNextIdle()
  241.  
  242.     if ( idletime > 0 && CurTime() > idletime ) then
  243.  
  244.         vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_idle_0" .. math.random( 1, 2 ) ) )
  245.  
  246.         self:UpdateNextIdle()
  247.  
  248.     end
  249.    
  250.     -- Todo: add uppercut
  251.     if (LocalPlayer():Crouching()) then
  252.        
  253.         flLastDuck = CurTime()
  254.        
  255.     end
  256.    
  257.     local flNextMeleeAttack = self:GetNextMeleeAttack()
  258.     if ( flNextMeleeAttack > 0 && CurTime() > flNextMeleeAttack ) then
  259.  
  260.         self:DealDamage()
  261.         self:SetNextMeleeAttack( 0 )
  262.  
  263.     end
  264.  
  265.     if ( SERVER && CurTime() > self:GetNextPrimaryFire() + 0.1 ) then
  266.  
  267.         self:SetCombo( 0 )
  268.  
  269.     end
  270.  
  271. end
  272.  
  273.  
Advertisement
Add Comment
Please, Sign In to add comment