Files
VnUtest/garrysmod/addons/tfa_base/lua/weapons/tfa_bash_base.lua
2026-03-31 10:27:04 +03:00

235 lines
6.4 KiB
Lua

if SERVER then
AddCSLuaFile()
end
DEFINE_BASECLASS("tfa_gun_base")
SWEP.Secondary.BashDamage = 25
SWEP.Secondary.BashSound = Sound("TFA.Bash")
SWEP.Secondary.BashHitSound = Sound("TFA.BashWall")
SWEP.Secondary.BashHitSound_Flesh = Sound("TFA.BashFlesh")
SWEP.Secondary.BashLength = 54
SWEP.Secondary.BashDelay = 0.2
SWEP.Secondary.BashDamageType = DMG_SLASH
SWEP.Secondary.BashEnd = nil --Override bash sequence length easier
SWEP.Secondary.BashInterrupt = false --Do you need to be in a "ready" status to bash?
SWEP.BashBase = true
function SWEP:BashForce(ent, force, pos, now)
if not IsValid(ent) or not ent.GetPhysicsObjectNum then return end
if now then
if ent.GetRagdollEntity then
ent = ent:GetRagdollEntity() or ent
end
local phys = ent:GetPhysicsObjectNum(0)
if IsValid(phys) then
if ent:IsPlayer() or ent:IsNPC() then
ent:SetVelocity( force * 0.1)
phys:SetVelocity(phys:GetVelocity() + force * 0.1)
else
phys:ApplyForceOffset(force, pos)
end
end
else
timer.Simple(0, function()
if IsValid(self) and self:OwnerIsValid() and IsValid(ent) then
self:BashForce(ent, force, pos, true)
end
end)
end
end
local cv_doordestruction = GetConVar("sv_tfa_melee_doordestruction")
function SWEP:HandleDoor(slashtrace)
if CLIENT or not IsValid(slashtrace.Entity) then return end
if not cv_doordestruction:GetBool() then return end
if slashtrace.Entity:GetClass() == "func_door_rotating" or slashtrace.Entity:GetClass() == "prop_door_rotating" then
slashtrace.Entity:EmitSound("ambient/materials/door_hit1.wav", 100, math.random(80, 120))
local newname = "TFABash" .. self:EntIndex()
self.PreBashName = self:GetName()
self:SetName(newname)
slashtrace.Entity:SetKeyValue("Speed", "500")
slashtrace.Entity:SetKeyValue("Open Direction", "Both directions")
slashtrace.Entity:SetKeyValue("opendir", "0")
slashtrace.Entity:Fire("unlock", "", .01)
slashtrace.Entity:Fire("openawayfrom", newname, .01)
timer.Simple(0.02, function()
if not IsValid(self) or self:GetName() ~= newname then return end
self:SetName(self.PreBashName)
end)
timer.Simple(0.3, function()
if IsValid(slashtrace.Entity) then
slashtrace.Entity:SetKeyValue("Speed", "100")
end
end)
end
end
local l_CT = CurTime
local sp = game.SinglePlayer()
function SWEP:AltAttack()
local time = l_CT()
if
self:GetStatL("Secondary.CanBash") == false or
not self:OwnerIsValid() or
time < self:GetNextSecondaryFire()
then return end
local stat = self:GetStatus()
if not TFA.Enum.ReadyStatus[stat] and not self:GetStatL("Secondary.BashInterrupt") or
stat == TFA.Enum.STATUS_BASHING and self:GetStatL("Secondary.BashInterrupt") then return end
if self:IsSafety() or self:GetHolding() then return end
local retVal = hook.Run("TFA_CanBash", self)
if retVal == false then return end
local enabled, tanim, ttype = self:ChooseBashAnim()
if not enabled then return end
hook.Run("TFA_Bash", self)
if self:GetOwner().Vox and IsFirstTimePredicted() then
self:GetOwner():Vox("bash", 0)
end
self:BashAnim()
if sp and SERVER then self:CallOnClient("BashAnim", "") end
local bashend = self:GetStatL("Secondary.BashEnd")
local nextTime = time + (bashend or self:GetActivityLength(tanim, false, ttype))
self:SetNextPrimaryFire(nextTime)
self:SetNextSecondaryFire(nextTime)
self:EmitSoundNet(self:GetStatL("Secondary.BashSound"))
self:ScheduleStatus(TFA.Enum.STATUS_BASHING, self:GetStatL("Secondary.BashDelay"))
hook.Run("TFA_PostBash", self)
end
function SWEP:BashAnim()
if not IsFirstTimePredicted() then return end
local ht = self.DefaultHoldType or self.HoldType
local altanim = false
if ht == "ar2" or ht == "shotgun" or ht == "crossbow" or ht == "physgun" then
altanim = true
end
self:GetOwner():AnimRestartGesture(0, altanim and ACT_GMOD_GESTURE_MELEE_SHOVE_2HAND or ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE2, true)
end
local ttime = -1
function SWEP:HandleBashAttack()
local ply = self:GetOwner()
local pos = ply:GetShootPos()
local av = ply:GetAimVector()
local slash = {}
slash.start = pos
slash.endpos = pos + (av * self:GetStatL("Secondary.BashLength"))
slash.filter = ply
slash.mins = Vector(-10, -5, 0)
slash.maxs = Vector(10, 5, 5)
local slashtrace = util.TraceHull(slash)
local pain = self:GetStatL("Secondary.BashDamage")
if not slashtrace.Hit then return end
self:HandleDoor(slashtrace)
if not (sp and CLIENT) then
self:EmitSound(
(slashtrace.MatType == MAT_FLESH or slashtrace.MatType == MAT_ALIENFLESH) and
self:GetStatL("Secondary.BashHitSound_Flesh") or
self:GetStatL("Secondary.BashHitSound"))
end
if CLIENT then return end
local dmg = DamageInfo()
dmg:SetAttacker(ply)
dmg:SetInflictor(self)
dmg:SetDamagePosition(pos)
dmg:SetDamageForce(av * pain)
dmg:SetDamage(pain)
dmg:SetDamageType(self:GetStatL("Secondary.BashDamageType"))
if IsValid(slashtrace.Entity) and slashtrace.Entity.TakeDamageInfo then
slashtrace.Entity:TakeDamageInfo(dmg)
end
local ent = slashtrace.Entity
if not IsValid(ent) or not ent.GetPhysicsObject then return end
local phys
if ent:IsRagdoll() then
phys = ent:GetPhysicsObjectNum(slashtrace.PhysicsBone or 0)
else
phys = ent:GetPhysicsObject()
end
if IsValid(phys) then
if ent:IsPlayer() or ent:IsNPC() then
ent:SetVelocity(av * self:GetStatL("Secondary.BashDamage") * 0.5)
phys:SetVelocity(phys:GetVelocity() + av * self:GetStatL("Secondary.BashDamage") * 0.5)
else
phys:ApplyForceOffset(av * self:GetStatL("Secondary.BashDamage") * 0.5, slashtrace.HitPos)
end
end
end
function SWEP:Think2(...)
if self:GetStatus() == TFA.Enum.STATUS_BASHING and self:GetStatusEnd() < l_CT() then
self:SetStatus(TFA.Enum.STATUS_BASHING_WAIT, self:GetNextSecondaryFire())
if IsFirstTimePredicted() then
self:HandleBashAttack()
end
end
BaseClass.Think2(self, ...)
end
function SWEP:SecondaryAttack()
if not self:GetStatL("Secondary.IronSightsEnabled", false) then
self:AltAttack()
return
end
BaseClass.SecondaryAttack(self)
end
function SWEP:GetBashing()
local stat = self:GetStatus()
if not self:VMIV() then
return stat == TFA.Enum.STATUS_BASHING or stat == TFA.Enum.STATUS_BASHING_WAIT
end
return (stat == TFA.Enum.STATUS_BASHING or stat == TFA.Enum.STATUS_BASHING_WAIT) and self.OwnerViewModel:GetCycle() > 0 and self.OwnerViewModel:GetCycle() < 0.65
end
function SWEP:GetBashingStrict()
local stat = self:GetStatus()
return stat == TFA.Enum.STATUS_BASHING or stat == TFA.Enum.STATUS_BASHING_WAIT
end
TFA.FillMissingMetaValues(SWEP)