Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- AddCSLuaFile()
- SWEP.PrintName = "The Specialists - Kung Fu"
- SWEP.Author = "Knee"
- SWEP.Purpose = "The melee weapon from the popular Half-Life mod: The Specialists"
- SWEP.Slot = 0
- SWEP.SlotPos = 4
- SWEP.Spawnable = true
- SWEP.ViewModel = Model( "models/weapons/c_arms.mdl" )
- SWEP.WorldModel = ""
- SWEP.ViewModelFOV = 54
- SWEP.UseHands = true
- SWEP.Primary.ClipSize = -1
- SWEP.Primary.DefaultClip = -1
- SWEP.Primary.Automatic = true
- SWEP.Primary.Ammo = "none"
- SWEP.Secondary.ClipSize = -1
- SWEP.Secondary.DefaultClip = -1
- SWEP.Secondary.Automatic = true
- SWEP.Secondary.Ammo = "none"
- SWEP.DrawAmmo = false
- SWEP.HitDistance = 48
- local SwingSound = Sound( "WeaponFrag.Throw" )
- local HitSound = Sound( "Flesh.ImpactHard" )
- local flLastDuck = 0
- local flNextSwing = 0
- local iCurrentSwing = 0
- -- Sequence of punches to be followed while holding down attack button
- local eSwing = {
- RIGHT_PUNCH1 = 1,
- LEFT_PUNCH1 = 2,
- LEFT_PUNCH2 = 3,
- LEFT_PUNCH3 = 4,
- RIGHT_PUNCH2 = 5
- }
- -- Grouping together information about punching sequences
- SwingData = {strAnimation = "null", flDamage = 0, flNextSwing = 0}
- function SwingData:create(strAnim, flDmg, flNxtSwng)
- self.strAnimation = strAnim
- self.flDamage = flDmg
- self.flNextSwing = flNxtSwng
- end
- local arrPunchData = {
- sdPunch1 = SwingData:create("fists_right", 20.0, 0.45),
- sdPunch2 = SwingData:create("fists_left" , 15.0, 0.23),
- sdPunch3 = SwingData:create("fists_left" , 15.0, 0.23),
- sdPunch4 = SwingData:create("fists_left" , 15.0, 0.23),
- sdPunch5 = SwingData:create("fists_right", 30.0, 0.55)
- }
- function SWEP:Initialize()
- self:SetHoldType( "fist" )
- end
- function SWEP:SetupDataTables()
- self:NetworkVar( "Float", 0, "NextMeleeAttack" )
- self:NetworkVar( "Float", 1, "NextIdle" )
- self:NetworkVar( "Int", 2, "Combo" )
- end
- function SWEP:UpdateNextIdle()
- local vm = self.Owner:GetViewModel()
- self:SetNextIdle( CurTime() + vm:SequenceDuration() / vm:GetPlaybackRate() )
- end
- function SWEP:PrimaryAttack( right )
- self.Owner:SetAnimation( PLAYER_ATTACK1 )
- local strAnimation = "fists_left"
- local flDamage = 0 -- [float] how much damage is down to a target
- local flMeleeCooldown = 0 -- [seconds] cooldown between punches
- local sdCurrentPunch = arrPunchData[iCurrentSwing]
- iCurrentSwing = iCurrentSwing + 1
- if (iCurrentSwing > eSwing.RIGHT_PUNCH2)
- iCurrentSwing = eSwing.RIGHT_PUNCH1
- end
- local objViewModel = self.Owner:GetViewModel()
- objViewModel:SendViewModelMatchingSequence( objViewModel:LookupSequence(sdCurrentPunch.strAnimation) )
- self:UpdateNextIdle()
- self:SetNextMeleeAttack( CurTime() + sdCurrentPunch.flNextSwing )
- self:SetNextPrimaryFire( CurTime() + sdCurrentPunch.flNextSwing )
- self:SetNextSecondaryFire( CurTime() + sdCurrentPunch.flNextSwing )
- end
- function SWEP:SecondaryAttack()
- self:PrimaryAttack( true )
- end
- local phys_pushscale = GetConVar( "phys_pushscale" )
- function SWEP:DealDamage(flDamage)
- local anim = self:GetSequenceName(self.Owner:GetViewModel():GetSequence())
- self.Owner:LagCompensation( true )
- local tr = util.TraceLine( {
- start = self.Owner:GetShootPos(),
- endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * self.HitDistance,
- filter = self.Owner,
- mask = MASK_SHOT_HULL
- } )
- if ( !IsValid( tr.Entity ) ) then
- tr = util.TraceHull( {
- start = self.Owner:GetShootPos(),
- endpos = self.Owner:GetShootPos() + self.Owner:GetAimVector() * self.HitDistance,
- filter = self.Owner,
- mins = Vector( -10, -10, -8 ),
- maxs = Vector( 10, 10, 8 ),
- mask = MASK_SHOT_HULL
- } )
- end
- -- We need the second part for single player because SWEP:Think is ran shared in SP
- if ( tr.Hit && !( game.SinglePlayer() && CLIENT ) ) then
- self:EmitSound( HitSound )
- end
- local hit = false
- local scale = phys_pushscale:GetFloat()
- if ( SERVER && IsValid( tr.Entity ) && ( tr.Entity:IsNPC() || tr.Entity:IsPlayer() || tr.Entity:Health() > 0 ) ) then
- local dmginfo = DamageInfo()
- local attacker = self.Owner
- if ( !IsValid( attacker ) ) then attacker = self end
- dmginfo:SetAttacker( attacker )
- dmginfo:SetInflictor( self )
- dmginfo:SetDamage( flDamage )
- if ( anim == "fists_left" ) then
- dmginfo:SetDamageForce( self.Owner:GetRight() * 4912 * scale + self.Owner:GetForward() * 9998 * scale ) -- Yes we need those specific numbers
- elseif ( anim == "fists_right" ) then
- dmginfo:SetDamageForce( self.Owner:GetRight() * -4912 * scale + self.Owner:GetForward() * 9989 * scale )
- elseif ( anim == "fists_uppercut" ) then
- dmginfo:SetDamageForce( self.Owner:GetUp() * 5158 * scale + self.Owner:GetForward() * 10012 * scale )
- dmginfo:SetDamage( flDamage )
- end
- SuppressHostEvents( NULL ) -- Let the breakable gibs spawn in multiplayer on client
- tr.Entity:TakeDamageInfo( dmginfo )
- SuppressHostEvents( self.Owner )
- hit = true
- end
- if ( IsValid( tr.Entity ) ) then
- local phys = tr.Entity:GetPhysicsObject()
- if ( IsValid( phys ) ) then
- phys:ApplyForceOffset( self.Owner:GetAimVector() * 80 * phys:GetMass() * scale, tr.HitPos )
- end
- end
- if ( SERVER ) then
- if ( hit && anim != "fists_uppercut" ) then
- self:SetCombo( self:GetCombo() + 1 )
- else
- self:SetCombo( 0 )
- end
- end
- self.Owner:LagCompensation( false )
- end
- function SWEP:OnDrop()
- self:Remove() -- You can't drop fists
- end
- function SWEP:Deploy()
- local speed = GetConVarNumber( "sv_defaultdeployspeed" )
- local vm = self.Owner:GetViewModel()
- vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_draw" ) )
- vm:SetPlaybackRate( speed )
- self:SetNextPrimaryFire( CurTime() + vm:SequenceDuration() / speed )
- self:SetNextSecondaryFire( CurTime() + vm:SequenceDuration() / speed )
- self:UpdateNextIdle()
- if ( SERVER ) then
- self:SetCombo( 0 )
- end
- return true
- end
- function SWEP:Holster()
- self:SetNextMeleeAttack( 0 )
- return true
- end
- function SWEP:Think()
- local vm = self.Owner:GetViewModel()
- local idletime = self:GetNextIdle()
- if ( idletime > 0 && CurTime() > idletime ) then
- vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_idle_0" .. math.random( 1, 2 ) ) )
- self:UpdateNextIdle()
- end
- -- Todo: add uppercut
- if (LocalPlayer():Crouching()) then
- flLastDuck = CurTime()
- end
- local flNextMeleeAttack = self:GetNextMeleeAttack()
- if ( flNextMeleeAttack > 0 && CurTime() > flNextMeleeAttack ) then
- self:DealDamage()
- self:SetNextMeleeAttack( 0 )
- end
- if ( SERVER && CurTime() > self:GetNextPrimaryFire() + 0.1 ) then
- self:SetCombo( 0 )
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment