mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
256 lines
8.4 KiB
Lua
256 lines
8.4 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
|
|
-- Copyright (c) 2018-2020 TFA Base Devs
|
|
|
|
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
-- of this software and associated documentation files (the "Software"), to deal
|
|
-- in the Software without restriction, including without limitation the rights
|
|
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
-- copies of the Software, and to permit persons to whom the Software is
|
|
-- furnished to do so, subject to the following conditions:
|
|
|
|
-- The above copyright notice and this permission notice shall be included in all
|
|
-- copies or substantial portions of the Software.
|
|
|
|
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
-- SOFTWARE.
|
|
|
|
local vector_origin = Vector()
|
|
|
|
local timed_blocking_cv = GetConVar("sv_tfa_melee_blocking_timed")
|
|
local angle_mult_cv = GetConVar("sv_tfa_melee_blocking_anglemult")
|
|
local deflect_cv = GetConVar("sv_tfa_melee_blocking_deflection")
|
|
local stun_cv = GetConVar("sv_tfa_melee_blocking_stun_enabled")
|
|
local stuntime_cv = GetConVar("sv_tfa_melee_blocking_stun_time")
|
|
|
|
local bul = {
|
|
HullSize = 5,
|
|
Num = 1,
|
|
Tracer = 1,
|
|
AmmoType = "",
|
|
TracerName = "Tracer",
|
|
Spread = Vector(0.05,0.05,0),
|
|
Distance = 56756
|
|
}
|
|
|
|
local function CanDeflect()
|
|
return true
|
|
end
|
|
|
|
local function DeflectBullet( ent, dmginfo, olddmg )
|
|
if dmginfo:IsDamageType( DMG_BULLET ) and CanDeflect() and ent.FireBullets then
|
|
bul.Src = ent:GetShootPos()
|
|
bul.Dir = ent:EyeAngles():Forward()
|
|
bul.Damage = olddmg
|
|
bul.Force = olddmg / 10
|
|
local atk = dmginfo:GetAttacker()
|
|
if IsValid( atk ) and atk.TFALastTracer then
|
|
bul.Tracer = atk.TFALastTracer
|
|
end
|
|
ent:FireBullets( bul, false )
|
|
dmginfo:ScaleDamage(0)
|
|
end
|
|
end
|
|
|
|
local stuntime = 0.65
|
|
|
|
local function StunNPC( npc, ply )
|
|
if stun_cv and not stun_cv:GetBool() then return end
|
|
if ( not IsValid( npc ) ) or ( not npc:IsNPC() ) then
|
|
return
|
|
end
|
|
if npc.ClearSchedule then
|
|
npc:ClearSchedule()
|
|
end
|
|
if npc.SetEnemy then
|
|
npc:SetEnemy(nil)
|
|
end
|
|
if npc.AddEntityRelationship and IsValid(ply) then
|
|
local oldrel = npc.GetRelationship and npc:GetRelationship(ply) or D_HT
|
|
npc:AddEntityRelationship( ply, D_NU, 99)
|
|
stuntime = stuntime_cv:GetFloat()
|
|
timer.Simple( stuntime , function()
|
|
if IsValid(npc) and npc:IsNPC() and IsValid(ply) then
|
|
npc:AddEntityRelationship( ply, oldrel, 99)
|
|
end
|
|
end)
|
|
end
|
|
if npc.ClearEnemyMemory then
|
|
npc:ClearEnemyMemory()
|
|
end
|
|
end
|
|
|
|
local function BlockDamageNew( ent, dmginfo )
|
|
if not ent:IsPlayer() then return end
|
|
if dmginfo:IsDamageType( DMG_DROWNRECOVER ) or dmginfo:IsDamageType(DMG_DIRECT) then return end
|
|
local wep
|
|
wep = ent:GetActiveWeapon()
|
|
|
|
if (wep.IsTFAWeapon and wep.BlockDamageTypes and wep:GetStatus() == TFA.Enum.STATUS_BLOCKING) then
|
|
local canblock = false
|
|
for _,v in ipairs(wep.BlockDamageTypes) do
|
|
if dmginfo:IsDamageType(v) then canblock = true end
|
|
end
|
|
if canblock then
|
|
local damageinflictor, blockthreshold
|
|
damageinflictor = dmginfo:GetInflictor()
|
|
|
|
if (not IsValid(damageinflictor)) then
|
|
damageinflictor = dmginfo:GetAttacker()
|
|
end
|
|
|
|
blockthreshold = ( wep.BlockCone or 135 ) / 2
|
|
if angle_mult_cv then
|
|
blockthreshold = blockthreshold * angle_mult_cv:GetFloat()
|
|
end
|
|
if ( IsValid(damageinflictor) and ( math.abs(math.AngleDifference( ent:EyeAngles().y, ( damageinflictor:GetPos() - ent:GetPos() ):Angle().y )) <= blockthreshold)) then
|
|
local fac = math.Clamp( ( CurTime() - wep:GetBlockStart() - wep.BlockTimeWindow ) / wep.BlockTimeFade, 0, 1)
|
|
local dmgscale
|
|
if ( not timed_blocking_cv ) or timed_blocking_cv:GetBool() then
|
|
dmgscale = Lerp(fac, wep.BlockDamageMaximum, wep.BlockDamageMinimum)
|
|
else
|
|
dmgscale = wep.BlockDamageMaximum
|
|
end
|
|
local olddmg = dmginfo:GetDamage()
|
|
dmgscale = math.min( dmgscale, wep.BlockDamageCap / dmginfo:GetDamage() )
|
|
--print(fac)
|
|
dmginfo:ScaleDamage(dmgscale)
|
|
dmginfo:SetDamagePosition(vector_origin)
|
|
dmginfo:SetDamageType( bit.bor( dmginfo:GetDamageType(), DMG_DROWNRECOVER ) )
|
|
wep:EmitSound(wep.BlockSound or "")
|
|
|
|
if wep.ChooseBlockAnimation then
|
|
wep:ChooseBlockAnimation()
|
|
end
|
|
|
|
if deflect_cv and deflect_cv:GetInt() == 2 then
|
|
DeflectBullet( ent, dmginfo, olddmg )
|
|
end
|
|
|
|
if dmginfo:GetDamage() < 1 then
|
|
if deflect_cv and deflect_cv:GetInt() == 1 and wep.BlockCanDeflect then
|
|
DeflectBullet( ent, dmginfo, olddmg )
|
|
end
|
|
StunNPC( dmginfo:GetAttacker(), ent )
|
|
return true
|
|
end
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
hook.Add("EntityFireBullets","TFA_Melee_LogTracer",function(ent,bulv) --Record tracer for blocking
|
|
ent.TFALastTracer = bulv.TracerName or ""
|
|
end)
|
|
|
|
local npc_dmg_scale_cv = GetConVar("sv_tfa_melee_damage_npc")
|
|
local ply_dmg_scale_cv = GetConVar("sv_tfa_melee_damage_ply")
|
|
|
|
hook.Add("EntityTakeDamage", "TFA_Melee_Scaling", function( ent, dmginfo )
|
|
local wep = dmginfo:GetInflictor()
|
|
if not IsValid(wep) then return end
|
|
if wep:IsPlayer() then wep = wep:GetActiveWeapon() end
|
|
if not IsValid(wep) or not wep:IsWeapon() then return end
|
|
if not wep.BlockDamageCap then return end
|
|
if ent:IsNPC() then
|
|
dmginfo:ScaleDamage( npc_dmg_scale_cv:GetFloat() )
|
|
elseif ent:IsPlayer() then
|
|
dmginfo:ScaleDamage( ply_dmg_scale_cv:GetFloat() )
|
|
end
|
|
end) --Cancel
|
|
hook.Add("EntityTakeDamage", "aaa_TFA_Melee_Block", function( ent, dmginfo )
|
|
return BlockDamageNew( ent, dmginfo )
|
|
end) --Cancel
|
|
hook.Add("ScalePlayerDamage", "aaa_TFA_Melee_Block", function( ent, _, dmginfo ) --Cancel
|
|
return BlockDamageNew( ent, dmginfo )
|
|
end)
|
|
|
|
game.AddAmmoType({
|
|
name = "TFMSwordHitGenericSlash",
|
|
dmgtype = DMG_SLASH,
|
|
tracer = TRACER_NONE
|
|
})
|
|
|
|
local function TFMPlayerSpawn(ply)
|
|
ply:SetNW2Vector("TFM_SwordPosition", Vector(1, 1, 1))
|
|
ply:SetNW2Vector("TFM_SwordNormal", Vector(1, 1, 1))
|
|
ply:SetNW2Bool("TFM_IsSprinting", false)
|
|
ply:SetNW2Bool("TFM_IsBlocking", false)
|
|
ply:SetNW2Bool("TFM_IsSwinging", false)
|
|
ply:SetNW2Float("TFM_SwingStart", CurTime())
|
|
end
|
|
|
|
hook.Add("PlayerSpawn", "TFM_PlayerSpawn", TFMPlayerSpawn)
|
|
|
|
hook.Add("EntityTakeDamage", "TFM_Block", function(ent, dmginfo) --Legacy
|
|
if ent:IsPlayer() then
|
|
local wep
|
|
wep = ent:GetActiveWeapon()
|
|
|
|
if (wep.IsTFAWeapon and wep.BlockAngle) and (dmginfo:IsDamageType(DMG_SLASH) or dmginfo:IsDamageType(DMG_CLUB) or (wep.NinjaMode and wep.NinjaMode == true and (dmginfo:IsDamageType(DMG_CRUSH) or dmginfo:IsDamageType(DMG_BULLET)))) and wep:GetIronSights() then
|
|
local damageinflictor, blockthreshold
|
|
damageinflictor = dmginfo:GetInflictor()
|
|
|
|
if (not IsValid(damageinflictor)) then
|
|
damageinflictor = dmginfo:GetAttacker()
|
|
end
|
|
|
|
blockthreshold = wep.BlockAngle / 2 or 90
|
|
|
|
if (IsValid(damageinflictor) and (math.abs((ent:GetAimVector():Angle() - (damageinflictor:GetPos() - ent:GetPos()):Angle()).y) <= blockthreshold)) or (math.abs((ent:GetAimVector():Angle() - (dmginfo:GetDamagePosition() - ent:GetPos()):Angle()).y) <= blockthreshold) then
|
|
local fac = math.Clamp((CurTime() - wep:GetBlockStart() - wep.BlockWindow) / wep.BlockFadeTime, 0, 1)
|
|
local dmgscale
|
|
if ( not timed_blocking_cv ) or timed_blocking_cv:GetBool() then
|
|
dmgscale = Lerp(fac, wep.BlockMaximum, wep.BlockMinimum)
|
|
else
|
|
dmgscale = wep.BlockMaximum
|
|
end
|
|
--print(fac)
|
|
dmginfo:ScaleDamage(dmgscale)
|
|
dmginfo:SetDamagePosition(vector_origin)
|
|
wep:EmitSound(wep.Primary.Sound_Impact_Metal)
|
|
|
|
if wep.BlockAnim then
|
|
wep:BlockAnim()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
--Getting the position and angle of an attachment and sending it back to the server is wayyy too laggy. Must be pre-coded.
|
|
--[[
|
|
if SERVER then
|
|
util.AddNetworkString( "TFM_SAPacket" )
|
|
net.Receive("TFM_SAPacket", function()
|
|
local ply;
|
|
ply = net.ReadEntity()
|
|
local pos;
|
|
pos = net.ReadVector()
|
|
local norm;
|
|
norm = net.ReadNormal()
|
|
if IsValid(ply) then
|
|
if pos and norm then
|
|
ply:SetNW2Vector("TFM_SwordPosition",pos)
|
|
ply:SetNW2Vector("TFM_SwordNormal",norm)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
]]
|
|
-- |