2014-11-10 11:51:43 +08:00
|
|
|
AddCSLuaFile()
|
|
|
|
|
|
|
|
SWEP.PrintName = "Fists"
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.Base = "weapon_zs_basemelee"
|
2014-11-10 11:51:43 +08:00
|
|
|
|
|
|
|
SWEP.ViewModel = "models/weapons/c_arms_citizen.mdl"
|
|
|
|
SWEP.WorldModel = ""
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.UseHands = true
|
|
|
|
|
|
|
|
SWEP.HoldType = "fist"
|
|
|
|
|
|
|
|
SWEP.WalkSpeed = SPEED_NORMAL
|
|
|
|
SWEP.OldWalkSpeed = 0
|
2014-11-10 11:51:43 +08:00
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.MeleeDamage = 15
|
|
|
|
SWEP.DamageType = DMG_CLUB
|
2014-11-10 11:51:43 +08:00
|
|
|
SWEP.UppercutDamageMultiplier = 3
|
|
|
|
SWEP.HitDistance = 40
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.MeleeKnockBack = 0
|
2014-11-10 11:51:43 +08:00
|
|
|
|
|
|
|
SWEP.ViewModelFOV = 52
|
|
|
|
|
|
|
|
SWEP.AutoSwitchFrom = true
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.Unarmed = true
|
|
|
|
|
2014-11-10 11:51:43 +08:00
|
|
|
SWEP.Undroppable = true
|
|
|
|
SWEP.NoPickupNotification = true
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.NoDismantle = true
|
|
|
|
SWEP.NoGlassWeapons = true
|
2014-11-10 11:51:43 +08:00
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.Primary.Delay = 0.6
|
2014-11-11 09:09:01 +08:00
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.Weight = 2 -- This is the second crappiest weapon you could hope for, besides food
|
|
|
|
SWEP.SlotPos = 100
|
2014-11-10 11:51:43 +08:00
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.IsFistWeapon = true
|
|
|
|
SWEP.SwingSound = Sound( "weapons/slam/throw.wav" )
|
|
|
|
SWEP.HitSound = Sound( "Flesh.ImpactHard" )
|
2014-11-10 11:51:43 +08:00
|
|
|
|
|
|
|
function SWEP:PreDrawViewModel(vm, wep, pl)
|
|
|
|
vm:SetMaterial("engine/occlusionproxy")
|
|
|
|
end
|
|
|
|
|
|
|
|
function SWEP:SetupDataTables()
|
|
|
|
self:NetworkVar("Float", 0, "NextMeleeAttack")
|
|
|
|
self:NetworkVar("Float", 1, "NextIdle")
|
|
|
|
self:NetworkVar("Float", 2, "NextIdleHoldType")
|
|
|
|
self:NetworkVar("Int", 2, "Combo")
|
2018-05-02 06:32:59 +08:00
|
|
|
--self:NetworkVar("Bool", 0, "HitPrevious")
|
|
|
|
self:NetworkVar("Int", 0, "PowerCombo")
|
2014-11-10 11:51:43 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
function SWEP:UpdateNextIdle()
|
2018-05-02 06:32:59 +08:00
|
|
|
local vm = self:GetOwner():GetViewModel()
|
2014-11-10 11:51:43 +08:00
|
|
|
self:SetNextIdle( CurTime() + vm:SequenceDuration() )
|
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
SWEP.LastSwingHit = 0
|
|
|
|
SWEP.LastSwingStart = 0
|
|
|
|
|
2014-11-10 11:51:43 +08:00
|
|
|
function SWEP:PrimaryAttack(right)
|
2018-05-02 06:32:59 +08:00
|
|
|
local owner = self:GetOwner()
|
|
|
|
local time = CurTime()
|
|
|
|
|
|
|
|
self:SetNextIdleHoldType(time + 1.5)
|
|
|
|
owner:SetAnimation(PLAYER_ATTACK1)
|
|
|
|
self.OldWalkSpeed = math.max(self.OldWalkSpeed, self.WalkSpeed)
|
|
|
|
if not owner:IsSkillActive(SKILL_KNUCKLEMASTER) and self.Unarmed then
|
|
|
|
self.WalkSpeed = 165
|
|
|
|
owner:ResetSpeed()
|
|
|
|
end
|
2014-11-10 11:51:43 +08:00
|
|
|
|
|
|
|
local anim = "fists_left"
|
|
|
|
if ( right ) then anim = "fists_right" end
|
|
|
|
if ( self:GetCombo() >= 2 ) then
|
|
|
|
anim = "fists_uppercut"
|
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
local vm = self:GetOwner():GetViewModel()
|
2014-11-10 11:51:43 +08:00
|
|
|
vm:SendViewModelMatchingSequence( vm:LookupSequence( anim ) )
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
self:EmitSound( self.SwingSound )
|
2014-11-10 11:51:43 +08:00
|
|
|
|
|
|
|
self:UpdateNextIdle()
|
2018-05-02 06:32:59 +08:00
|
|
|
|
|
|
|
local armdelay = owner:GetMeleeSpeedMul()
|
|
|
|
local hitdelay = self.Primary.Delay / 3 * (owner.MeleeSwingDelayMul or 1) * armdelay
|
|
|
|
owner:GetViewModel():SetPlaybackRate(1 / armdelay)
|
|
|
|
if time < self.LastSwingStart + 1 and owner:IsSkillActive(SKILL_COMBOKNUCKLE) then
|
|
|
|
if time < self.LastSwingHit + 0.75 then --if self:GetHitPrevious() then
|
|
|
|
hitdelay = hitdelay / 2
|
|
|
|
owner:GetViewModel():SetPlaybackRate(2 / armdelay)
|
|
|
|
else
|
|
|
|
hitdelay = hitdelay * 2
|
|
|
|
owner:GetViewModel():SetPlaybackRate(0.5 / armdelay)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
self:SetNextMeleeAttack( time + hitdelay )
|
|
|
|
|
|
|
|
self:SetNextPrimaryFire( time + self.Primary.Delay * armdelay )
|
|
|
|
self:SetNextSecondaryFire( time + self.Primary.Delay * armdelay )
|
|
|
|
|
|
|
|
self.LastSwingStart = time
|
2014-11-10 11:51:43 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
function SWEP:SecondaryAttack()
|
|
|
|
self:PrimaryAttack( true )
|
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
function SWEP:GenerateDamageInfo(damage, hitpos)
|
|
|
|
local dmginfo = DamageInfo()
|
|
|
|
dmginfo:SetAttacker(self:GetOwner())
|
|
|
|
dmginfo:SetInflictor(self)
|
|
|
|
dmginfo:SetDamageType(self.DamageType)
|
|
|
|
dmginfo:SetDamagePosition(hitpos)
|
|
|
|
dmginfo:SetDamage(damage)
|
|
|
|
return dmginfo
|
|
|
|
end
|
|
|
|
|
2014-11-10 11:51:43 +08:00
|
|
|
function SWEP:DealDamage()
|
2018-05-02 06:32:59 +08:00
|
|
|
local owner = self:GetOwner()
|
2014-11-10 11:51:43 +08:00
|
|
|
local aimvector = owner:GetAimVector()
|
|
|
|
local anim = self:GetSequenceName(owner:GetViewModel():GetSequence())
|
2018-05-02 06:32:59 +08:00
|
|
|
local time = CurTime()
|
|
|
|
|
|
|
|
local tr = owner:CompensatedMeleeTrace(self.HitDistance * (owner.MeleeRangeMul or 1), 3)
|
2014-11-10 11:51:43 +08:00
|
|
|
|
|
|
|
local hitent = tr.Entity
|
|
|
|
|
|
|
|
-- We need the second part for single player because SWEP:Think is ran shared in SP.
|
|
|
|
if tr.Hit and not ( game.SinglePlayer() and CLIENT ) then
|
2018-05-02 06:32:59 +08:00
|
|
|
self:EmitSound( self.HitSound, 75, 100, 1, CHAN_WEAPON + 1)
|
|
|
|
end
|
|
|
|
|
|
|
|
if self.OnMeleeHit and self:OnMeleeHit(hitent, hitflesh, tr) then
|
|
|
|
return
|
2014-11-10 11:51:43 +08:00
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
local armdelay = owner:GetMeleeSpeedMul()
|
|
|
|
local delay = self.Primary.Delay * (owner.UnarmedDelayMul or 1) * armdelay
|
|
|
|
if tr.Hit then
|
|
|
|
self.LastSwingHit = time
|
|
|
|
if owner:IsSkillActive(SKILL_COMBOKNUCKLE) then
|
|
|
|
delay = delay / 2
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if owner:IsSkillActive(SKILL_COMBOKNUCKLE) then
|
|
|
|
delay = delay * 2
|
|
|
|
end
|
|
|
|
|
|
|
|
if owner.MeleePowerAttackMul and owner.MeleePowerAttackMul > 1 then
|
|
|
|
self:SetPowerCombo(0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
self:SetNextPrimaryFire( time + delay )
|
|
|
|
self:SetNextSecondaryFire( time + delay )
|
|
|
|
|
|
|
|
if hitent:IsValid() then
|
|
|
|
local damagemultiplier = owner:GetTotalAdditiveModifier("UnarmedDamageMul", "MeleeDamageMultiplier")
|
|
|
|
if owner:IsSkillActive(SKILL_LASTSTAND) then
|
|
|
|
if owner:Health() <= owner:GetMaxHealth() * 0.25 then
|
|
|
|
damagemultiplier = damagemultiplier * 2
|
|
|
|
else
|
|
|
|
damagemultiplier = damagemultiplier * 0.85
|
|
|
|
end
|
|
|
|
end
|
2014-11-10 11:51:43 +08:00
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
if SERVER and hitent:IsPlayer() and not self.NoGlassWeapons and owner:IsSkillActive(SKILL_GLASSWEAPONS) then
|
|
|
|
damagemultiplier = damagemultiplier * 3.5
|
|
|
|
owner.GlassWeaponShouldBreak = not owner.GlassWeaponShouldBreak
|
|
|
|
end
|
2014-11-10 11:51:43 +08:00
|
|
|
|
|
|
|
if anim == "fists_uppercut" then
|
2018-05-02 06:32:59 +08:00
|
|
|
damagemultiplier = damagemultiplier * self.UppercutDamageMultiplier
|
2014-11-10 11:51:43 +08:00
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
local damage = self.MeleeDamage * damagemultiplier
|
|
|
|
local dmginfo = self:GenerateDamageInfo(damage, tr.HitPos)
|
|
|
|
|
|
|
|
local vel
|
|
|
|
if hitent:IsPlayer() then
|
|
|
|
self:PlayerHitUtil(owner, damage, hitent, dmginfo)
|
|
|
|
|
|
|
|
if SERVER then
|
|
|
|
hitent:SetLastHitGroup(tr.HitGroup)
|
|
|
|
if tr.HitGroup == HITGROUP_HEAD then
|
|
|
|
hitent:SetWasHitInHead()
|
|
|
|
end
|
|
|
|
|
|
|
|
if hitent:WouldDieFrom(dmginfo:GetDamage(), dmginfo:GetDamagePosition()) then
|
|
|
|
if anim == "fists_left" then
|
|
|
|
dmginfo:SetDamageForce(owner:GetRight() * 4912 + owner:GetForward() * 9998)
|
|
|
|
elseif anim == "fists_right" then
|
|
|
|
dmginfo:SetDamageForce(owner:GetRight() * -4912 + owner:GetForward() * 9989)
|
|
|
|
elseif anim == "fists_uppercut" then
|
|
|
|
dmginfo:SetDamageForce(owner:GetUp() * 5158 + owner:GetForward() * 10012)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if owner:IsSkillActive(SKILL_CRITICALKNUCKLE) then
|
|
|
|
hitent:ThrowFromPositionSetZ(tr.StartPos, 240 * (owner.MeleeKnockbackMultiplier or 1), nil, true)
|
|
|
|
end
|
|
|
|
|
|
|
|
if owner.BoxingTraining then
|
|
|
|
self:SetDTInt(5, self:GetDTInt(5) + 1)
|
|
|
|
|
|
|
|
if self:GetDTInt(5) >= 5 then
|
|
|
|
self:SetDTInt(5, 0)
|
|
|
|
|
|
|
|
hitent:AddLegDamage(18)
|
|
|
|
hitent:AddArmDamage(18)
|
|
|
|
hitent:EmitSound("weapons/crowbar/crowbar_impact1.wav", 75, math.random(60, 65))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
vel = hitent:GetVelocity()
|
|
|
|
else
|
|
|
|
if owner.MeleePowerAttackMul and owner.MeleePowerAttackMul > 1 then
|
|
|
|
self:SetPowerCombo(0)
|
2014-11-10 11:51:43 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
if IsFirstTimePredicted() then
|
|
|
|
self:PostHitUtil(owner, hitent, dmginfo, tr, vel)
|
|
|
|
end
|
2014-11-10 11:51:43 +08:00
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
if SERVER and hitent:GetMoveType() == MOVETYPE_VPHYSICS then
|
|
|
|
local phys = hitent:GetPhysicsObject()
|
|
|
|
if phys and phys:IsValid() then
|
|
|
|
phys:ApplyForceOffset( aimvector * 2000, tr.HitPos )
|
|
|
|
hitent:SetPhysicsAttacker(owner)
|
|
|
|
end
|
2014-11-10 11:51:43 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if SERVER then
|
|
|
|
if hitplayer and anim ~= "fists_uppercut" then
|
|
|
|
self:SetCombo( self:GetCombo() + 1 )
|
|
|
|
else
|
|
|
|
self:SetCombo( 0 )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
if SERVER then
|
|
|
|
self:ServerMeleePostHitEntity(tr, hitent, damagemultiplier)
|
|
|
|
end
|
2014-11-10 11:51:43 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
function SWEP:OnRemove()
|
2018-05-02 06:32:59 +08:00
|
|
|
if CLIENT and self:GetOwner():IsValid() and self:GetOwner():IsPlayer() then
|
|
|
|
local vm = self:GetOwner():GetViewModel()
|
2014-11-10 11:51:43 +08:00
|
|
|
if IsValid(vm) then vm:SetMaterial("") end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function SWEP:Holster(wep)
|
|
|
|
if CurTime() >= self:GetNextPrimaryFire() then
|
|
|
|
self:OnRemove()
|
2018-05-02 06:32:59 +08:00
|
|
|
if CLIENT then
|
|
|
|
self:Anim_Holster()
|
|
|
|
end
|
2014-11-10 11:51:43 +08:00
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
function SWEP:Deploy()
|
2018-05-02 06:32:59 +08:00
|
|
|
local vm = self:GetOwner():GetViewModel()
|
2014-11-10 11:51:43 +08:00
|
|
|
vm:SendViewModelMatchingSequence(vm:LookupSequence("fists_draw"))
|
2018-05-02 06:32:59 +08:00
|
|
|
|
2014-11-10 11:51:43 +08:00
|
|
|
self:UpdateNextIdle()
|
2018-05-02 06:32:59 +08:00
|
|
|
|
2014-11-10 11:51:43 +08:00
|
|
|
if SERVER then
|
|
|
|
self:SetCombo(0)
|
|
|
|
end
|
2018-05-02 06:32:59 +08:00
|
|
|
self:GetOwner():ResetSpeed()
|
2014-11-10 11:51:43 +08:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function SWEP:Think()
|
|
|
|
local idletime = self:GetNextIdle()
|
|
|
|
local idle_holdtype_time = self:GetNextIdleHoldType()
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
if idle_holdtype_time > 0 and CurTime() >= idle_holdtype_time then
|
2014-11-12 08:15:49 +08:00
|
|
|
--self:SetWeaponHoldType("normal")
|
2014-11-10 11:51:43 +08:00
|
|
|
self:SetNextIdleHoldType(0)
|
2018-05-02 06:32:59 +08:00
|
|
|
self.WalkSpeed = self.OldWalkSpeed
|
|
|
|
self:GetOwner():ResetSpeed()
|
2014-11-10 11:51:43 +08:00
|
|
|
end
|
2018-05-02 06:32:59 +08:00
|
|
|
|
|
|
|
if idletime > 0 and CurTime() >= idletime then
|
|
|
|
local vm = self:GetOwner():GetViewModel()
|
2014-11-10 11:51:43 +08:00
|
|
|
vm:SendViewModelMatchingSequence( vm:LookupSequence("fists_idle_0"..math.random(2)))
|
|
|
|
|
|
|
|
self:UpdateNextIdle()
|
|
|
|
end
|
2018-05-02 06:32:59 +08:00
|
|
|
|
2014-11-10 11:51:43 +08:00
|
|
|
local meleetime = self:GetNextMeleeAttack()
|
2018-05-02 06:32:59 +08:00
|
|
|
|
|
|
|
if meleetime > 0 and CurTime() >= meleetime then
|
2014-11-10 11:51:43 +08:00
|
|
|
self:DealDamage()
|
|
|
|
self:SetNextMeleeAttack( 0 )
|
|
|
|
end
|
2018-05-02 06:32:59 +08:00
|
|
|
|
|
|
|
if SERVER and CurTime() >= self:GetNextPrimaryFire() + 0.1 then
|
2014-11-10 11:51:43 +08:00
|
|
|
self:SetCombo( 0 )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
function SWEP:TranslateActivity( act )
|
|
|
|
return self.ActivityTranslate and self.ActivityTranslate[act] or -1
|
|
|
|
end
|
|
|
|
|
2014-11-10 11:51:43 +08:00
|
|
|
if not CLIENT then return end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
function SWEP:DrawWeaponSelection(x, y, w, h, alpha)
|
|
|
|
self:BaseDrawWeaponSelection(x, y, w, h, alpha)
|
|
|
|
end
|
|
|
|
|
|
|
|
function SWEP:DrawHUD()
|
|
|
|
self:DrawCrosshairDot()
|
2014-11-10 11:51:43 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
function SWEP:GetViewModelPosition(pos, ang)
|
|
|
|
pos = pos - ang:Up() * 3
|
|
|
|
|
|
|
|
return pos, ang
|
|
|
|
end
|