SWEP.Sound_MeleeHit = nil SWEP.Sound_MeleeHitBody = nil -- Don't you love lua table inheritance?? SWEP._Sound_MeleeHit = { "TacRP/weapons/melee_hit-1.wav", "TacRP/weapons/melee_hit-2.wav" } SWEP._Sound_MeleeHitBody = { "TacRP/weapons/melee_body_hit-1.wav", "TacRP/weapons/melee_body_hit-2.wav", "TacRP/weapons/melee_body_hit-3.wav", "TacRP/weapons/melee_body_hit-4.wav", "TacRP/weapons/melee_body_hit-5.wav", } function SWEP:Melee(alt) if !self:GetValue("CanMeleeAttack") then return end if self:StillWaiting(false, true) then return end if DarkRP and self:GetNWBool("TacRP_PoliceBiocode") and !self:GetOwner():isCP() then return end -- if self:SprintLock() then return end self.Primary.Automatic = true self.Secondary.Automatic = true self:SetCharge(false) self:CancelReload() self:ToggleBlindFire(TacRP.BLINDFIRE_NONE) self:ScopeToggle(0) local dmg = self:GetValue("MeleeDamage") * self:GetConfigDamageMultiplier() local range = self:GetValue("MeleeRange") local delay = self:GetValue("MeleeDelay") if alt then self:PlayAnimation("melee2", 1, false, true) -- self:GetOwner():DoAnimationEvent(self:GetValue("GestureBash2") or self:GetValue("GestureBash")) -- range = self:GetValue("Melee2Range") or range dmg = self:GetHeavyAttackDamage() * self:GetConfigDamageMultiplier() else self:PlayAnimation("melee", 1, false, true) -- self:GetOwner():DoAnimationEvent(self:GetValue("GestureBash")) end local t = alt and self:GetHeavyAttackTime() or self:GetValue("MeleeAttackTime") self:GetOwner():DoCustomAnimEvent(PLAYERANIMEVENT_ATTACK_PRIMARY, t * 1000 * (alt and -1 or 1)) if delay > 0 then self:EmitSound(self:ChooseSound(self:GetValue("Sound_MeleeSwing")), 75, 100, 1) end self:SetTimer(delay, function() self:GetOwner():LagCompensation(true) local filter = {self:GetOwner()} table.Add(filter, self.Shields) local start = self:GetOwner():GetShootPos() local dir = self:GetOwner():GetAimVector() local tr = util.TraceLine({ start = start, endpos = start + dir * range, filter = filter, mask = MASK_SHOT_HULL, }) -- weapon_hl2mpbasebasebludgeon.cpp: do a hull trace if not hit if tr.Fraction == 1 or !IsValid(tr.Entity) then local dim = 32 local pos2 = tr.HitPos - dir * (dim * 1.732) local tr2 = util.TraceHull({ start = start, endpos = pos2, filter = filter, mask = MASK_SHOT_HULL, mins = Vector(-dim, -dim, -dim), maxs = Vector(dim, dim, dim) }) if tr2.Fraction < 1 and IsValid(tr2.Entity) then local dot = (tr2.Entity:GetPos() - start):GetNormalized():Dot(dir) if dot >= 0.5 then tr = tr2 end end end local dmginfo = DamageInfo() dmginfo:SetDamage(dmg) dmginfo:SetDamageForce(dir * dmg * 500) dmginfo:SetDamagePosition(tr.HitPos) dmginfo:SetDamageType(self:GetValue("MeleeDamageType")) if dmginfo:GetDamageType() == DMG_GENERIC and engine.ActiveGamemode() == "terrortown" then dmginfo:SetDamageType(DMG_CLUB) -- use CLUB so TTT can assign DNA (it does not leave DNA on generic damage) end dmginfo:SetAttacker(self:GetOwner()) dmginfo:SetInflictor(self) if tr.Fraction < 1 then TacRP.CancelBodyDamage(tr.Entity, dmginfo, tr.HitGroup) if IsValid(tr.Entity) and (tr.Entity:IsNPC() or tr.Entity:IsPlayer() or tr.Entity:IsNextBot() or tr.Entity:IsRagdoll()) then self:EmitSound(self:ChooseSound(self:GetValue("Sound_MeleeHitBody") or self:GetValue("_Sound_MeleeHitBody")), 75, 100, 1, CHAN_ITEM) if !tr.Entity:IsRagdoll() and self:GetValue("MeleeBackstab") then local ang = math.NormalizeAngle(self:GetOwner():GetAngles().y - tr.Entity:GetAngles().y) if ang <= 60 and ang >= -60 then dmginfo:ScaleDamage(self:GetValue("MeleeBackstabMult")) self:EmitSound("tacrp/riki_backstab.wav", 70, 100, 0.4) end end else self:EmitSound(self:ChooseSound(self:GetValue("Sound_MeleeHit") or self:GetValue("_Sound_MeleeHit")), 75, 100, 1, CHAN_ITEM) end if IsValid(tr.Entity) and self:GetValue("MeleeSlow") then tr.Entity.TacRPBashSlow = true end if tr.HitGroup == HITGROUP_HEAD then dmginfo:ScaleDamage(1.25) end if IsValid(tr.Entity) then if tr.Entity.LVS then return end --tr.Entity:TakeDamageInfo(dmginfo) tr.Entity:DispatchTraceAttack(dmginfo, tr) end self:FireBullets({ Attacker = self:GetOwner(), Damage = 0, Force = 0, Distance = range + 8, HullSize = 0, Tracer = 0, Dir = (tr.HitPos - start):GetNormalized(), Src = start, }) else local tmiss if !alt and self:GetValue("MeleeAttackMissTime") then tmiss = self:GetValue("MeleeAttackMissTime") elseif alt then tmiss = self:GetHeavyAttackTime(true, false) end if tmiss then self:SetNextSecondaryFire(CurTime() + (tmiss - delay)) end if delay == 0 then self:EmitSound(self:ChooseSound(self:GetValue("Sound_MeleeSwing")), 75, 100, 1) end end self:GetOwner():LagCompensation(false) end, "Melee") self:SetLastMeleeTime(CurTime()) self:SetNextSecondaryFire(CurTime() + t) end function SWEP:GetHeavyAttackDamage(base) local valfunc = base and self.GetBaseValue or self.GetValue return valfunc(self, "Melee2Damage") or valfunc(self, "MeleeDamage") * self:GetMeleePerkDamage(base) * 1.5 end function SWEP:GetHeavyAttackTime(miss, base) local valfunc = base and self.GetBaseValue or self.GetValue if miss then return (valfunc(self, "Melee2AttackMissTime") or (valfunc(self, "MeleeAttackMissTime") * 1.6)) * self:GetMeleePerkCooldown(base) else return (valfunc(self, "Melee2AttackTime") or (valfunc(self, "MeleeAttackTime") * 1.6)) * self:GetMeleePerkCooldown(base) end end function SWEP:GetMeleePerkDamage(base) local valfunc = base and self.GetBaseValue or self.GetValue local stat = valfunc(self, "MeleePerkStr") if stat >= 0.5 then return Lerp((stat - 0.5) * 2, 1, 2) else return Lerp(stat * 2, 0.7, 1) end end function SWEP:GetMeleePerkCooldown(base) local valfunc = base and self.GetBaseValue or self.GetValue local stat = valfunc(self, "MeleePerkAgi") if stat >= 0.5 then return Lerp((stat - 0.5) * 2, 1, 0.7) else return Lerp(stat * 2, 1.3, 1) end end function SWEP:GetMeleePerkSpeed(base) local valfunc = base and self.GetBaseValue or self.GetValue local stat = valfunc(self, "MeleePerkAgi") if stat >= 0.5 then return Lerp((stat - 0.5) * 2, 1, 1.5) else return Lerp(stat * 2, 0.5, 1) end end function SWEP:GetMeleePerkVelocity(base) local valfunc = base and self.GetBaseValue or self.GetValue local stat = valfunc(self, "MeleePerkInt") if stat >= 0.5 then return Lerp((stat - 0.5) * 2, 1, 3) * valfunc(self, "MeleeThrowForce") else return Lerp(stat * 2, 0.5, 1) * valfunc(self, "MeleeThrowForce") end end hook.Add("PostEntityTakeDamage", "tacrp_melee", function(ent, dmg, took) if ent.TacRPBashSlow then if took and (!ent:IsPlayer() or (ent:IsPlayer() and !(IsValid(ent:GetActiveWeapon()) and ent:GetActiveWeapon().ArcticTacRP and ent:GetActiveWeapon():GetValue("StunResist")))) then ent:SetNWFloat("TacRPLastBashed", CurTime()) end ent.TacRPBashSlow = false end local wep = dmg:GetInflictor() if (!IsValid(wep) or !wep:IsWeapon()) and IsValid(dmg:GetAttacker()) and dmg:GetAttacker():IsPlayer() then wep = dmg:GetAttacker():GetActiveWeapon() end if took and (ent:IsPlayer() or ent:IsNPC() or ent:IsNextBot()) and IsValid(wep) and wep.ArcticTacRP then if (wep:GetValue("Lifesteal") or 0) > 0 then wep:GetOwner():SetHealth(math.min(math.max(wep:GetOwner():GetMaxHealth(), wep:GetOwner():Health()), wep:GetOwner():Health() + dmg:GetDamage() * wep:GetValue("Lifesteal"))) end if (wep:GetValue("DamageCharge") or 0) > 0 then wep:SetBreath(math.min(1, wep:GetBreath() + dmg:GetDamage() * wep:GetValue("DamageCharge"))) end end end)