This commit is contained in:
lifestorm
2024-08-04 22:55:00 +03:00
parent 0e770b2b49
commit 94063e4369
7342 changed files with 1718932 additions and 14 deletions

View File

@@ -0,0 +1,60 @@
--[[
| 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.
include("shared.lua")
include("common/ai_translations.lua")
include("common/anims.lua")
include("common/autodetection.lua")
include("common/utils.lua")
include("common/stat.lua")
include("common/attachments.lua")
include("common/bullet.lua")
include("common/effects.lua")
include("common/calc.lua")
include("common/akimbo.lua")
include("common/events.lua")
include("common/nzombies.lua")
include("common/ttt.lua")
include("common/viewmodel.lua")
include("common/skins.lua")
include("client/effects.lua")
include("client/viewbob.lua")
include("client/viewmodel.lua")
include("client/bobcode.lua")
include("client/hud.lua")
include("client/mods.lua")
include("client/laser.lua")
include("client/fov.lua")
include("client/flashlight.lua")
TFA.FillMissingMetaValues(SWEP)

View File

@@ -0,0 +1,247 @@
--[[
| 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()
SWEP.ti = 0
SWEP.LastCalcBob = 0
SWEP.tiView = 0
SWEP.LastCalcViewBob = 0
local TAU = math.pi * 2
local rateScaleFac = 2
local rate_up = 6 * rateScaleFac
local scale_up = 0.5
local rate_right = 3 * rateScaleFac
local scale_right = -0.5
local rate_forward_view = 3 * rateScaleFac
local scale_forward_view = 0.35
local rate_right_view = 3 * rateScaleFac
local scale_right_view = -1
local rate_p = 6 * rateScaleFac
local scale_p = 3
local rate_y = 3 * rateScaleFac
local scale_y = 6
local rate_r = 3 * rateScaleFac
local scale_r = -6
local pist_rate = 3 * rateScaleFac
local pist_scale = 9
local rate_clamp = 2 * rateScaleFac
local walkIntensitySmooth, breathIntensitySmooth = 0, 0
local walkRate = 160 / 60 * TAU / 1.085 / 2 * rateScaleFac --steps are at 160bpm at default velocity, then divide that by 60 for per-second, multiply by TAU for trig, divided by default walk rate
local walkVec = Vector()
local ownerVelocity, ownerVelocityMod = Vector(), Vector()
local zVelocity, zVelocitySmooth = 0, 0
local xVelocity, xVelocitySmooth, rightVec = 0, 0, Vector()
local flatVec = Vector(1, 1, 0)
local WalkPos = Vector()
local WalkPosLagged = Vector()
local gunbob_intensity_cvar = GetConVar("cl_tfa_gunbob_intensity")
local gunbob_intensity = 0
SWEP.VMOffsetWalk = Vector(0.5, -0.5, -0.5)
SWEP.footstepTotal = 0
SWEP.footstepTotalTarget = 0
local upVec, riVec, fwVec = Vector(0, 0, 1), Vector(1, 0, 0), Vector(0, 1, 0)
local function l_Lerp(t, a, b)
if t <= 0 then return a end
if t >= 1 then return b end
return a + (b - a) * t
end
function SWEP:WalkBob(pos, ang, breathIntensity, walkIntensity, rate, ftv)
local self2 = self:GetTable()
if not self2.OwnerIsValid(self) then return end
rate = math.min(rate or 0.5, rate_clamp)
gunbob_intensity = gunbob_intensity_cvar:GetFloat()
local ea = self:GetOwner():EyeAngles()
local up = ang:Up()
local ri = ang:Right()
local fw = ang:Forward()
local upLocal = upVec
local riLocal = riVec
local fwLocal = fwVec
local delta = ftv
local flip_v = self2.ViewModelFlip and -1 or 1
--delta = delta * game.GetTimeScale()
--self2.LastCalcBob = SysTime()
self2.bobRateCached = rate
self2.ti = self2.ti + delta * rate
if self2.SprintStyle == nil then
if self:GetStatL("SprintViewModelAngle") and self:GetStatL("SprintViewModelAngle").x > 5 then
self2.SprintStyle = 1
else
self2.SprintStyle = 0
end
end
--preceding calcs
walkIntensitySmooth = l_Lerp(delta * 10 * rateScaleFac, walkIntensitySmooth, walkIntensity)
breathIntensitySmooth = l_Lerp(delta * 10 * rateScaleFac, breathIntensitySmooth, breathIntensity)
walkVec = LerpVector(walkIntensitySmooth, vector_origin, self2.VMOffsetWalk)
ownerVelocity = self:GetOwner():GetVelocity()
zVelocity = ownerVelocity.z
zVelocitySmooth = l_Lerp(delta * 7 * rateScaleFac, zVelocitySmooth, zVelocity)
ownerVelocityMod = ownerVelocity * flatVec
ownerVelocityMod:Normalize()
rightVec = ea:Right() * flatVec
rightVec:Normalize()
xVelocity = ownerVelocity:Length2D() * ownerVelocityMod:Dot(rightVec)
xVelocitySmooth = l_Lerp(delta * 5 * rateScaleFac, xVelocitySmooth, xVelocity)
--multipliers
breathIntensity = breathIntensitySmooth * gunbob_intensity * 1.5
walkIntensity = walkIntensitySmooth * gunbob_intensity * 1.5
--breathing / walking while ADS
local breatheMult2 = math.Clamp((self2.IronSightsProgressUnpredicted2 or self:GetIronSightsProgress()), 0, 1)
--local breatheMult2 = 0
local breatheMult1 = 1 - breatheMult2
--local breatheMult1 = 1
pos:Add(riLocal * (math.sin(self2.ti * walkRate) - math.cos(self2.ti * walkRate)) * flip_v * breathIntensity * 0.2 * breatheMult1)
pos:Add(upLocal * math.sin(self2.ti * walkRate) * breathIntensity * 0.5 * breatheMult1)
pos:Add(riLocal * math.cos(self2.ti * walkRate / 2) * flip_v * breathIntensity * 0.6 * breatheMult2)
pos:Add(upLocal * math.sin(self2.ti * walkRate) * breathIntensity * 0.3 * breatheMult2)
--walk anims, danny method because i just can't
self2.walkTI = (self2.walkTI or 0) + delta * 160 / 60 * self:GetOwner():GetVelocity():Length2D() / self:GetOwner():GetWalkSpeed()
WalkPos.x = l_Lerp(delta * 5 * rateScaleFac, WalkPos.x, -math.sin(self2.ti * walkRate * 0.5) * gunbob_intensity * walkIntensity)
WalkPos.y = l_Lerp(delta * 5 * rateScaleFac, WalkPos.y, math.sin(self2.ti * walkRate) / 1.5 * gunbob_intensity * walkIntensity)
WalkPosLagged.x = l_Lerp(delta * 5 * rateScaleFac, WalkPosLagged.x, -math.sin((self2.ti * walkRate * 0.5) + math.pi / 3) * gunbob_intensity * walkIntensity)
WalkPosLagged.y = l_Lerp(delta * 5 * rateScaleFac, WalkPosLagged.y, math.sin(self2.ti * walkRate + math.pi / 3) / 1.5 * gunbob_intensity * walkIntensity)
pos:Add(WalkPos.x * 0.33 * riLocal)
pos:Add(WalkPos.y * 0.25 * upLocal)
ang:RotateAroundAxis(ri, -WalkPosLagged.y)
ang:RotateAroundAxis(up, WalkPosLagged.x)
ang:RotateAroundAxis(fw, WalkPos.x)
--constant offset
pos:Add(riLocal * walkVec.x * flip_v)
pos:Add(fwLocal * walkVec.y)
pos:Add(upLocal * walkVec.z)
--jumping
local trigX = -math.Clamp(zVelocitySmooth / 200, -1, 1) * math.pi / 2
local jumpIntensity = (3 + math.Clamp(math.abs(zVelocitySmooth) - 100, 0, 200) / 200 * 4) * (1 - (self2.IronSightsProgressUnpredicted or self:GetIronSightsProgress()) * 0.8)
pos:Add(ri * math.sin(trigX) * scale_r * 0.1 * jumpIntensity * flip_v * 0.4)
pos:Add(-up * math.sin(trigX) * scale_r * 0.1 * jumpIntensity * 0.4)
ang:RotateAroundAxis(ang:Forward(), math.sin(trigX) * scale_r * jumpIntensity * flip_v * 0.4)
--rolling with horizontal motion
local xVelocityClamped = xVelocitySmooth
if math.abs(xVelocityClamped) > 200 then
local sign = (xVelocityClamped < 0) and -1 or 1
xVelocityClamped = (math.sqrt((math.abs(xVelocityClamped) - 200) / 50) * 50 + 200) * sign
end
ang:RotateAroundAxis(ang:Forward(), xVelocityClamped * 0.04 * flip_v)
return pos, ang
end
function SWEP:SprintBob(pos, ang, intensity, origPos, origAng)
local self2 = self:GetTable()
if not IsValid(self:GetOwner()) or not gunbob_intensity then return pos, ang end
local flip_v = self2.ViewModelFlip and -1 or 1
local eyeAngles = self:GetOwner():EyeAngles()
local localUp = ang:Up()
local localRight = ang:Right()
local localForward = ang:Forward()
local playerUp = eyeAngles:Up()
local playerRight = eyeAngles:Right()
local playerForward = eyeAngles:Forward()
intensity = intensity * gunbob_intensity * 1.5
gunbob_intensity = gunbob_intensity_cvar:GetFloat()
if intensity > 0.005 then
if self2.SprintStyle == 1 then
local intensity3 = math.max(intensity - 0.3, 0) / (1 - 0.3)
ang:RotateAroundAxis(ang:Up(), math.sin(self2.ti * pist_rate) * pist_scale * intensity3 * 0.33 * 0.75)
ang:RotateAroundAxis(ang:Forward(), math.sin(self2.ti * pist_rate) * pist_scale * intensity3 * 0.33 * -0.25)
pos:Add(ang:Forward() * math.sin(self2.ti * pist_rate * 2 + math.pi) * pist_scale * -0.1 * intensity3 * 0.4)
pos:Add(ang:Right() * math.sin(self2.ti * pist_rate) * pist_scale * 0.15 * intensity3 * 0.33 * 0.2)
else
pos:Add(localUp * math.sin(self2.ti * rate_up + math.pi) * scale_up * intensity * 0.33)
pos:Add(localRight * math.sin(self2.ti * rate_right) * scale_right * intensity * flip_v * 0.33)
pos:Add(eyeAngles:Forward() * math.max(math.sin(self2.ti * rate_forward_view), 0) * scale_forward_view * intensity * 0.33)
pos:Add(eyeAngles:Right() * math.sin(self2.ti * rate_right_view) * scale_right_view * intensity * flip_v * 0.33)
ang:RotateAroundAxis(localRight, math.sin(self2.ti * rate_p + math.pi) * scale_p * intensity * 0.33)
pos:Add(-localUp * math.sin(self2.ti * rate_p + math.pi) * scale_p * 0.1 * intensity * 0.33)
ang:RotateAroundAxis(localUp, math.sin(self2.ti * rate_y) * scale_y * intensity * flip_v * 0.33)
pos:Add(localRight * math.sin(self2.ti * rate_y) * scale_y * 0.1 * intensity * flip_v * 0.33)
ang:RotateAroundAxis(localForward, math.sin(self2.ti * rate_r) * scale_r * intensity * flip_v * 0.33)
pos:Add(localRight * math.sin(self2.ti * rate_r) * scale_r * 0.05 * intensity * flip_v * 0.33)
pos:Add(localUp * math.sin(self2.ti * rate_r) * scale_r * 0.1 * intensity * 0.33)
end
end
return pos, ang
end
local cv_customgunbob = GetConVar("cl_tfa_gunbob_custom")
local fac, bscale
function SWEP:UpdateEngineBob()
local self2 = self:GetTable()
if cv_customgunbob:GetBool() then
self2.BobScale = 0
self2.SwayScale = 0
return
end
local isp = self2.IronSightsProgressUnpredicted or self:GetIronSightsProgress()
local wpr = self2.WalkProgressUnpredicted or self:GetWalkProgress()
local spr = self:GetSprintProgress()
fac = gunbob_intensity_cvar:GetFloat() * ((1 - isp) * 0.85 + 0.15)
bscale = fac
if spr > 0.005 then
bscale = bscale * l_Lerp(spr, 1, self2.SprintBobMult)
elseif wpr > 0.005 then
bscale = bscale * l_Lerp(wpr, 1, l_Lerp(isp, self2.WalkBobMult, self2.WalkBobMult_Iron or self2.WalkBobMult))
end
self2.BobScale = bscale
self2.SwayScale = fac
end

View File

@@ -0,0 +1,202 @@
--[[
| 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_up = Vector(0, 0, 1)
local math = math
local render = render
local LerpVector = LerpVector
--[[
Function Name: ComputeSmokeLighting
Syntax: self:ComputeSmokeLighting(pos, nrm, pcf).
Returns: Nothing.
Notes: Used to light the muzzle smoke trail, by setting its PCF Control Point 1
Purpose: FX
]]--
function SWEP:ComputeSmokeLighting( pos, nrm, pcf )
if not IsValid(pcf) then return end
local licht = render.ComputeLighting(pos, nrm)
local lichtFloat = math.Clamp((licht.r + licht.g + licht.b) / 3, 0, TFA.Particles.SmokeLightingClamp) / TFA.Particles.SmokeLightingClamp
local lichtFinal = LerpVector(lichtFloat, TFA.Particles.SmokeLightingMin, TFA.Particles.SmokeLightingMax)
pcf:SetControlPoint(1, lichtFinal)
end
--[[
Function Name: SmokePCFLighting
Syntax: self:SmokePCFLighting().
Returns: Nothing.
Notes: Used to loop through all of our SmokePCF tables and call ComputeSmokeLighting on them
Purpose: FX
]]--
function SWEP:SmokePCFLighting()
local mzPos = self:GetMuzzlePos()
if not mzPos or not mzPos.Pos then return end
local pos = mzPos.Pos
if self.SmokePCF then
for _, v in pairs(self.SmokePCF) do
self:ComputeSmokeLighting(pos, vector_up, v)
end
end
if not self:VMIV() then return end
local vm = self.OwnerViewModel
if vm.SmokePCF then
for _, v in pairs(vm.SmokePCF) do
self:ComputeSmokeLighting(pos, vector_up, v)
end
end
end
--[[
Function Name: FireAnimationEvent
Syntax: self:FireAnimationEvent( position, angle, event id, options).
Returns: Nothing.
Notes: Used to capture and disable viewmodel animation events, unless you disable that feature.
Purpose: FX
]]--
function SWEP:FireAnimationEvent(pos, ang, event, options)
if self.CustomMuzzleFlash or not self.MuzzleFlashEnabled then
-- Disables animation based muzzle event
if (event == 21) then return true end
-- Disable thirdperson muzzle flash
if (event == 5003) then return true end
-- Disable CS-style muzzle flashes, but chance our muzzle flash attachment if one is given.
if (event == 5001 or event == 5011 or event == 5021 or event == 5031) then
if self.AutoDetectMuzzleAttachment then
self.MuzzleAttachmentRaw = math.Clamp(math.floor((event - 4991) / 10), 1, 4)
self:ShootEffectsCustom(true)
end
return true
end
end
if (self.LuaShellEject and event ~= 5004) then return true end
end
--[[
Function Name: MakeMuzzleSmoke
Syntax: self:MakeMuzzleSmoke( entity, attachment).
Returns: Nothing.
Notes: Deprecated. Used to make the muzzle smoke effect, clientside.
Purpose: FX
]]--
local limit_particle_cv = GetConVar("cl_tfa_fx_muzzlesmoke_limited")
function SWEP:MakeMuzzleSmoke(entity, attachment)
if ( not limit_particle_cv ) or limit_particle_cv:GetBool() then
self:CleanParticles()
end
local ht = self.DefaultHoldType and self.DefaultHoldType or self.HoldType
if (CLIENT and TFA.GetMZSmokeEnabled() and IsValid(entity) and attachment and attachment ~= 0) then
ParticleEffectAttach(self.SmokeParticles[ht], PATTACH_POINT_FOLLOW, entity, attachment)
end
end
--[[
Function Name: ImpactEffect
Syntax: self:ImpactEffect( position, normal (ang:Up()), materialt ype).
Returns: Nothing.
Notes: Used to make the impact effect. See utilities code for CanDustEffect.
Purpose: FX
]]--
function SWEP:DoImpactEffect(tr, dmgtype)
if tr.HitSky then return true end
local ib = self.BashBase and IsValid(self) and self:GetBashing()
local dmginfo = DamageInfo()
dmginfo:SetDamageType(dmgtype)
if dmginfo:IsDamageType(DMG_SLASH) or (ib and self.Secondary_TFA.BashDamageType == DMG_SLASH and tr.MatType ~= MAT_FLESH and tr.MatType ~= MAT_ALIENFLESH) or (self and self.DamageType and self.DamageType == DMG_SLASH) then
util.Decal("ManhackCut", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal)
return true
end
if ib and self.Secondary_TFA.BashDamageType == DMG_GENERIC then return true end
if ib then return end
if IsValid(self) then
self:ImpactEffectFunc(tr.HitPos, tr.HitNormal, tr.MatType)
end
if self.ImpactDecal and self.ImpactDecal ~= "" then
util.Decal(self.ImpactDecal, tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal)
return true
end
end
local impact_cl_enabled = GetConVar("cl_tfa_fx_impact_enabled")
local impact_sv_enabled = GetConVar("sv_tfa_fx_impact_override")
function SWEP:ImpactEffectFunc(pos, normal, mattype)
local enabled
if impact_cl_enabled then
enabled = impact_cl_enabled:GetBool()
else
enabled = true
end
if impact_sv_enabled and impact_sv_enabled:GetInt() >= 0 then
enabled = impact_sv_enabled:GetBool()
end
if enabled then
local fx = EffectData()
fx:SetOrigin(pos)
fx:SetNormal(normal)
if self:CanDustEffect(mattype) then
TFA.Effects.Create("tfa_dust_impact", fx)
end
if self:CanSparkEffect(mattype) then
TFA.Effects.Create("tfa_metal_impact", fx)
end
local scal = math.sqrt(self:GetStatL("Primary.Damage") / 30)
if mattype == MAT_FLESH then
scal = scal * 0.25
end
fx:SetEntity(self:GetOwner())
fx:SetMagnitude(mattype or 0)
fx:SetScale( scal )
TFA.Effects.Create("tfa_bullet_impact", fx)
if self.ImpactEffect then
TFA.Effects.Create(self.ImpactEffect, fx)
end
end
end

View File

@@ -0,0 +1,213 @@
--[[
| 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 att, angpos, attname, elemname, targetent
SWEP.FlashlightDistance = 12 * 50 -- default 50 feet
SWEP.FlashlightAttachment = 0
SWEP.FlashlightBrightness = 1
SWEP.FlashlightFOV = 60
local Material = Material
local ProjectedTexture = ProjectedTexture
local math = math
local function IsHolstering(wep)
if IsValid(wep) and TFA.Enum.HolsterStatus[wep:GetStatus()] then return true end
return false
end
-- TODO: This seems to be *extremely* similar to drawlaser
-- Should we merge them?
function SWEP:DrawFlashlight(is_vm)
local self2 = self:GetTable()
if not self2.FlashlightDotMaterial then
self2.FlashlightDotMaterial = Material(self2.GetStatL(self, "FlashlightMaterial") or "effects/flashlight001")
end
local ply = self:GetOwner()
if not IsValid(ply) then return end
if not self:GetFlashlightEnabled() then
self:CleanFlashlight()
return
end
if is_vm then
if not self:VMIV() then
self:CleanFlashlight()
return
end
targetent = ply:GetViewModel()
elemname = self2.GetStatL(self, "Flashlight_VElement", self2.GetStatL(self, "Flashlight_Element"))
local ViewModelElements = self:GetStatRaw("ViewModelElements", TFA.LatestDataVersion)
if elemname and ViewModelElements[elemname] and IsValid(ViewModelElements[elemname].curmodel) then
targetent = ViewModelElements[elemname].curmodel
end
att = self2.GetStatL(self, "FlashlightAttachment")
attname = self2.GetStatL(self, "FlashlightAttachmentName")
if attname then
att = targetent:LookupAttachment(attname)
end
if (not att) or att <= 0 then
self:CleanFlashlight()
return
end
angpos = targetent:GetAttachment(att)
if not angpos then
self:CleanFlashlight()
return
end
if self2.FlashlightISMovement and self2.CLIronSightsProgress > 0 then
local isang = self2.GetStatL(self, "IronSightsAngle")
angpos.Ang:RotateAroundAxis(angpos.Ang:Right(), isang.y * (self2.ViewModelFlip and -1 or 1) * self2.CLIronSightsProgress)
angpos.Ang:RotateAroundAxis(angpos.Ang:Up(), -isang.x * self2.CLIronSightsProgress)
end
local localProjAng = select(2, WorldToLocal(vector_origin, angpos.Ang, vector_origin, EyeAngles()))
localProjAng.p = localProjAng.p * ply:GetFOV() / self2.ViewModelFOV
localProjAng.y = localProjAng.y * ply:GetFOV() / self2.ViewModelFOV
local wsProjAng = select(2, LocalToWorld(vector_origin, localProjAng, vector_origin, EyeAngles())) --reprojection for view angle
if not IsValid(ply.TFAFlashlightGun) and not IsHolstering(self) then
local lamp = ProjectedTexture()
ply.TFAFlashlightGun = lamp
lamp:SetTexture(self2.FlashlightDotMaterial:GetString("$basetexture"))
lamp:SetFarZ(self2.GetStatL(self, "FlashlightDistance")) -- How far the light should shine
lamp:SetFOV(self2.GetStatL(self, "FlashlightFOV"))
lamp:SetPos(angpos.Pos)
lamp:SetAngles(angpos.Ang)
lamp:SetBrightness(self2.GetStatL(self, "FlashlightBrightness") * (0.9 + 0.1 * math.max(math.sin(CurTime() * 120), math.cos(CurTime() * 40))))
lamp:SetNearZ(1)
lamp:SetColor(color_white)
lamp:SetEnableShadows(true)
lamp:Update()
end
local lamp = ply.TFAFlashlightGun
if IsValid(lamp) then
lamp:SetPos(angpos.Pos)
lamp:SetAngles(wsProjAng)
lamp:SetBrightness(1.4 + 0.1 * math.max(math.sin(CurTime() * 120), math.cos(CurTime() * 40)))
lamp:Update()
end
return
end
targetent = self
elemname = self2.GetStatL(self, "Flashlight_WElement", self2.GetStatL(self, "Flashlight_Element"))
local WorldModelElements = self:GetStatRaw("WorldModelElements", TFA.LatestDataVersion)
if elemname and WorldModelElements[elemname] and IsValid(WorldModelElements[elemname].curmodel) then
targetent = WorldModelElements[elemname].curmodel
end
att = self2.GetStatL(self, "FlashlightAttachmentWorld", self2.GetStatL(self, "FlashlightAttachment"))
attname = self2.GetStatL(self, "FlashlightAttachmentNameWorld", self2.GetStatL(self, "FlashlightAttachmentName"))
if attname then
att = targetent:LookupAttachment(attname)
end
if (not att) or att <= 0 then
self:CleanFlashlight()
return
end
angpos = targetent:GetAttachment(att)
if not angpos then
angpos = targetent:GetAttachment(1)
end
if not angpos then
self:CleanFlashlight()
return
end
if not IsValid(ply.TFAFlashlightGun) and not IsHolstering(self) then
local lamp = ProjectedTexture()
ply.TFAFlashlightGun = lamp
lamp:SetTexture(self2.FlashlightDotMaterial:GetString("$basetexture"))
lamp:SetFarZ(self2.GetStatL(self, "FlashlightDistance")) -- How far the light should shine
lamp:SetFOV(self2.GetStatL(self, "FlashlightFOV"))
lamp:SetPos(angpos.Pos)
lamp:SetAngles(angpos.Ang)
lamp:SetBrightness(self2.GetStatL(self, "FlashlightBrightness") * (0.9 + 0.1 * math.max(math.sin(CurTime() * 120), math.cos(CurTime() * 40))))
lamp:SetNearZ(1)
lamp:SetColor(color_white)
lamp:SetEnableShadows(false)
lamp:Update()
end
local lamp = ply.TFAFlashlightGun
if IsValid(lamp) then
local lamppos = angpos.Pos
local ang = angpos.Ang
lamp:SetPos(lamppos)
lamp:SetAngles(ang)
lamp:SetBrightness(self2.GetStatL(self, "FlashlightBrightness") * (0.9 + 0.1 * math.max(math.sin(CurTime() * 120), math.cos(CurTime() * 40))))
lamp:Update()
end
end
function SWEP:CleanFlashlight()
local ply = self:GetOwner()
if IsValid(ply) and IsValid(ply.TFAFlashlightGun) then
ply.TFAFlashlightGun:Remove()
end
end

View File

@@ -0,0 +1,77 @@
--[[
| 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 LocalPlayer = LocalPlayer
local math = math
local function GetScreenAspectRatio()
return ScrW() / ScrH()
end
local function ScaleFOVByWidthRatio(fovDegrees, ratio)
local halfAngleRadians = fovDegrees * (0.5 * math.pi / 180.0)
local t = math.tan(halfAngleRadians)
t = t * ratio
local retDegrees = (180.0 / math.pi) * math.atan(t)
return retDegrees * 2.0
end
local default_fov_cv = GetConVar("default_fov")
function SWEP:GetTrueFOV()
local fov = TFADUSKFOV or default_fov_cv:GetFloat()
local ply = LocalPlayer()
if not ply:IsValid() then return fov end
if ply:GetFOV() < ply:GetDefaultFOV() - 1 then
fov = ply:GetFOV()
end
if TFADUSKFOV_FINAL then
fov = TFADUSKFOV_FINAL
end
return fov
end
function SWEP:GetViewModelFinalFOV()
local fov_default = default_fov_cv:GetFloat()
local fov = self:GetTrueFOV()
local flFOVOffset = fov_default - fov
local fov_vm = self.ViewModelFOV - flFOVOffset
local aspectRatio = GetScreenAspectRatio() * 0.75 -- (4/3)
--local final_fov = ScaleFOVByWidthRatio( fov, aspectRatio )
local final_fovViewmodel = ScaleFOVByWidthRatio(fov_vm, aspectRatio)
return final_fovViewmodel
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,244 @@
--[[
| 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 att, angpos, attname, elemname, targetent
local col = Color(255, 0, 0, 255)
local pc
local laserline
local laserdot
local laserFOV = 1.5
local traceres
local render = render
local Material = Material
local ProjectedTexture = ProjectedTexture
local math = math
SWEP.LaserDistance = 12 * 50 -- default 50 feet
SWEP.LaserDistanceVisual = 12 * 4 --default 4 feet
local function IsHolstering(wep)
if IsValid(wep) and TFA.Enum.HolsterStatus[wep:GetStatus()] then return true end
return false
end
function SWEP:DrawLaser(is_vm)
local self2 = self:GetTable()
if not laserline then
laserline = Material(self2.LaserLine or "cable/smoke")
end
if not laserdot then
laserdot = Material(self2.LaserDot or "effects/tfalaserdot")
end
local ply = self:GetOwner()
if not IsValid(ply) then return end
if ply:IsPlayer() then
local f = ply.GetNW2Vector or ply.GetNWVector
pc = f(ply, "TFALaserColor", vector_origin)
col.r = pc.x
col.g = pc.y
col.b = pc.z
else
col.r = 255
col.g = 0
col.b = 0
end
if is_vm then
if not self:VMIV() then
self:CleanLaser()
return
end
targetent = ply:GetViewModel()
elemname = self2.GetStatL(self, "LaserSight_VElement", self2.GetStatL(self, "LaserSight_Element"))
local ViewModelElements = self:GetStatRaw("ViewModelElements", TFA.LatestDataVersion)
if elemname and ViewModelElements[elemname] and IsValid(ViewModelElements[elemname].curmodel) then
targetent = ViewModelElements[elemname].curmodel
end
att = self2.GetStatL(self, "LaserSightAttachment")
attname = self2.GetStatL(self, "LaserSightAttachmentName")
if attname then
att = targetent:LookupAttachment(attname)
end
if (not att) or att <= 0 then
self:CleanLaser()
return
end
angpos = targetent:GetAttachment(att)
if not angpos then
self:CleanLaser()
return
end
if self2.LaserDotISMovement and self2.CLIronSightsProgress > 0 then
local isang = self2.GetStatL(self, "IronSightsAngle")
angpos.Ang:RotateAroundAxis(angpos.Ang:Right(), isang.y * (self2.ViewModelFlip and -1 or 1) * self2.CLIronSightsProgress)
angpos.Ang:RotateAroundAxis(angpos.Ang:Up(), -isang.x * self2.CLIronSightsProgress)
end
local localProjAng = select(2, WorldToLocal(vector_origin, angpos.Ang, vector_origin, EyeAngles()))
localProjAng.p = localProjAng.p * ply:GetFOV() / self2.ViewModelFOV
localProjAng.y = localProjAng.y * ply:GetFOV() / self2.ViewModelFOV
local wsProjAng = select(2, LocalToWorld(vector_origin, localProjAng, vector_origin, EyeAngles())) --reprojection for trace angle
traceres = util.QuickTrace(ply:GetShootPos(), wsProjAng:Forward() * 999999, ply)
if not IsValid(ply.TFALaserDot) and not IsHolstering(self) then
local lamp = ProjectedTexture()
ply.TFALaserDot = lamp
lamp:SetTexture(laserdot:GetString("$basetexture"))
lamp:SetFarZ(self2.LaserDistance) -- How far the light should shine
lamp:SetFOV(laserFOV)
lamp:SetPos(angpos.Pos)
lamp:SetAngles(angpos.Ang)
lamp:SetBrightness(5)
lamp:SetNearZ(1)
lamp:SetEnableShadows(false)
lamp:Update()
end
local lamp = ply.TFALaserDot
if IsValid(lamp) then
local lamppos = EyePos() + EyeAngles():Up() * 4
local ang = (traceres.HitPos - lamppos):Angle()
self2.laserpos_old = traceres.HitPos
ang:RotateAroundAxis(ang:Forward(), math.Rand(-180, 180))
lamp:SetPos(lamppos)
lamp:SetAngles(ang)
lamp:SetColor(col)
lamp:SetFOV(laserFOV * math.Rand(0.9, 1.1))
lamp:Update()
end
return
end
targetent = self
elemname = self2.GetStatL(self, "LaserSight_WElement", self2.GetStatL(self, "LaserSight_Element"))
local WorldModelElements = self:GetStatRaw("WorldModelElements", TFA.LatestDataVersion)
if elemname and WorldModelElements[elemname] and IsValid(WorldModelElements[elemname].curmodel) then
targetent = WorldModelElements[elemname].curmodel
end
att = self2.GetStatL(self, "LaserSightAttachmentWorld", self2.GetStatL(self, "LaserSightAttachment"))
attname = self2.GetStatL(self, "LaserSightAttachmentWorldName", self2.GetStatL(self, "LaserSightAttachmentName"))
if attname then
att = targetent:LookupAttachment(attname)
end
if (not att) or att <= 0 then
self:CleanLaser()
return
end
angpos = targetent:GetAttachment(att)
if not angpos then
angpos = targetent:GetAttachment(1)
end
if not angpos then
self:CleanLaser()
return
end
if not IsValid(ply.TFALaserDot) and not IsHolstering(self) then
local lamp = ProjectedTexture()
ply.TFALaserDot = lamp
lamp:SetTexture(laserdot:GetString("$basetexture"))
lamp:SetFarZ(self2.LaserDistance) -- How far the light should shine
lamp:SetFOV(laserFOV)
lamp:SetPos(angpos.Pos)
lamp:SetAngles(angpos.Ang)
lamp:SetBrightness(5)
lamp:SetNearZ(1)
lamp:SetEnableShadows(false)
lamp:Update()
end
local lamp = ply.TFALaserDot
if IsValid(lamp) then
local ang = angpos.Ang
ang:RotateAroundAxis(ang:Forward(), math.Rand(-180, 180))
lamp:SetPos(angpos.Pos)
lamp:SetAngles(ang)
lamp:SetColor(col)
lamp:SetFOV(laserFOV * math.Rand(0.9, 1.1))
lamp:Update()
end
traceres = util.QuickTrace(angpos.Pos, angpos.Ang:Forward() * self2.LaserDistance, ply)
local hpos = traceres.StartPos + angpos.Ang:Forward() * math.min(traceres.HitPos:Distance(angpos.Pos), self2.LaserDistanceVisual )
render.SetMaterial(laserline)
render.SetColorModulation(1, 1, 1)
render.StartBeam(2)
col.r = math.sqrt(col.r / 255) * 255
col.g = math.sqrt(col.g / 255) * 255
col.b = math.sqrt(col.b / 255) * 255
render.AddBeam(angpos.Pos, self2.LaserBeamWidth or 0.25, 0, col)
col.a = 0
render.AddBeam(hpos, 0, 0, col)
render.EndBeam()
end
function SWEP:CleanLaser()
local ply = self:GetOwner()
if IsValid(ply) and IsValid(ply.TFALaserDot) then
ply.TFALaserDot:Remove()
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,170 @@
--[[
| 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.
SWEP.SprintBobMult = 1.5 -- More is more bobbing, proportionally. This is multiplication, not addition. You want to make this > 1 probably for sprinting.
SWEP.IronBobMult = 0.0 -- More is more bobbing, proportionally. This is multiplication, not addition. You want to make this < 1 for sighting, 0 to outright disable.
SWEP.IronBobMultWalk = 0.2 -- More is more bobbing, proportionally. This is multiplication, not addition. You want to make this < 1 for sighting, 0 to outright disable.
SWEP.WalkBobMult = 1 -- More is more bobbing, proportionally. This is multiplication, not addition. You may want to disable it when using animated walk.
SWEP.SprintViewBobMult = 4
--[[
Function Name: CalcView
Syntax: Don't ever call this manually.
Returns: Nothing.
Notes: Used to calculate view angles.
Purpose: Feature
]]
--"
--[[
local ta = Angle()
local v = Vector()
local m_AD = math.AngleDifference
local m_NA = math.NormalizeAngle
local l_LA = function(t,a1,a2)
ta.p = m_NA( a1.p + m_AD(a2.p,a1.p) * t )
ta.y = m_NA( a1.y + m_AD(a2.y,a1.y) * t )
ta.r = m_NA( a1.r + m_AD(a2.r,a1.r) * t )
return ta
end
local l_LV = function(t,v1,v2)
v = v1 + ( v2 - v1 ) * t
return v * 1
end
]]
--
SWEP.ViewHolProg = 0
SWEP.AttachmentViewOffset = Angle(0, 0, 0)
SWEP.ProceduralViewOffset = Angle(0, 0, 0)
--local procedural_fadeout = 0.6
local procedural_vellimit = 5
local l_Lerp = Lerp
local l_mathApproach = math.Approach
local l_mathClamp = math.Clamp
local viewbob_intensity_cvar, viewbob_animated_cvar
viewbob_intensity_cvar = GetConVar("cl_tfa_viewbob_intensity")
viewbob_animated_cvar = GetConVar("cl_tfa_viewbob_animated")
local oldangtmp
local mzang_fixed
local mzang_fixed_last
local mzang_velocity = Angle()
local progress = 0
local targint, targbool
function SWEP:CalcView(ply, pos, ang, fov)
if not ang then return end
if ply ~= LocalPlayer() then return end
local vm = ply:GetViewModel()
if not IsValid(vm) then return end
local self2 = self:GetTable()
local ftv = math.max(TFA.FrameTime(), 0.001)
local viewbobintensity = viewbob_intensity_cvar:GetFloat() * 0.5
local holprog = TFA.Enum.HolsterStatus[self2.GetStatus(self)] and 1 or 0
self2.ViewHolProg = math.Approach(self2.ViewHolProg, holprog, ftv / 5)
oldangtmp = ang * 1
if self2.CameraAngCache and viewbob_animated_cvar:GetBool() then
self2.CameraAttachmentScale = self2.CameraAttachmentScale or 1
ang:RotateAroundAxis(ang:Right(), (self2.CameraAngCache.p + self2.CameraOffset.p) * viewbobintensity * -self2.CameraAttachmentScale)
ang:RotateAroundAxis(ang:Up(), (self2.CameraAngCache.y + self2.CameraOffset.y) * viewbobintensity * self2.CameraAttachmentScale)
ang:RotateAroundAxis(ang:Forward(), (self2.CameraAngCache.r + self2.CameraOffset.r) * viewbobintensity * self2.CameraAttachmentScale)
-- - self2.MZReferenceAngle--WorldToLocal( angpos.Pos, angpos.Ang, angpos.Pos, oldangtmp + self2.MZReferenceAngle )
--* progress )
--self2.ProceduralViewOffset.p = l_mathApproach(self2.ProceduralViewOffset.p, 0 , l_mathClamp( procedural_pitchrestorefac - math.min( math.abs( self2.ProceduralViewOffset.p ), procedural_pitchrestorefac ) ,1,procedural_pitchrestorefac)*ftv/5 )
--self2.ProceduralViewOffset.y = l_mathApproach(self2.ProceduralViewOffset.y, 0 , l_mathClamp( procedural_pitchrestorefac - math.min( math.abs( self2.ProceduralViewOffset.y ), procedural_pitchrestorefac ) ,1,procedural_pitchrestorefac)*ftv/5 )
--self2.ProceduralViewOffset.r = l_mathApproach(self2.ProceduralViewOffset.r, 0 , l_mathClamp( procedural_pitchrestorefac - math.min( math.abs( self2.ProceduralViewOffset.r ), procedural_pitchrestorefac ) ,1,procedural_pitchrestorefac)*ftv/5 )
else
local vb_d, vb_r, vb_s, idraw, ireload, ihols, stat
stat = self:GetStatus()
idraw = stat == TFA.Enum.STATUS_DRAW
ihols = TFA.Enum.HolsterStatus[stat]
ireload = TFA.Enum.ReloadStatus[stat]
vb_d = viewbob_animated_cvar:GetBool()
vb_r = viewbob_animated_cvar:GetBool()
vb_s = viewbob_animated_cvar:GetBool()
targbool = (vb_d and idraw) or (vb_r and ireload) or (self2.GetBashing and self2.GetBashing(self)) or (vb_s and stat == TFA.Enum.STATUS_SHOOTING and (self2.ViewBob_Shoot or not self:CanInterruptShooting())) or stat == TFA.Enum.STATUS_PUMP
targbool = targbool and not (ihols and self2.GetStatL(self, "ProceduralHolsterEnabled"))
targint = targbool and 1 or 0
if stat == TFA.Enum.STATUS_RELOADING_LOOP_END or stat == TFA.Enum.STATUS_RELOADING or stat == TFA.Enum.STATUS_PUMP or (stat == TFA.Enum.STATUS_RELOADING_WAIT and not self:GetStatL("LoopedReload")) or stat == TFA.Enum.STATUS_SHOOTING or (idraw and vb_d) then
targint = math.min(targint, 1 - math.pow(math.max(vm:GetCycle() - 0.5, 0) * 2, 2))
end
progress = l_Lerp(ftv * 15, progress, targint)
local att = self2.MuzzleAttachmentRaw or vm:LookupAttachment(self2.MuzzleAttachment)
if not att then
att = 1
end
local angpos = vm:GetAttachment(att)
if angpos then
mzang_fixed = vm:WorldToLocalAngles(angpos.Ang)
mzang_fixed:Normalize()
end
self2.ProceduralViewOffset:Normalize()
if mzang_fixed_last then
local delta = mzang_fixed - mzang_fixed_last
delta:Normalize()
mzang_velocity = mzang_velocity + delta * (2 * (1 - self2.ViewHolProg))
mzang_velocity.p = l_mathApproach(mzang_velocity.p, -self2.ProceduralViewOffset.p * 2, ftv * 20)
mzang_velocity.p = l_mathClamp(mzang_velocity.p, -procedural_vellimit, procedural_vellimit)
self2.ProceduralViewOffset.p = self2.ProceduralViewOffset.p + mzang_velocity.p * ftv
self2.ProceduralViewOffset.p = l_mathClamp(self2.ProceduralViewOffset.p, -90, 90)
mzang_velocity.y = l_mathApproach(mzang_velocity.y, -self2.ProceduralViewOffset.y * 2, ftv * 20)
mzang_velocity.y = l_mathClamp(mzang_velocity.y, -procedural_vellimit, procedural_vellimit)
self2.ProceduralViewOffset.y = self2.ProceduralViewOffset.y + mzang_velocity.y * ftv
self2.ProceduralViewOffset.y = l_mathClamp(self2.ProceduralViewOffset.y, -90, 90)
mzang_velocity.r = l_mathApproach(mzang_velocity.r, -self2.ProceduralViewOffset.r * 2, ftv * 20)
mzang_velocity.r = l_mathClamp(mzang_velocity.r, -procedural_vellimit, procedural_vellimit)
self2.ProceduralViewOffset.r = self2.ProceduralViewOffset.r + mzang_velocity.r * ftv
self2.ProceduralViewOffset.r = l_mathClamp(self2.ProceduralViewOffset.r, -90, 90)
end
self2.ProceduralViewOffset.p = l_mathApproach(self2.ProceduralViewOffset.p, 0, (1 - progress) * ftv * -self2.ProceduralViewOffset.p)
self2.ProceduralViewOffset.y = l_mathApproach(self2.ProceduralViewOffset.y, 0, (1 - progress) * ftv * -self2.ProceduralViewOffset.y)
self2.ProceduralViewOffset.r = l_mathApproach(self2.ProceduralViewOffset.r, 0, (1 - progress) * ftv * -self2.ProceduralViewOffset.r)
mzang_fixed_last = mzang_fixed
local ints = viewbob_intensity_cvar:GetFloat() * 1.25
ang:RotateAroundAxis(ang:Right(), l_Lerp(progress, 0, -self2.ProceduralViewOffset.p) * ints)
ang:RotateAroundAxis(ang:Up(), l_Lerp(progress, 0, self2.ProceduralViewOffset.y / 2) * ints)
ang:RotateAroundAxis(ang:Forward(), Lerp(progress, 0, self2.ProceduralViewOffset.r / 3) * ints)
end
return pos, LerpAngle(math.pow(self2.ViewHolProg, 2), ang, oldangtmp), fov
end

View File

@@ -0,0 +1,788 @@
--[[
| 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 angle_zero = Angle()
local Vector = Vector
local Angle = Angle
local math = math
local LerpVector = LerpVector
local sv_cheats = GetConVar("sv_cheats")
local host_timescale = GetConVar("host_timescale")
local cv_fov = GetConVar("fov_desired")
local cl_vm_nearwall = GetConVar("cl_tfa_viewmodel_nearwall")
local cl_tfa_viewmodel_offset_x = GetConVar("cl_tfa_viewmodel_offset_x")
local cl_tfa_viewmodel_offset_y = GetConVar("cl_tfa_viewmodel_offset_y")
local cl_tfa_viewmodel_offset_z = GetConVar("cl_tfa_viewmodel_offset_z")
local cl_tfa_viewmodel_centered = GetConVar("cl_tfa_viewmodel_centered")
local cl_tfa_viewmodel_vp_enabled = GetConVar("cl_tfa_viewmodel_vp_enabled")
local cl_tfa_viewmodel_vp_pitch = GetConVar("cl_tfa_viewmodel_vp_pitch")
local cl_tfa_viewmodel_vp_pitch_is = GetConVar("cl_tfa_viewmodel_vp_pitch_is")
local cl_tfa_viewmodel_vp_vertical = GetConVar("cl_tfa_viewmodel_vp_vertical")
local cl_tfa_viewmodel_vp_vertical_is = GetConVar("cl_tfa_viewmodel_vp_vertical_is")
local cl_tfa_viewmodel_vp_max_vertical = GetConVar("cl_tfa_viewmodel_vp_max_vertical")
local cl_tfa_viewmodel_vp_max_vertical_is = GetConVar("cl_tfa_viewmodel_vp_max_vertical_is")
local cl_tfa_viewmodel_vp_yaw = GetConVar("cl_tfa_viewmodel_vp_yaw")
local cl_tfa_viewmodel_vp_yaw_is = GetConVar("cl_tfa_viewmodel_vp_yaw_is")
local sv_tfa_recoil_legacy = GetConVar("sv_tfa_recoil_legacy")
local cv_customgunbob = GetConVar("cl_tfa_gunbob_custom")
local function Lerp(t, a, b)
return a + (b - a) * t
end
local function Clamp(a, b, c)
if a < b then return b end
if a > c then return c end
return a
end
local math_max = math.max
local cl_vm_flip_cv = GetConVar("cl_tfa_viewmodel_flip")
local fovmod_add = GetConVar("cl_tfa_viewmodel_offset_fov")
local fovmod_mult = GetConVar("cl_tfa_viewmodel_multiplier_fov")
function SWEP:AirWalkScale()
return (self:OwnerIsValid() and self:GetOwner():IsOnGround()) and 1 or 0.2
end
SWEP.OldPos = Vector(0, 0, 0)
SWEP.OldAng = Angle(0, 0, 0)
function SWEP:GetViewModelPosition(opos, oang, ...)
local self2 = self:GetTable()
if not self2.pos_cached then return opos, oang end
local npos, nang = opos * 1, oang * 1
nang:RotateAroundAxis(nang:Right(), self2.ang_cached.p)
nang:RotateAroundAxis(nang:Up(), self2.ang_cached.y)
nang:RotateAroundAxis(nang:Forward(), self2.ang_cached.r)
npos:Add(nang:Right() * self2.pos_cached.x)
npos:Add(nang:Forward() * self2.pos_cached.y)
npos:Add(nang:Up() * self2.pos_cached.z)
if cv_customgunbob:GetBool() then
npos, nang = self:Sway(npos, nang)
npos, nang = self:SprintBob(npos, nang, Lerp(self2.SprintProgressUnpredicted3 or self2.SprintProgressUnpredicted or self:GetSprintProgress(), 0, self2.SprintBobMult))
end
local pos, ang = self2.SightsAttPos, Angle(self2.SightsAttAng)
if not pos or not ang then return npos, nang end
local ofpos, ofang = WorldToLocal(npos, nang, opos, oang)
self2.OldPos = npos
self2.OldAng = nang
if self.IronSightsProgressUnpredicted > 0.005 then
local _opos, _oang = opos * 1, oang * 1
-- tfa base vm offset
local right, up, fwd = _oang:Right(), _oang:Up(), _oang:Forward()
_opos = _opos - ofpos.y * right + ofpos.x * fwd + ofpos.z * up
_oang:RotateAroundAxis(fwd, ofang.r)
_oang:RotateAroundAxis(right, -ofang.p)
_oang:RotateAroundAxis(up, ofang.y)
-- sight offset
_oang:RotateAroundAxis(_oang:Forward(), -ang.r)
_oang:RotateAroundAxis(_oang:Right(), ang.p)
_oang:RotateAroundAxis(_oang:Up(), -ang.y)
right, up, fwd = _oang:Right(), _oang:Up(), _oang:Forward()
_opos = _opos - pos.x * fwd + pos.y * right - pos.z * up
self2.OldPos = LerpVector(self2.IronSightsProgressUnpredicted, npos, _opos)
self2.OldAng = LerpAngle(self2.IronSightsProgressUnpredicted, nang, _oang)
end
return self2.OldPos, self2.OldAng
end
function SWEP:CalculateViewModelFlip()
local self2 = self:GetTable()
if self2.ViewModelFlipDefault == nil then
self2.ViewModelFlipDefault = self2.ViewModelFlip
end
local righthanded = true
if cl_vm_flip_cv:GetBool() then
righthanded = false
end
local shouldflip = self2.ViewModelFlipDefault
if not righthanded then
shouldflip = not self2.ViewModelFlipDefault
end
if self2.ViewModelFlip ~= shouldflip then
self2.ViewModelFlip = shouldflip
end
self2.ViewModelFOV_OG = self2.ViewModelFOV_OG or self2.ViewModelFOV
local cam_fov = self2.LastTranslatedFOV or cv_fov:GetInt() or 90
local iron_add = cam_fov * (1 - 90 / cam_fov) * math.max(1 - self2.GetStatL(self, "Secondary.OwnerFOV", 90) / 90, 0)
local ironSightsProgress = TFA.Cosine(self2.IronSightsProgressUnpredicted or self:GetIronSightsProgress())
self2.ViewModelFOV = Lerp(ironSightsProgress, self2.ViewModelFOV_OG, self2.GetStatL(self, "Secondary.ViewModelFOV", self2.ViewModelFOV_OG)) * fovmod_mult:GetFloat() + fovmod_add:GetFloat() + iron_add * ironSightsProgress
end
function SWEP:UpdateWeaponLength()
local self2 = self:GetTable()
if not self:VMIV() then return end
local vm = self2.OwnerViewModel
local mzpos = self:GetMuzzlePos()
if not mzpos then return end
if not mzpos.Pos then return end
if GetViewEntity and GetViewEntity() ~= self:GetOwner() then return end
local mzVec = vm:WorldToLocal(mzpos.Pos)
self2.WeaponLength = math.abs(mzVec.x)
end
function SWEP:CalculateNearWall(p, a)
local self2 = self:GetTable()
if not self:OwnerIsValid() then return p, a end
if not cl_vm_nearwall:GetBool() then return p, a end
local ply = self:GetOwner()
local sp = ply:GetShootPos()
local ea = ply:EyeAngles()
local et = util.QuickTrace(sp,ea:Forward()*128,{self,ply})--self:GetOwner():GetEyeTrace()
local dist = et.HitPos:Distance(sp)
if dist<1 then
et=util.QuickTrace(sp,ea:Forward()*128,{self,ply,et.Entity})
dist = et.HitPos:Distance(sp)
end
self:UpdateWeaponLength()
local nw_offset_vec = LerpVector(self2.IronSightsProgressUnpredicted or self:GetIronSightsProgress(), self2.NearWallVector, self2.NearWallVectorADS)
local off = self2.WeaponLength - dist
self2.LastNearWallOffset = self2.LastNearWallOffset or 0
local ft = RealFrameTime() * game.GetTimeScale() * (sv_cheats:GetBool() and host_timescale:GetFloat() or 1)
if off > self2.LastNearWallOffset then
self2.LastNearWallOffset = math.min(self2.LastNearWallOffset + math.max(ft * 66, off * 0.1), off, 34)
elseif off < self2.LastNearWallOffset then
self2.LastNearWallOffset = math.max(self2.LastNearWallOffset - ft * 66, off, 0)
end
off = TFA.Cosine(self2.LastNearWallOffset / 34) * 34
if off > 0 then
p = p + nw_offset_vec * off / 2
local posCompensated = sp * 1
posCompensated:Add(ea:Right() * nw_offset_vec.x * off / 2 * (self2.ViewModelFlip and -1 or 1))
posCompensated:Add(ea:Forward() * nw_offset_vec.y * off / 2)
posCompensated:Add(ea:Up() * nw_offset_vec.z * off / 2)
local angleComp = (et.HitPos - posCompensated):Angle()
a.x = a.x - math.AngleDifference(angleComp.p, ea.p) / 2
a.y = a.y + math.AngleDifference(angleComp.y, ea.y) / 2
end
return p, a
end
local centered_sprintpos = Vector(0, -1, 1)
local centered_sprintang = Vector(-15, 0, 0)
local bezierVectorBuffer = {}
local function bezierVector(t, vec1, vec2, vec3)
local _1, _2 = vec1.x, vec3.x
bezierVectorBuffer[1] = _1
bezierVectorBuffer[2] = _1
bezierVectorBuffer[3] = _1
bezierVectorBuffer[4] = _1
bezierVectorBuffer[5] = vec2.x
bezierVectorBuffer[6] = _2
bezierVectorBuffer[7] = _2
bezierVectorBuffer[8] = _2
bezierVectorBuffer[9] = _2
local x = TFA.tbezier(t, bezierVectorBuffer)
_1, _2 = vec1.y, vec3.y
bezierVectorBuffer[1] = _1
bezierVectorBuffer[2] = _1
bezierVectorBuffer[3] = _1
bezierVectorBuffer[4] = _1
bezierVectorBuffer[5] = vec2.y
bezierVectorBuffer[6] = _2
bezierVectorBuffer[7] = _2
bezierVectorBuffer[8] = _2
bezierVectorBuffer[9] = _2
local y = TFA.tbezier(t, bezierVectorBuffer)
_1, _2 = vec1.z, vec3.z
bezierVectorBuffer[1] = _1
bezierVectorBuffer[2] = _1
bezierVectorBuffer[3] = _1
bezierVectorBuffer[4] = _1
bezierVectorBuffer[5] = vec2.z
bezierVectorBuffer[6] = _2
bezierVectorBuffer[7] = _2
bezierVectorBuffer[8] = _2
bezierVectorBuffer[9] = _2
local z = TFA.tbezier(t, bezierVectorBuffer)
return Vector(x, y, z)
end
function SWEP:CalculateViewModelOffset(delta)
local self2 = self:GetTable()
local target_pos, target_ang
local additivePos = self2.GetStatL(self, "AdditiveViewModelPosition")
if additivePos then
target_pos, target_ang = Vector(), Vector()
else
target_pos = Vector(self2.GetStatL(self, "ViewModelPosition"))
target_ang = Vector(self2.GetStatL(self, "ViewModelAngle"))
end
local CenteredViewModelPosition = self2.GetStatL(self, "CenteredViewModelPosition")
local CenteredViewModelAngle = self2.GetStatL(self, "CenteredViewModelAngle")
local IronSightsPosition = self2.GetStatL(self, "IronSightsPosition", self2.SightsPos)
local IronSightsAngle = self2.GetStatL(self, "IronSightsAngle", self2.SightsAng)
local targetPosCenter, targetAngCenter
if CenteredViewModelPosition then
targetPosCenter = Vector(CenteredViewModelPosition)
if CenteredViewModelAngle then
targetAngCenter = Vector(CenteredViewModelAngle)
end
elseif IronSightsPosition then
targetPosCenter = Vector((self2.IronSightsPositionCurrent or IronSightsPosition).x, target_pos.y, target_pos.z - 3)
if IronSightsAngle then
targetAngCenter = Vector(0, (self2.IronSightsAngleCurrent or IronSightsAngle).y, 0)
end
else
targetPosCenter, targetAngCenter = target_pos, target_ang
end
if cl_tfa_viewmodel_centered:GetBool() then
target_pos:Set(targetPosCenter)
target_ang:Set(targetAngCenter)
end
local stat = self:GetStatus()
local holsterStatus = TFA.Enum.HolsterStatus[stat] and self2.GetStatL(self, "ProceduralHolsterEnabled")
local proceduralReloadStatus = TFA.Enum.ReloadStatus[stat] and self2.GetStatL(self, "IsProceduralReloadBased")
local holsterProgress = 0
local statusProgress = self:GetStatusProgress()
if proceduralReloadStatus then
holsterProgress = TFA.Quintic(Clamp((statusProgress >= 0.5 and (2 - statusProgress * 2) or (statusProgress * 2)), 0, 1))
elseif self2.GetStatL(self, "ProceduralHolsterEnabled") then
if TFA.Enum.HolsterStatusFinal[stat] then
holsterProgress = 1
elseif TFA.Enum.HolsterStatus[stat] then
holsterProgress = TFA.Quintic(Clamp(statusProgress * 1.1, 0, 1))
end
end
local sprintAnimAllowed = self2.Sprint_Mode == TFA.Enum.LOCOMOTION_LUA or self2.Sprint_Mode == TFA.Enum.LOCOMOTION_HYBRID
local isSafety = self:IsSafety()
local ironSights = self:GetIronSights()
local isSprinting = self:GetSprinting()
local sprintProgress = sprintAnimAllowed and TFA.Cubic(self2.SprintProgressUnpredicted2 or self2.SprintProgressUnpredicted or self:GetSprintProgress()) or 0
local safetyProgress = Lerp(sprintProgress, TFA.Cubic(self2.SafetyProgressUnpredicted or 0), 0)
local ironSightsProgress = Clamp(
Lerp(
math_max(holsterProgress, sprintProgress, safetyProgress),
TFA.Cubic(self2.IronSightsProgressUnpredicted2 or self2.IronSightsProgressUnpredicted or self:GetIronSightsProgress()),
0)
, 0, 1)
--local ironSightsProgress = TFA.tbezier(self2.IronSightsProgressUnpredicted or self:GetIronSightsProgress(), IRON_SIGHTS_BEZIER)
local crouchRatio = Lerp(math_max(ironSightsProgress, holsterProgress, Clamp(sprintProgress * 2, 0, 1), safetyProgress), TFA.Quintic(self2.CrouchingRatioUnpredicted or self:GetCrouchingRatio()), 0)
if crouchRatio > 0.01 then
target_pos = LerpVector(crouchRatio, target_pos, self2.GetStatL(self, "CrouchViewModelPosition"))
target_ang = LerpVector(crouchRatio, target_ang, self2.GetStatL(self, "CrouchViewModelAngle"))
end
if holsterStatus or proceduralReloadStatus then
local targetHolsterPos = Vector(self2.GetStatL(self, "ProceduralHolsterPosition"))
local targetHolsterAng = Vector(self2.GetStatL(self, "ProceduralHolsterAngle"))
if self2.ViewModelFlip then
targetHolsterPos.x = -targetHolsterPos.x
targetHolsterAng.y = -targetHolsterAng.y
targetHolsterAng.z = -targetHolsterAng.z
end
target_pos = LerpVector(holsterProgress, target_pos, targetHolsterPos)
target_ang = LerpVector(holsterProgress, target_ang, targetHolsterAng)
end
if
(sprintProgress > 0.01 or safetyProgress > 0.01) and
(sprintAnimAllowed and sprintProgress > 0.01 or safetyProgress > 0.01)
and stat ~= TFA.Enum.STATUS_BASHING
then
if cl_tfa_viewmodel_centered:GetBool() then
target_pos = target_pos + centered_sprintpos
target_ang = target_ang + centered_sprintang
else
target_pos = LerpVector(safetyProgress, target_pos, self2.GetStatL(self, "SafetyPos", self2.GetStatL(self, "SprintViewModelPosition")))
target_ang = LerpVector(safetyProgress, target_ang, self2.GetStatL(self, "SafetyAng", self2.GetStatL(self, "SprintViewModelAngle")))
if sprintAnimAllowed then
target_pos = LerpVector(sprintProgress, target_pos, self2.GetStatL(self, "SprintViewModelPosition"))
target_ang = LerpVector(sprintProgress, target_ang, self2.GetStatL(self, "SprintViewModelAngle"))
end
end
end
if ironSightsProgress > 0.02 and (self2.Sights_Mode == TFA.Enum.LOCOMOTION_LUA or self2.Sights_Mode == TFA.Enum.LOCOMOTION_HYBRID) then
local score = self2.VM_IronPositionScore or 1
local getSightsPos = self2.IronSightsPositionCurrent or IronSightsPosition or self2.GetStatL(self, "SightsPos", vector_origin)
if targetPosCenter and score > 0.04 then
target_pos = bezierVector(ironSightsProgress, target_pos, LerpVector(score, getSightsPos, targetPosCenter), getSightsPos)
else
target_pos = LerpVector(ironSightsProgress, target_pos, getSightsPos)
end
if targetAngCenter and score > 0.04 then
local deviate = 30 * score
if self2.VM_IsScopedIn then
deviate = -deviate
end
if self2.ViewModelFlip then
deviate = -deviate
end
local targetAngCenter2 = Vector(targetAngCenter.x * score, targetAngCenter.y * score, targetAngCenter.z * score + deviate)
target_ang = bezierVector(ironSightsProgress, target_ang, targetAngCenter2, self2.IronSightsAngleCurrent or IronSightsAngle or self2.GetStatL(self, "SightsAng", vector_origin))
else
target_ang = LerpVector(ironSightsProgress, target_ang, self2.IronSightsAngleCurrent or IronSightsAngle or self2.GetStatL(self, "SightsAng", vector_origin))
end
end
target_pos.x = target_pos.x + cl_tfa_viewmodel_offset_x:GetFloat() * (1 - ironSightsProgress)
target_pos.y = target_pos.y + cl_tfa_viewmodel_offset_y:GetFloat() * (1 - ironSightsProgress)
target_pos.z = target_pos.z + cl_tfa_viewmodel_offset_z:GetFloat() * (1 - ironSightsProgress)
local customizationProgress = TFA.Quintic(self2.CustomizingProgressUnpredicted or self:GetInspectingProgress())
if customizationProgress > 0.01 and self2.Customize_Mode ~= TFA.Enum.LOCOMOTION_ANI then
if not self2.InspectPos then
self2.InspectPos = Vector(self2.InspectPosDef)
if self2.ViewModelFlip then
self2.InspectPos.x = self2.InspectPos.x * -1
end
end
if not self2.InspectAng then
self2.InspectAng = Vector(self2.InspectAngDef)
if self2.ViewModelFlip then
self2.InspectAng.y = self2.InspectAngDef.y * -1
self2.InspectAng.z = self2.InspectAngDef.z * -1
end
end
target_pos = LerpVector(customizationProgress, target_pos, self2.GetStatL(self, "InspectPos"))
target_ang = LerpVector(customizationProgress, target_ang, self2.GetStatL(self, "InspectAng"))
end
target_pos, target_ang = self:CalculateNearWall(target_pos, target_ang)
if additivePos then
target_pos:Add(self2.GetStatL(self, "ViewModelPosition"))
target_ang:Add(self2.GetStatL(self, "ViewModelAngle"))
end
target_ang.z = target_ang.z + -7.5 * (1 - math.abs(0.5 - ironSightsProgress) * 2) * (self:GetIronSights() and 1 or 0.5) * (self2.ViewModelFlip and 1 or -1) * (self2.VM_IronPositionScore or 1)
if self:GetHidden() then
target_pos.z = target_pos.z - 5
end
if self2.GetStatL(self, "BlowbackEnabled") and self2.BlowbackCurrentRoot > 0.01 then
local bbvec = self2.GetStatL(self, "BlowbackVector")
target_pos = target_pos + bbvec * self2.BlowbackCurrentRoot
local bbang = self2.GetStatL(self, "BlowbackAngle") or angle_zero
bbvec = bbvec * 1
bbvec.x = bbang.p
bbvec.y = bbang.y
bbvec.z = bbang.r
target_ang = target_ang + bbvec * self2.BlowbackCurrentRoot
bbang = self2.BlowbackRandomAngle * (1 - math.max(0, ironSightsProgress) * .8)
bbvec.x = bbang.p
bbvec.y = bbang.y
bbvec.z = bbang.r
target_ang = target_ang + bbvec * self2.BlowbackCurrentRoot
end
if not sv_tfa_recoil_legacy:GetBool() and cl_tfa_viewmodel_vp_enabled:GetBool() then
if self:HasRecoilLUT() then
if not ironSights then
local ang = self:GetRecoilLUTAngle()
target_ang.x = target_ang.x - ang.p / 2 * Lerp(ironSightsProgress, self:GetStatL("ViewModelPunchPitchMultiplier") * cl_tfa_viewmodel_vp_pitch:GetFloat(), self:GetStatL("ViewModelPunchPitchMultiplier_IronSights") * cl_tfa_viewmodel_vp_pitch_is:GetFloat())
target_ang.y = target_ang.y + ang.y / 2 * Lerp(ironSightsProgress, self:GetStatL("ViewModelPunchYawMultiplier") * cl_tfa_viewmodel_vp_yaw:GetFloat(), self:GetStatL("ViewModelPunchYawMultiplier_IronSights") * cl_tfa_viewmodel_vp_yaw_is:GetFloat())
end
else
target_ang.x = target_ang.x - self:GetViewPunchP() * Lerp(ironSightsProgress, self:GetStatL("ViewModelPunchPitchMultiplier") * cl_tfa_viewmodel_vp_pitch:GetFloat(), self:GetStatL("ViewModelPunchPitchMultiplier_IronSights") * cl_tfa_viewmodel_vp_pitch_is:GetFloat())
target_ang.y = target_ang.y + self:GetViewPunchY() * Lerp(ironSightsProgress, self:GetStatL("ViewModelPunchYawMultiplier") * cl_tfa_viewmodel_vp_yaw:GetFloat(), self:GetStatL("ViewModelPunchYawMultiplier_IronSights") * cl_tfa_viewmodel_vp_yaw_is:GetFloat())
local ViewModelPunch_MaxVertialOffset = Lerp(ironSightsProgress, self:GetStatL("ViewModelPunch_MaxVertialOffset") * cl_tfa_viewmodel_vp_max_vertical:GetFloat(), self:GetStatL("ViewModelPunch_MaxVertialOffset_IronSights") * cl_tfa_viewmodel_vp_max_vertical_is:GetFloat())
target_pos.y = target_pos.y + math.Clamp(
self:GetViewPunchP() * Lerp(ironSightsProgress, self:GetStatL("ViewModelPunch_VertialMultiplier") * cl_tfa_viewmodel_vp_vertical:GetFloat(), self:GetStatL("ViewModelPunch_VertialMultiplier_IronSights") * cl_tfa_viewmodel_vp_vertical_is:GetFloat()),
-ViewModelPunch_MaxVertialOffset,
ViewModelPunch_MaxVertialOffset)
end
end
if not cv_customgunbob:GetBool() then
self2.pos_cached, self2.ang_cached = Vector(target_pos), Angle(target_ang.x, target_ang.y, target_ang.z)
return
end
local intensityWalk = math.min(self:GetOwner():GetVelocity():Length2D() / self:GetOwner():GetWalkSpeed(), 1) * Lerp(ironSightsProgress, self2.WalkBobMult, self2.WalkBobMult_Iron or self2.WalkBobMult)
local intensityBreath = Lerp(ironSightsProgress, self2.GetStatL(self, "BreathScale", 0.2), self2.GetStatL(self, "IronBobMultWalk", 0.5) * intensityWalk)
intensityWalk = (1 - ironSightsProgress) * intensityWalk
local intensityRun = Lerp(self2.SprintProgressUnpredicted3 or self2.SprintProgressUnpredicted or self:GetSprintProgress(), 0, self2.SprintBobMult)
local velocity = math.max(self:GetOwner():GetVelocity():Length2D() * self:AirWalkScale() - self:GetOwner():GetVelocity().z * 0.5, 0)
local rate = math.min(math.max(0.15, math.sqrt(velocity / self:GetOwner():GetRunSpeed()) * 1.75), self:GetSprinting() and 5 or 3)
self2.pos_cached, self2.ang_cached = self:WalkBob(
target_pos,
Angle(target_ang.x, target_ang.y, target_ang.z),
math.max(intensityBreath - intensityWalk - intensityRun, 0),
math.max(intensityWalk - intensityRun, 0), rate, delta)
end
local rft, eyeAngles, viewPunch, oldEyeAngles, delta, motion, counterMotion, compensation, fac, positionCompensation, swayRate, wiggleFactor, flipFactor
local gunswaycvar = GetConVar("cl_tfa_gunbob_intensity")
local sv_tfa_weapon_weight = GetConVar("sv_tfa_weapon_weight")
function SWEP:Sway(pos, ang, ftv)
local self2 = self:GetTable()
--sanity check
if not self:OwnerIsValid() then return pos, ang end
--convar
fac = gunswaycvar:GetFloat() * 3 * ((1 - ((self2.IronSightsProgressUnpredicted or self:GetIronSightsProgress()) or 0)) * 0.85 + 0.15)
flipFactor = (self2.ViewModelFlip and -1 or 1)
--init vars
delta = delta or Angle()
motion = motion or Angle()
counterMotion = counterMotion or Angle()
compensation = compensation or Angle()
if ftv then
--grab eye angles
eyeAngles = self:GetOwner():EyeAngles()
viewPunch = self:GetOwner():GetViewPunchAngles()
eyeAngles.p = eyeAngles.p - viewPunch.p
eyeAngles.y = eyeAngles.y - viewPunch.y
oldEyeAngles = oldEyeAngles or eyeAngles
--calculate delta
wiggleFactor = (1 - (sv_tfa_weapon_weight:GetBool() and self2.GetStatL(self, "RegularMoveSpeedMultiplier") or 1)) / 0.6 + 0.15
swayRate = math.pow(sv_tfa_weapon_weight:GetBool() and self2.GetStatL(self, "RegularMoveSpeedMultiplier") or 1, 1.5) * 10
rft = math.Clamp(ftv, 0.001, 1 / 20)
local clampFac = 1.1 - math.min((math.abs(motion.p) + math.abs(motion.y) + math.abs(motion.r)) / 20, 1)
delta.p = math.AngleDifference(eyeAngles.p, oldEyeAngles.p) / rft / 120 * clampFac
delta.y = math.AngleDifference(eyeAngles.y, oldEyeAngles.y) / rft / 120 * clampFac
delta.r = math.AngleDifference(eyeAngles.r, oldEyeAngles.r) / rft / 120 * clampFac
oldEyeAngles = eyeAngles
--calculate motions, based on Juckey's methods
counterMotion = LerpAngle(rft * (swayRate * (0.75 + math.max(0, 0.5 - wiggleFactor))), counterMotion, -motion)
compensation.p = math.AngleDifference(motion.p, -counterMotion.p)
compensation.y = math.AngleDifference(motion.y, -counterMotion.y)
motion = LerpAngle(rft * swayRate, motion, delta + compensation)
end
--modify position/angle
positionCompensation = 0.2 + 0.2 * ((self2.IronSightsProgressUnpredicted or self:GetIronSightsProgress()) or 0)
pos:Add(-motion.y * positionCompensation * 0.66 * fac * ang:Right() * flipFactor) --compensate position for yaw
pos:Add(-motion.p * positionCompensation * fac * ang:Up()) --compensate position for pitch
ang:RotateAroundAxis(ang:Right(), motion.p * fac)
ang:RotateAroundAxis(ang:Up(), -motion.y * 0.66 * fac * flipFactor)
ang:RotateAroundAxis(ang:Forward(), counterMotion.r * 0.5 * fac * flipFactor)
return pos, ang
end
local mirror = Matrix()
hook.Add("PostRender", "TFA:CacheSightsPos", function()
local self = LocalPlayer():GetActiveWeapon()
if not IsValid(self) then return end
local self2 = self:GetTable()
if not self2.IsTFAWeapon then return end
if not self2.ViewModelFlip then return end
local vm = self2.OwnerViewModel
self2.ViewModelFlip = false
vm:SetRenderOrigin(vector_origin)
vm:SetRenderAngles(angle_zero)
vm:InvalidateBoneCache()
vm:SetupBones()
local ViewModelElements = self:GetStatRaw("ViewModelElements", TFA.LatestDataVersion)
if ViewModelElements and self2.HasInitAttachments then
if not self2.vRenderOrder then
self:RebuildModsRenderOrder()
end
TFA._IncNextSetupBones()
for index = 1, #self2.vRenderOrder do
local name = self2.vRenderOrder[index]
local element = ViewModelElements[name]
if not element then
self:RebuildModsRenderOrder()
break
end
if element.type ~= "Model" then goto CONTINUE end
if element.hide then goto CONTINUE end
if not element.bone then goto CONTINUE end
if self2.GetStatL(self, "ViewModelElements." .. name .. ".active") == false then goto CONTINUE end
local pos, ang = self:GetBoneOrientation(ViewModelElements, element, vm, nil, true)
if not pos and not element.bonemerge then goto CONTINUE end
self:PrecacheElement(element, true)
local model = element.curmodel
local sprite = element.spritemat
if IsValid(model) then
if not element.bonemerge then
model:SetPos(pos + ang:Forward() * element.pos.x + ang:Right() * element.pos.y + ang:Up() * element.pos.z)
ang:RotateAroundAxis(ang:Up(), element.angle.y)
ang:RotateAroundAxis(ang:Right(), element.angle.p)
ang:RotateAroundAxis(ang:Forward(), element.angle.r)
model:SetAngles(ang)
mirror:Identity()
mirror:Scale(element.size)
model:EnableMatrix("RenderMultiply", mirror)
end
if not self2.VElementsBodygroupsCache[index] then
self2.VElementsBodygroupsCache[index] = #model:GetBodyGroups() - 1
end
if self2.VElementsBodygroupsCache[index] then
for _b = 0, self2.VElementsBodygroupsCache[index] do
local newbg = self2.GetStatL(self, "ViewModelElements." .. name .. ".bodygroup." .. _b, 0) -- names are not supported, use overridetable
if model:GetBodygroup(_b) ~= newbg then
model:SetBodygroup(_b, newbg)
end
end
end
if element.bonemerge then
if element.rel and ViewModelElements[element.rel] and IsValid(ViewModelElements[element.rel].curmodel) then
element.parModel = ViewModelElements[element.rel].curmodel
else
element.parModel = self2.OwnerViewModel or self
end
if model:GetParent() ~= element.parModel then
model:SetParent(element.parModel)
end
if not model:IsEffectActive(EF_BONEMERGE) then
model:AddEffects(EF_BONEMERGE)
model:AddEffects(EF_BONEMERGE_FASTCULL)
model:SetMoveType(MOVETYPE_NONE)
model:SetLocalPos(vector_origin)
model:SetLocalAngles(angle_zero)
end
elseif model:IsEffectActive(EF_BONEMERGE) then
model:RemoveEffects(EF_BONEMERGE)
model:SetParent(NULL)
end
model:InvalidateBoneCache()
model:SetupBones()
model.tfa_next_setup_bones = TFA._GetNextSetupBones()
end
::CONTINUE::
end
end
self:CacheSightsPos(vm, true)
vm:SetRenderOrigin()
vm:SetRenderAngles()
self.ViewModelFlip = true
vm:InvalidateBoneCache()
end)
function SWEP:CacheSightsPos(vm, flipped)
self.SightsAttPos, self.SightsAttAng = nil, nil
if not self:GetStat("ProceduralSight", false) then return end
local model = vm
local attname = self:GetStat("ProceduralSight_VElement")
if attname then
if not self:GetStat("VElements." .. attname .. ".active", false) then return end
model = self.VElements[attname].curmodel
end
if not IsValid(model) then return end
local ViewModelElements = self:GetStatRaw("ViewModelElements", TFA.LatestDataVersion)
TFA._IncNextSetupBones()
if self:GetStat("ProceduralSight_PositionType", TFA.Enum.SIGHTSPOS_ATTACH) == TFA.Enum.SIGHTSPOS_BONE then
local boneid = self:GetStat("ProceduralSight_Bone")
if not boneid then return end
if type(boneid) == "string" then
boneid = model:LookupBone(boneid)
end
if not boneid or boneid < 0 then return end
self.SightsAttPos, self.SightsAttAng = model:GetBonePosition(boneid)
else
local attid = self:GetStat("ProceduralSight_Attachment")
if not attid then return end
if type(attid) == "string" then
attid = model:LookupAttachment(attid)
end
if not attid or attid <= 0 then return end
local attpos = model:GetAttachment(attid)
self.SightsAttPos, self.SightsAttAng = attpos.Pos, attpos.Ang
end
if self.SightsAttPos and self.SightsAttAng then
if not flipped then
local transform = Matrix()
transform:Translate(vm:GetPos())
transform:Rotate(vm:GetAngles())
transform:Invert()
transform:Translate(self.SightsAttPos)
transform:Rotate(self.SightsAttAng)
self.SightsAttPos, self.SightsAttAng = transform:GetTranslation(), transform:GetAngles()
end
local OffsetPos = self:GetStatL("ProceduralSight_OffsetPos")
if OffsetPos then
if GetConVarNumber("developer") > 0 then -- draw pre-offset pos
local a, b = LocalToWorld(self.SightsAttPos, self.SightsAttAng, vm:GetPos(), vm:GetAngles())
render.DrawLine(a, a + b:Forward() * 1, Color(127, 0, 0), false)
render.DrawLine(a, a - b:Right() * 1, Color(0, 127, 0), false)
render.DrawLine(a, a + b:Up() * 1, Color(0, 0, 127), false)
end
self.SightsAttPos:Add(self.SightsAttAng:Right() * OffsetPos.x)
self.SightsAttPos:Add(self.SightsAttAng:Forward() * OffsetPos.y)
self.SightsAttPos:Add(self.SightsAttAng:Up() * OffsetPos.z)
end
local OffsetAng = self:GetStatL("ProceduralSight_OffsetAng")
if OffsetAng then
self.SightsAttAng:RotateAroundAxis(self.SightsAttAng:Right(), OffsetAng.p)
self.SightsAttAng:RotateAroundAxis(self.SightsAttAng:Up(), OffsetAng.y)
self.SightsAttAng:RotateAroundAxis(self.SightsAttAng:Forward(), OffsetAng.r)
end
if GetConVarNumber("developer") > 0 then -- draw final pos
local a, b = LocalToWorld(self.SightsAttPos, self.SightsAttAng, vm:GetPos(), vm:GetAngles())
render.DrawLine(a, a + b:Forward() * 1, Color(255, 0, 0), false)
render.DrawLine(a, a - b:Right() * 1, Color(0, 255, 0), false)
render.DrawLine(a, a + b:Up() * 1, Color(0, 0, 255), false)
end
end
end

View File

@@ -0,0 +1,181 @@
--[[
| 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 HoldTypeTable = {
["melee"] = {
[ACT_IDLE] = ACT_IDLE_MELEE,
[ACT_IDLE_ANGRY] = ACT_IDLE_MELEE,
[ACT_IDLE_RELAXED] = ACT_IDLE_MELEE,
[ACT_IDLE_STIMULATED] = ACT_IDLE_MELEE,
[ACT_IDLE_AGITATED] = ACT_IDLE_MELEE,
[ACT_IDLE_AIM_RELAXED] = ACT_IDLE_MELEE,
[ACT_IDLE_AIM_STIMULATED] = ACT_IDLE_MELEE,
[ACT_IDLE_AIM_AGITATED] = ACT_IDLE_MELEE,
[ACT_RANGE_ATTACK1] = ACT_RANGE_ATTACK_THROW,
[ACT_RANGE_ATTACK1_LOW] = ACT_MELEE_ATTACK_SWING,
[ACT_MELEE_ATTACK1] = ACT_MELEE_ATTACK_SWING,
[ACT_MELEE_ATTACK2] = ACT_MELEE_ATTACK_SWING,
[ACT_SPECIAL_ATTACK1] = ACT_RANGE_ATTACK_THROW,
[ACT_RANGE_AIM_LOW] = ACT_IDLE_MELEE,
[ACT_COVER_LOW] = ACT_IDLE_MELEE,
[ACT_WALK] = ACT_WALK_SUITCASE,
[ACT_WALK_RELAXED] = ACT_WALK_SUITCASE,
[ACT_WALK_STIMULATED] = ACT_WALK_SUITCASE,
[ACT_WALK_AGITATED] = ACT_WALK_SUITCASE,
[ACT_RUN_CROUCH] = ACT_RUN_CROUCH,
[ACT_RUN_CROUCH_AIM] = ACT_RUN_CROUCH,
[ACT_RUN] = ACT_RUN,
[ACT_RUN_AIM_RELAXED] = ACT_RUN,
[ACT_RUN_AIM_STIMULATED] = ACT_RUN,
[ACT_RUN_AIM_AGITATED] = ACT_RUN,
[ACT_RUN_AIM] = ACT_RUN,
[ACT_SMALL_FLINCH] = ACT_RANGE_ATTACK_PISTOL,
[ACT_BIG_FLINCH] = ACT_RANGE_ATTACK_PISTOL
},
["melee2"] = {
[ACT_IDLE] = ACT_IDLE_ANGRY_MELEE,
[ACT_IDLE_ANGRY] = ACT_IDLE_ANGRY_MELEE,
[ACT_IDLE_RELAXED] = ACT_IDLE,
[ACT_IDLE_STIMULATED] = ACT_IDLE,
[ACT_IDLE_AGITATED] = ACT_IDLE_ANGRY_MELEE,
[ACT_MP_RUN] = ACT_HL2MP_RUN_SUITCASE,
[ACT_RUN] = ACT_RUN,
[ACT_RUN_AIM_RELAXED] = ACT_RUN,
[ACT_RUN_AIM_STIMULATED] = ACT_RUN,
[ACT_RUN_AIM_AGITATED] = ACT_RUN,
[ACT_RUN_AIM] = ACT_RUN,
[ACT_WALK] = ACT_WALK_SUITCASE,
[ACT_MELEE_ATTACK1] = ACT_MELEE_ATTACK_SWING,
[ACT_RANGE_ATTACK1] = ACT_MELEE_ATTACK_SWING,
[ACT_MELEE_ATTACK2] = ACT_MELEE_ATTACK_SWING,
[ACT_RANGE_ATTACK2] = ACT_MELEE_ATTACK_SWING,
[ACT_SPECIAL_ATTACK1] = ACT_RANGE_ATTACK_THROW,
[ACT_SMALL_FLINCH] = ACT_RANGE_ATTACK_PISTOL,
[ACT_BIG_FLINCH] = ACT_RANGE_ATTACK_PISTOL
},
["pistol"] = {
[ACT_IDLE] = ACT_IDLE_PISTOL,
[ACT_IDLE_ANGRY] = ACT_IDLE_ANGRY_PISTOL,
[ACT_IDLE_AGITATED] = ACT_IDLE_ANGRY_PISTOL,
[ACT_RANGE_ATTACK1] = ACT_RANGE_ATTACK_PISTOL,
[ACT_RELOAD] = ACT_RELOAD_PISTOL,
[ACT_WALK] = ACT_WALK_PISTOL,
[ACT_WALK_AIM] = ACT_WALK_AIM_PISTOL,
[ACT_RUN] = ACT_RUN_PISTOL,
[ACT_RUN_AIM] = ACT_RUN_AIM_PISTOL,
[ACT_RANGE_ATTACK1] = ACT_RANGE_ATTACK_PISTOL,
[ACT_GESTURE_RANGE_ATTACK1] = ACT_GESTURE_RANGE_ATTACK_PISTOL,
[ACT_RELOAD_LOW] = ACT_RELOAD_PISTOL_LOW,
[ACT_RANGE_ATTACK1_LOW] = ACT_RANGE_ATTACK_PISTOL_LOW,
[ACT_COVER_LOW] = ACT_COVER_PISTOL_LOW,
[ACT_RANGE_AIM_LOW] = ACT_RANGE_AIM_PISTOL_LOW,
[ACT_GESTURE_RELOAD] = ACT_GESTURE_RELOAD_PISTOL
},
["ar2"] = {
[ACT_RANGE_ATTACK1] = ACT_RANGE_ATTACK_AR2,
[ACT_RELOAD] = ACT_RELOAD_SMG1,
[ACT_IDLE] = ACT_IDLE_SMG1,
[ACT_IDLE_ANGRY] = ACT_IDLE_ANGRY_SMG1,
[ACT_WALK] = ACT_WALK_RIFLE,
[ACT_IDLE_RELAXED] = ACT_IDLE_SMG1_RELAXED,
[ACT_IDLE_STIMULATED] = ACT_IDLE_SMG1_STIMULATED,
[ACT_IDLE_AGITATED] = ACT_IDLE_ANGRY_SMG1,
[ACT_WALK_RELAXED] = ACT_WALK_RIFLE_RELAXED,
[ACT_WALK_STIMULATED] = ACT_WALK_RIFLE_STIMULATED,
[ACT_WALK_AGITATED] = ACT_WALK_AIM_RIFLE,
[ACT_RUN_RELAXED] = ACT_RUN_RIFLE_RELAXED,
[ACT_RUN_STIMULATED] = ACT_RUN_RIFLE_STIMULATED,
[ACT_RUN_AGITATED] = ACT_RUN_AIM_RIFLE,
[ACT_IDLE_AIM_RELAXED] = ACT_IDLE_SMG1_RELAXED,
[ACT_IDLE_AIM_STIMULATED] = ACT_IDLE_AIM_RIFLE_STIMULATED,
[ACT_IDLE_AIM_AGITATED] = ACT_IDLE_ANGRY_SMG1,
[ACT_WALK_AIM_RELAXED] = ACT_WALK_RIFLE_RELAXED,
[ACT_WALK_AIM_STIMULATED] = ACT_WALK_AIM_RIFLE_STIMULATED,
[ACT_WALK_AIM_AGITATED] = ACT_WALK_AIM_RIFLE,
[ACT_RUN_AIM_RELAXED] = ACT_RUN_RIFLE_RELAXED,
[ACT_RUN_AIM_STIMULATED] = ACT_RUN_AIM_RIFLE_STIMULATED,
[ACT_RUN_AIM_AGITATED] = ACT_RUN_AIM_RIFLE,
[ACT_WALK_AIM] = ACT_WALK_AIM_RIFLE,
[ACT_WALK_CROUCH] = ACT_WALK_CROUCH_RIFLE,
[ACT_WALK_CROUCH_AIM] = ACT_WALK_CROUCH_AIM_RIFLE,
[ACT_RUN] = ACT_RUN_RIFLE,
[ACT_RUN_AIM] = ACT_RUN_AIM_RIFLE,
[ACT_RUN_CROUCH] = ACT_RUN_CROUCH_RIFLE,
[ACT_RUN_CROUCH_AIM] = ACT_RUN_CROUCH_AIM_RIFLE,
[ACT_GESTURE_RANGE_ATTACK1] = ACT_GESTURE_RANGE_ATTACK_AR2,
[ACT_COVER_LOW] = ACT_COVER_SMG1_LOW,
[ACT_RANGE_AIM_LOW] = ACT_RANGE_AIM_AR2_LOW,
[ACT_RANGE_ATTACK1_LOW] = ACT_RANGE_ATTACK_SMG1_LOW,
[ACT_RELOAD_LOW] = ACT_RELOAD_SMG1_LOW,
[ACT_GESTURE_RELOAD] = ACT_GESTURE_RELOAD_SMG1
},
["smg"] = {
[ACT_IDLE] = ACT_IDLE_SMG1,
[ACT_IDLE_ANGRY] = ACT_IDLE_ANGRY_SMG1,
[ACT_RANGE_ATTACK1] = ACT_RANGE_ATTACK_SMG1,
[ACT_RELOAD] = ACT_RELOAD_SMG1,
[ACT_WALK_AIM] = ACT_WALK_AIM_RIFLE,
[ACT_RUN_AIM] = ACT_RUN_AIM_RIFLE,
[ACT_GESTURE_RANGE_ATTACK1] = ACT_GESTURE_RANGE_ATTACK_SMG1,
[ACT_RELOAD_LOW] = ACT_RELOAD_SMG1_LOW,
[ACT_RANGE_ATTACK1_LOW] = ACT_RANGE_ATTACK_SMG1_LOW,
[ACT_COVER_LOW] = ACT_COVER_SMG1_LOW,
[ACT_RANGE_AIM_LOW] = ACT_RANGE_AIM_SMG1_LOW,
[ACT_GESTURE_RELOAD] = ACT_GESTURE_RELOAD_SMG1
}
}
function SWEP:SetupWeaponHoldTypeForAI(t)
local usedT = HoldTypeTable[t or "ar2"] or HoldTypeTable["ar2"]
self.ActivityTranslateAI = table.Copy(usedT)
end
function SWEP:TranslateActivity(act)
if (self:GetOwner():IsNPC()) then
if (self.ActivityTranslateAI[act]) then return self.ActivityTranslateAI[act] end
return -1
end
if (self.ActivityTranslate[act] ~= nil) then return self.ActivityTranslate[act] end
return -1
end
function SWEP:GetCapabilities()
local ht = self.DefaultHoldType or self.HoldType or "pistol"
if ht == "melee" or ht == "melee2" or ht == "knife" or self.IsKnife then
return CAP_WEAPON_MELEE_ATTACK1
else
return bit.bor(CAP_WEAPON_RANGE_ATTACK1, CAP_INNATE_RANGE_ATTACK1)
end
end

View File

@@ -0,0 +1,59 @@
--[[
| 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.
SWEP.AnimCycle = SWEP.ViewModelFlip and 0 or 1
function SWEP:FixAkimbo()
if not self:GetStatL("IsAkimbo") or self.Secondary_TFA.ClipSize <= 0 then return end
self.Primary_TFA.ClipSize = self.Primary_TFA.ClipSize + self.Secondary_TFA.ClipSize
self.Secondary_TFA.ClipSize = -1
self.Primary_TFA.RPM = self.Primary_TFA.RPM * 2
self.Akimbo_Inverted = self.ViewModelFlip
self.AnimCycle = self.ViewModelFlip and 0 or 1
self:SetAnimCycle(self.AnimCycle)
self:ClearStatCache()
timer.Simple(FrameTime(), function()
timer.Simple(0.01, function()
if IsValid(self) and self:OwnerIsValid() then
self:SetClip1(self.Primary_TFA.ClipSize)
end
end)
end)
end
function SWEP:ToggleAkimbo(arg1)
if self:GetStatL("IsAkimbo") then
self:SetAnimCycle(1 - self:GetAnimCycle())
self.AnimCycle = self:GetAnimCycle()
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,727 @@
--[[
| 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 ATT_DIMENSION
local ATT_MAX_SCREEN_RATIO = 1 / 3
local tableCopy = table.Copy
SWEP.Attachments = {} --[MDL_ATTACHMENT] = = { offset = { 0, 0 }, atts = { "sample_attachment_1", "sample_attachment_2" }, sel = 1, order = 1 } --offset will move the offset the display from the weapon attachment when using CW2.0 style attachment display --atts is a table containing the visible attachments --sel allows you to have an attachment pre-selected, and is used internally by the base to show which attachment is selected in each category. --order is the order it will appear in the TFA style attachment menu
SWEP.AttachmentCache = {} --["att_name"] = true
SWEP.AttachmentTableCache = {}
SWEP.AttachmentCount = 0
SWEP.AttachmentDependencies = {} --{["si_acog"] = {"bg_rail"}}
SWEP.AttachmentExclusions = {} --{ ["si_iron"] = {"bg_heatshield"} }
SWEP.AttachmentTableOverride = {}
local pairs, type, tonumber = pairs, type, tonumber
local string, IsValid = string, IsValid
local table = table
function SWEP:RemoveUnusedAttachments()
for k, v in pairs(self.Attachments) do
if v.atts then
local t = {}
local i = 1
for _, b in pairs(v.atts) do
if TFA.Attachments.Atts[b] then
t[i] = b
i = i + 1
end
end
v.atts = tableCopy(t)
end
if #v.atts <= 0 then
self.Attachments[k] = nil
end
end
end
local function select_function_table(target)
-- idk
local found_table
for i_index, base_value in pairs(target) do
if istable(base_value) then
found_table = base_value
end
end
if not found_table then
found_table = {}
table.insert(target, found_table)
end
return found_table
end
local function get(path, target)
if #path == 1 then
return target[path[1]]
end
local _target = target[path[1]]
if _target == nil then
target[path[1]] = {}
_target = target[path[1]]
end
for i = 2, #path do
if not istable(_target) then
return
end
if _target[path[i]] == nil then _target[path[i]] = {} end
if istable(_target[path[i]]) and _target[path[i]].functionTable and i ~= #path then
_target = select_function_table(_target[path[i]])
else
_target = _target[path[i]]
end
end
return _target
end
local function set(path, target, value)
if #path == 1 then
target[path[1]] = value
return value
end
local _target = target[path[1]]
if _target == nil then
target[path[1]] = {}
_target = target[path[1]]
end
for i = 2, #path - 1 do
if not istable(_target) then
return value
end
if _target[path[i]] == nil then _target[path[i]] = {} end
if _target[path[i]].functionTable then
_target = select_function_table(_target[path[i]])
else
_target = _target[path[i]]
end
end
if istable(_target) then
if istable(_target[path[#path]]) and _target[path[#path]].functionTable then
table.insert(select_function_table(_target[path[#path]]), value)
else
_target[path[#path]] = value
end
end
return value
end
local function CloneTableRecursive(source, target, root, source_version, target_version)
for index, value in pairs(source) do
local _root = root == "" and index or (root .. "." .. index)
-- merge two tables
if istable(value) then
local baseTable = get(TFA.GetStatPath(_root, source_version, target_version), target)
-- target is a function table
if istable(baseTable) and baseTable.functionTable then
local found_table
for i_index, base_value in pairs(baseTable) do
if istable(base_value) then
found_table = base_value
end
end
if not found_table then
found_table = {}
table.insert(baseTable, 1, found_table)
end
CloneTableRecursive(value, target, _root, source_version, target_version)
-- target is a regular table
else
if not istable(baseTable) then
set(TFA.GetStatPath(_root, source_version, target_version), target, {})
end
CloneTableRecursive(value, target, _root, source_version, target_version)
end
-- final value is determined by function
elseif isfunction(value) then
local temp
local get_path = TFA.GetStatPath(_root, source_version, target_version)
local get_table = get(get_path, target)
if get_table ~= nil and not istable(get_table) then
temp = get_table
end
local get_value = not istable(get_table) and set(get_path, target, {}) or get_table
-- mark this table as function based
get_value.functionTable = true
if temp ~= nil then
-- insert variable that was there before
table.insert(get_value, temp)
end
-- insert function
table.insert(get_value, value)
-- final value is a scalar
else
local get_table = get(TFA.GetStatPath(_root, source_version, target_version), target)
if istable(get_table) and get_table.functionTable then
table.insert(get_table, 1, value)
else
set(TFA.GetStatPath(_root, source_version, target_version), target, value)
end
end
end
end
function SWEP:BuildAttachmentCache()
self.AttachmentCount = 0
for k, v in pairs(self.Attachments) do
if v.atts then
for l, b in pairs(v.atts) do
self.AttachmentCount = self.AttachmentCount + 1
self.AttachmentCache[b] = (v.sel == l) and k or false
end
end
end
table.Empty(self.AttachmentTableCache)
for attName, sel in pairs(self.AttachmentCache) do
if not sel then goto CONTINUE end
if not TFA.Attachments.Atts[attName] then goto CONTINUE end
local srctbl = TFA.Attachments.Atts[attName].WeaponTable
if istable(srctbl) then
CloneTableRecursive(srctbl, self.AttachmentTableCache, "", TFA.Attachments.Atts[attName].TFADataVersion or 0, self.TFADataVersion or 0)
end
if istable(self.AttachmentTableOverride[attName]) then
CloneTableRecursive(self.AttachmentTableOverride[attName], self.AttachmentTableCache, "", self.TFADataVersion or 0, self.TFADataVersion or 0)
end
::CONTINUE::
end
self:ClearStatCache()
self:ClearMaterialCache()
end
function SWEP:IsAttached(attn)
return isnumber(self.AttachmentCache[attn])
end
local tc
function SWEP:CanAttach(attn)
local retVal = hook.Run("TFA_PreCanAttach", self, attn)
if retVal ~= nil then return retVal end
local self2 = self:GetTable()
if not self2.HasBuiltMutualExclusions then
tc = tableCopy(self2.AttachmentExclusions)
for k, v in pairs(tc) do
if k ~= "BaseClass" then
for _, b in pairs(v) do
self2.AttachmentExclusions[b] = self2.AttachmentExclusions[b] or {}
if not table.HasValue(self2.AttachmentExclusions[b]) then
self2.AttachmentExclusions[b][#self2.AttachmentExclusions[b] + 1] = k
end
end
end
end
self2.HasBuiltMutualExclusions = true
end
if self.AttachmentExclusions[attn] then
for _, v in pairs(self.AttachmentExclusions[attn]) do
if self:IsAttached(v) then return false end
end
end
if self2.AttachmentDependencies[attn] then
local t = self2.AttachmentDependencies[attn]
if isstring(t) then
if t ~= "BaseClass" and not self2.IsAttached(self, t) then return false end
elseif istable(t) then
t.type = t.type or "OR"
if t.type == "AND" then
for k, v in pairs(self.AttachmentDependencies[attn]) do
if k ~= "BaseClass" and k ~= "type" and not self2.IsAttached(self, v) then return false end
end
else
local cnt = 0
for k, v in pairs(self.AttachmentDependencies[attn]) do
if k ~= "BaseClass" and k ~= "type" and self2.IsAttached(self, v) then
cnt = cnt + 1
end
end
if cnt == 0 then return false end
end
end
end
local atTable = TFA.Attachments.Atts[attn]
if not atTable or not atTable:CanAttach(self) then return false end
local retVal2 = hook.Run("TFA_CanAttach", self, attn)
if retVal2 ~= nil then return retVal2 end
return true
end
local ATTACHMENT_SORTING_DEPENDENCIES = false
function SWEP:ForceAttachmentReqs(attn)
if not ATTACHMENT_SORTING_DEPENDENCIES then
ATTACHMENT_SORTING_DEPENDENCIES = true
local related = {}
for k, v in pairs(self.AttachmentDependencies) do
if istable(v) then
for _, b in pairs(v) do
if k == attn then
related[b] = true
elseif b == attn then
related[k] = true
end
end
elseif isstring(v) then
if k == attn then
related[v] = true
elseif v == attn then
related[k] = true
end
end
end
for k, v in pairs(self.AttachmentExclusions) do
if istable(v) then
for _, b in pairs(v) do
if k == attn then
related[b] = true
elseif b == attn then
related[k] = true
end
end
elseif isstring(v) then
if k == attn then
related[v] = true
elseif v == attn then
related[k] = true
end
end
end
for k, v in pairs(self.AttachmentCache) do
if v and related[k] and not self:CanAttach(k) then
self:SetTFAAttachment(v, 0, true, true)
end
end
ATTACHMENT_SORTING_DEPENDENCIES = false
end
end
do
local self3, att_neue, att_old
local function attach()
att_neue:Attach(self3)
end
local function detach()
att_old:Detach(self3)
end
function SWEP:SetTFAAttachment(cat, id, nw, force)
self3 = self
local self2 = self:GetTable()
if not self2.Attachments[cat] then return false end
if isstring(id) then
if id == "" then
id = -1
else
id = table.KeyFromValue(self2.Attachments[cat].atts, id)
if not id then return false end
end
end
if id <= 0 and self2.Attachments[cat].default and type(self2.Attachments[cat].default) == "string" and self2.Attachments[cat].default ~= "" then
return self2.SetTFAAttachment(self, cat, self2.Attachments[cat].default, nw, force)
end
local attn = self2.Attachments[cat].atts[id] or ""
local attn_old = self2.Attachments[cat].atts[self2.Attachments[cat].sel or -1] or ""
if SERVER and id > 0 and not (force or self2.CanAttach(self, attn)) then return false end
if id ~= self2.Attachments[cat].sel then
att_old = TFA.Attachments.Atts[self2.Attachments[cat].atts[self2.Attachments[cat].sel] or -1]
local detach_status = att_old == nil
if att_old then
detach_status = ProtectedCall(detach)
if detach_status then
hook.Run("TFA_Attachment_Detached", self, attn_old, att_old, cat, id, force)
end
end
att_neue = TFA.Attachments.Atts[self2.Attachments[cat].atts[id] or -1]
local attach_status = att_neue == nil
if detach_status then
if att_neue then
attach_status = ProtectedCall(attach)
if attach_status then
hook.Run("TFA_Attachment_Attached", self, attn, att_neue, cat, id, force)
end
end
end
if detach_status and attach_status then
if id > 0 then
self2.Attachments[cat].sel = id
else
self2.Attachments[cat].sel = nil
end
end
end
self2.BuildAttachmentCache(self)
self2.ForceAttachmentReqs(self, (id > 0) and attn or attn_old)
if nw and (not isentity(nw) or SERVER) then
net.Start("TFA_Attachment_Set")
net.WriteUInt(cat, 8)
net.WriteString(attn)
if SERVER then
net.WriteEntity(self)
if isentity(nw) then
local filter = RecipientFilter()
filter:AddPVS(self:GetPos())
filter:RemovePlayer(nw)
net.Send(filter)
else
net.SendPVS(self:GetPos())
end
elseif CLIENT then
net.SendToServer()
end
end
return true
end
end
function SWEP:Attach(attname, force)
if not attname or not IsValid(self) then return false end
if self.AttachmentCache[attname] == nil then return false end
for cat, tbl in pairs(self.Attachments) do
local atts = tbl.atts
for id, att in ipairs(atts) do
if att == attname then return self:SetTFAAttachment(cat, id, true, force) end
end
end
return false
end
function SWEP:Detach(attname, force)
if not attname or not IsValid(self) then return false end
local cat = self.AttachmentCache[attname]
if not cat then return false end
return self:SetTFAAttachment(cat, 0, true, force)
end
function SWEP:RandomizeAttachments(force)
for key, slot in pairs(self.AttachmentCache) do
if slot then
self:Detach(key)
end
end
for category, def in pairs(self.Attachments) do
if istable(def) and istable(def.atts) and #def.atts > 0 then
if math.random() > 0.3 then
local randkey = math.random(1, #def.atts)
self:SetTFAAttachment(category, randkey, true, force)
end
end
end
end
local attachments_sorted_alphabetically = GetConVar("sv_tfa_attachments_alphabetical")
function SWEP:InitAttachments()
if self.HasInitAttachments then return end
hook.Run("TFA_PreInitAttachments", self)
self.HasInitAttachments = true
for k, v in pairs(self.Attachments) do
if type(k) == "string" then
local tatt = self:VMIV() and self.OwnerViewModel:LookupAttachment(k) or self:LookupAttachment(k)
if tatt > 0 then
self.Attachments[tatt] = v
end
self.Attachments[k] = nil
elseif (not attachments_sorted_alphabetically) and attachments_sorted_alphabetically:GetBool() then
local sval = v.atts[v.sel]
table.sort(v.atts, function(a, b)
local aname = ""
local bname = ""
local att_a = TFA.Attachments.Atts[a]
if att_a then
aname = att_a.Name or a
end
local att_b = TFA.Attachments.Atts[b]
if att_b then
bname = att_b.Name or b
end
return aname < bname
end)
if sval then
v.sel = table.KeyFromValue(v.atts, sval) or v.sel
end
end
end
for k, v in pairs(self.Attachments) do
if v.sel then
local vsel = v.sel
v.sel = nil
if type(vsel) == "string" then
vsel = table.KeyFromValue(v.atts, vsel) or tonumber(vsel)
if not vsel then goto CONTINUE end
end
timer.Simple(0, function()
if IsValid(self) and self.SetTFAAttachment then
self:SetTFAAttachment(k, vsel, false)
end
end)
if SERVER and game.SinglePlayer() then
timer.Simple(0.05, function()
if IsValid(self) and self.SetTFAAttachment then
self:SetTFAAttachment(k, vsel, true)
end
end)
end
end
::CONTINUE::
end
hook.Run("TFA_PostInitAttachments", self)
self:RemoveUnusedAttachments()
self:BuildAttachmentCache()
hook.Run("TFA_FinalInitAttachments", self)
end
function SWEP:GenerateVGUIAttachmentTable()
self.VGUIAttachments = {}
local keyz = table.GetKeys(self.Attachments)
table.RemoveByValue(keyz, "BaseClass")
table.sort(keyz, function(a, b)
--A and B are keys
local v1 = self.Attachments[a]
local v2 = self.Attachments[b]
if v1 and v2 and (v1.order or v2.order) then
return (v1.order or a) < (v2.order or b)
else
return a < b
end
end)
for _, k in ipairs(keyz) do
local v = self.Attachments[k]
if not v.hidden then
local aTbl = tableCopy(v)
aTbl.cat = k
aTbl.offset = nil
aTbl.order = nil
table.insert(self.VGUIAttachments, aTbl)
end
end
ATT_DIMENSION = math.Round(TFA.ScaleH(TFA.Attachments.IconSize))
local max_row_atts = math.floor(ScrW() * ATT_MAX_SCREEN_RATIO / ATT_DIMENSION)
local i = 1
while true do
local v = self.VGUIAttachments[i]
if not v then break end
i = i + 1
for l, b in pairs(v.atts) do
if not istable(b) then
v.atts[l] = {b, l} --name, ID
end
end
if (#v.atts > max_row_atts) then
while (#v.atts > max_row_atts) do
local t = tableCopy(v)
for _ = 1, max_row_atts do
table.remove(t.atts, 1)
end
for _ = 1, #v.atts - max_row_atts do
table.remove(v.atts)
end
table.insert(self.VGUIAttachments, i, t)
end
end
end
end
local bgt = {}
SWEP.ViewModelBodygroups = {}
SWEP.WorldModelBodygroups = {}
function SWEP:IterateBodygroups(entity, tablename, version)
local self2 = self:GetTable()
bgt = self2.GetStatVersioned(self, tablename, version or 0, self2[tablename])
for k, v in pairs(bgt) do
if isnumber(k) then
local bgn = entity:GetBodygroupName(k)
if bgt[bgn] then
v = bgt[bgn]
end
if entity:GetBodygroup(k) ~= v then
entity:SetBodygroup(k, v)
end
end
end
end
function SWEP:ProcessBodygroups()
local self2 = self:GetTable()
local ViewModelBodygroups = self:GetStatRawL("ViewModelBodygroups")
local WorldModelBodygroups = self:GetStatRawL("WorldModelBodygroups")
if not self2.HasFilledBodygroupTables then
if self2.VMIV(self) then
for i = 0, #(self2.OwnerViewModel:GetBodyGroups() or ViewModelBodygroups) do
ViewModelBodygroups[i] = ViewModelBodygroups[i] or 0
end
end
for i = 0, #(self:GetBodyGroups() or WorldModelBodygroups) do
WorldModelBodygroups[i] = WorldModelBodygroups[i] or 0
end
self2.HasFilledBodygroupTables = true
end
if self2.VMIV(self) then
self2.IterateBodygroups(self, self2.OwnerViewModel, "ViewModelBodygroups", TFA.LatestDataVersion)
end
self2.IterateBodygroups(self, self, "WorldModelBodygroups", TFA.LatestDataVersion)
end
function SWEP:CallAttFunc(funcName, ...)
for attName, sel in pairs(self.AttachmentCache or {}) do
if not sel then goto CONTINUE end
local att = TFA.Attachments.Atts[attName]
if not att then goto CONTINUE end
local attFunc = att[funcName]
if attFunc and type(attFunc) == "function" then
local _ret1, _ret2, _ret3, _ret4, _ret5, _ret6, _ret7, _ret8, _ret9, _ret10 = attFunc(att, self, ...)
if _ret1 ~= nil then
return _ret1, _ret2, _ret3, _ret4, _ret5, _ret6, _ret7, _ret8, _ret9, _ret10
end
end
::CONTINUE::
end
return nil
end

View File

@@ -0,0 +1,797 @@
--[[
| 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.
function SWEP:FixSprintAnimBob()
local self2 = self:GetTable()
if self:GetStatRawL("Sprint_Mode") == TFA.Enum.LOCOMOTION_ANI then
self:SetStatRawL("SprintBobMult", 0)
end
end
function SWEP:FixWalkAnimBob()
local self2 = self:GetTable()
if self:GetStatRawL("Walk_Mode") == TFA.Enum.LOCOMOTION_ANI then
self:SetStatRawL("WalkBobMult_Iron", self:GetStatRawL("WalkBobMult"))
self:SetStatRawL("WalkBobMult", 0)
end
end
function SWEP:PatchAmmoTypeAccessors()
local self2 = self:GetTable()
self:SetStatRawL("GetPrimaryAmmoTypeOld", self:GetStatRawL("GetPrimaryAmmoTypeOld") or self:GetStatRawL("GetPrimaryAmmoType"))
self:SetStatRawL("GetPrimaryAmmoType", function(myself, ...) return myself.GetPrimaryAmmoTypeC(myself, ...) end)
self:SetStatRawL("GetSecondaryAmmoTypeOld", self:GetStatRawL("GetSecondaryAmmoTypeOld") or self:GetStatRawL("GetSecondaryAmmoType"))
self:SetStatRawL("GetSecondaryAmmoType", function(myself, ...) return myself.GetSecondaryAmmoTypeC(myself, ...) end)
end
function SWEP:FixProjectile()
local self2 = self:GetTable()
if self:GetStatRawL("ProjectileEntity") and self:GetStatRawL("ProjectileEntity") ~= "" then
self:SetStatRawL("Primary.Projectile", self:GetStatRawL("ProjectileEntity"))
self:SetStatRawL("ProjectileEntity", nil)
end
if self:GetStatRawL("ProjectileModel") and self:GetStatRawL("ProjectileModel") ~= "" then
self:SetStatRawL("Primary.ProjectileModel", self:GetStatRawL("ProjectileModel"))
self:SetStatRawL("ProjectileModel", nil)
end
if self:GetStatRawL("ProjectileVelocity") and self:GetStatRawL("ProjectileVelocity") ~= "" then
self:SetStatRawL("Primary.ProjectileVelocity", self:GetStatRawL("ProjectileVelocity"))
self:SetStatRawL("ProjectileVelocity", nil)
end
end
local sv_tfa_range_modifier = GetConVar("sv_tfa_range_modifier")
function SWEP:AutoDetectRange()
local self2 = self:GetTable()
if self:GetStatL("Primary.FalloffMetricBased") and not self:GetStatRawL("Primary.RangeFalloffLUT") then
self:SetStatRawL("Primary.RangeFalloffLUT_IsConverted", true)
self:SetStatRawL("Primary.RangeFalloffLUT", {
bezier = false,
range_func = "linear", -- function to spline range
units = "meters",
lut = {
{range = self:GetStatL("Primary.MinRangeStartFalloff"), damage = 1},
{range = self:GetStatL("Primary.MinRangeStartFalloff") + self:GetStatL("Primary.MaxFalloff") / self:GetStatL("Primary.FalloffByMeter"),
damage = (self:GetStatL("Primary.Damage") - self:GetStatL("Primary.MaxFalloff")) / self:GetStatL("Primary.Damage")},
}
})
return
end
if self:GetStatL("Primary.FalloffMetricBased") or self:GetStatL("Primary.RangeFalloffLUT") then return end
if self:GetStatL("Primary.Range") <= 0 then
self:SetStatRawL("Primary.Range", math.sqrt(self:GetStatL("Primary.Damage") / 32) * self:MetersToUnits(350) * self:AmmoRangeMultiplier())
end
if self:GetStatL("Primary.RangeFalloff") <= 0 then
self:SetStatRawL("Primary.RangeFalloff", 0.5)
end
self:SetStatRawL("Primary.RangeFalloffLUT_IsConverted", true)
self:SetStatRawL("Primary.RangeFalloffLUT", {
bezier = false,
range_func = "linear", -- function to spline range
units = "hammer",
lut = {
{range = self:GetStatL("Primary.Range") * self:GetStatL("Primary.RangeFalloff"), damage = 1},
{range = self:GetStatL("Primary.Range"), damage = 1 - sv_tfa_range_modifier:GetFloat()},
}
})
end
function SWEP:FixProceduralReload()
-- do nothing
end
function SWEP:FixRPM()
local self2 = self:GetTable()
if not self:GetStatRawL("Primary.RPM") then
if self:GetStatRawL("Primary.Delay") then
self:SetStatRawL("Primary.RPM", 60 / self:GetStatRawL("Primary.Delay"))
else
self:SetStatRawL("Primary.RPM", 120)
end
end
end
function SWEP:FixCone()
local self2 = self:GetTable()
if self:GetStatRawL("Primary.Cone") then
if (not self:GetStatRawL("Primary.Spread")) or self:GetStatRawL("Primary.Spread") < 0 then
self:SetStatRawL("Primary.Spread", self:GetStatRawL("Primary.Cone"))
end
self:SetStatRawL("Primary.Cone", nil)
end
end
--legacy compatibility
function SWEP:FixIdles()
local self2 = self:GetTable()
if self:GetStatRawL("DisableIdleAnimations") ~= nil and self:GetStatRawL("DisableIdleAnimations") == true then
self:SetStatRawL("Idle_Mode", TFA.Enum.IDLE_LUA)
end
end
function SWEP:FixIS()
local self2 = self:GetTable()
if self:GetStatRawL("SightsPos") and (not self:GetStatRawL("IronSightsPosition") or (self:GetStatRawL("IronSightsPosition").x ~= self:GetStatRawL("SightsPos").x and self:GetStatRawL("SightsPos").x ~= 0)) then
self:SetStatRawL("IronSightsPosition", self:GetStatRawL("SightsPos") or Vector())
self:SetStatRawL("IronSightsAngle", self:GetStatRawL("SightsAng") or Vector())
end
end
local legacy_spread_cv = GetConVar("sv_tfa_spread_legacy")
function SWEP:AutoDetectSpread()
local self2 = self:GetTable()
if legacy_spread_cv and legacy_spread_cv:GetBool() then
self:SetUpSpreadLegacy()
return
end
if self:GetStatRawL("Primary.SpreadMultiplierMax") == -1 or not self:GetStatRawL("Primary.SpreadMultiplierMax") then
self:SetStatRawL("Primary.SpreadMultiplierMax", math.Clamp(math.sqrt(math.sqrt(self:GetStatRawL("Primary.Damage") / 35) * 10 / 5) * 5, 0.01 / self:GetStatRawL("Primary.Spread"), 0.1 / self:GetStatRawL("Primary.Spread")))
end
if self:GetStatRawL("Primary.SpreadIncrement") == -1 or not self:GetStatRawL("Primary.SpreadIncrement") then
self:SetStatRawL("Primary.SpreadIncrement", self:GetStatRawL("Primary.SpreadMultiplierMax") * 60 / self:GetStatRawL("Primary.RPM") * 0.85 * 1.5)
end
if self:GetStatRawL("Primary.SpreadRecovery") == -1 or not self:GetStatRawL("Primary.SpreadRecovery") then
self:SetStatRawL("Primary.SpreadRecovery", math.max(self:GetStatRawL("Primary.SpreadMultiplierMax") * math.pow(self:GetStatRawL("Primary.RPM") / 600, 1 / 3) * 0.75, self:GetStatRawL("Primary.SpreadMultiplierMax") / 1.5))
end
end
--[[
Function Name: AutoDetectMuzzle
Syntax: self:AutoDetectMuzzle(). Call only once, or it's redundant.
Returns: Nothing.
Notes: Detects the proper muzzle flash effect if you haven't specified one.
Purpose: Autodetection
]]
--
function SWEP:AutoDetectMuzzle()
local self2 = self:GetTable()
if not self:GetStatRawL("MuzzleFlashEffect") then
local a = string.lower(self:GetStatRawL("Primary.Ammo"))
local cat = string.lower(self:GetStatRawL("Category") and self:GetStatRawL("Category") or "")
if self:GetStatRawL("Silenced") or self:GetSilenced() then
self:SetStatRawL("MuzzleFlashEffect", "tfa_muzzleflash_silenced")
elseif string.find(a, "357") or self:GetStatRawL("Revolver") or string.find(cat, "revolver") then
self:SetStatRawL("MuzzleFlashEffect", "tfa_muzzleflash_revolver")
elseif self:GetStatL("LoopedReload") or a == "buckshot" or a == "slam" or a == "airboatgun" or string.find(cat, "shotgun") then
self:SetStatRawL("MuzzleFlashEffect", "tfa_muzzleflash_shotgun")
elseif string.find(a, "smg") or string.find(cat, "smg") or string.find(cat, "submachine") or string.find(cat, "sub-machine") then
self:SetStatRawL("MuzzleFlashEffect", "tfa_muzzleflash_smg")
elseif string.find(a, "sniper") or string.find(cat, "sniper") then
self:SetStatRawL("MuzzleFlashEffect", "tfa_muzzleflash_sniper")
elseif string.find(a, "pistol") or string.find(cat, "pistol") then
self:SetStatRawL("MuzzleFlashEffect", "tfa_muzzleflash_pistol")
elseif string.find(a, "ar2") or string.find(a, "rifle") or (string.find(cat, "revolver") and not string.find(cat, "rifle")) then
self:SetStatRawL("MuzzleFlashEffect", "tfa_muzzleflash_rifle")
else
self:SetStatRawL("MuzzleFlashEffect", "tfa_muzzleflash_generic")
end
end
end
--[[
Function Name: AutoDetectDamage
Syntax: self:AutoDetectDamage(). Call only once. Hopefully you call this only once on like SWEP:Initialize() or something.
Returns: Nothing.
Notes: Fixes the damage for GDCW.
Purpose: Autodetection
]]
--
function SWEP:AutoDetectDamage()
local self2 = self:GetTable()
if self:GetStatRawL("Primary.Damage") and self:GetStatRawL("Primary.Damage") ~= -1 then return end
if self:GetStatRawL("Primary.Round") then
local rnd = string.lower(self:GetStatRawL("Primary.Round"))
if string.find(rnd, ".50bmg") then
self:SetStatRawL("Primary.Damage", 185)
elseif string.find(rnd, "5.45x39") then
self:SetStatRawL("Primary.Damage", 22)
elseif string.find(rnd, "5.56x45") then
self:SetStatRawL("Primary.Damage", 30)
elseif string.find(rnd, "338_lapua") then
self:SetStatRawL("Primary.Damage", 120)
elseif string.find(rnd, "338") then
self:SetStatRawL("Primary.Damage", 100)
elseif string.find(rnd, "7.62x51") then
self:SetStatRawL("Primary.Damage", 100)
elseif string.find(rnd, "9x39") then
self:SetStatRawL("Primary.Damage", 32)
elseif string.find(rnd, "9mm") then
self:SetStatRawL("Primary.Damage", 22)
elseif string.find(rnd, "9x19") then
self:SetStatRawL("Primary.Damage", 22)
elseif string.find(rnd, "9x18") then
self:SetStatRawL("Primary.Damage", 20)
end
if string.find(rnd, "ap") then
self:SetStatRawL("Primary.Damage", self:GetStatRawL("Primary.Damage") * 1.2)
end
end
if (not self:GetStatRawL("Primary.Damage")) or (self:GetStatRawL("Primary.Damage") <= 0.01) and self:GetStatRawL("Velocity") then
self:SetStatRawL("Primary.Damage", self:GetStatRawL("Velocity") / 5)
end
if (not self:GetStatRawL("Primary.Damage")) or (self:GetStatRawL("Primary.Damage") <= 0.01) then
self:SetStatRawL("Primary.Damage", (self:GetStatRawL("Primary.KickUp") + self:GetStatRawL("Primary.KickUp") + self:GetStatRawL("Primary.KickUp")) * 10)
end
end
--[[
Function Name: AutoDetectDamageType
Syntax: self:AutoDetectDamageType(). Call only once. Hopefully you call this only once on like SWEP:Initialize() or something.
Returns: Nothing.
Notes: Sets a damagetype
Purpose: Autodetection
]]
--
function SWEP:AutoDetectDamageType()
local self2 = self:GetTable()
if self:GetStatRawL("Primary.DamageType") == -1 or not self:GetStatRawL("Primary.DamageType") then
if self:GetStatRawL("DamageType") and not self:GetStatRawL("Primary.DamageType") then
self:SetStatRawL("Primary.DamageType", self:GetStatRawL("DamageType"))
else
self:SetStatRawL("Primary.DamageType", DMG_BULLET)
end
end
end
--[[
Function Name: AutoDetectForce
Syntax: self:AutoDetectForce(). Call only once. Hopefully you call this only once on like SWEP:Initialize() or something.
Returns: Nothing.
Notes: Detects force from damage
Purpose: Autodetection
]]
--
function SWEP:AutoDetectForce()
local self2 = self:GetTable()
if self:GetStatRawL("Primary.Force") == -1 or not self:GetStatRawL("Primary.Force") then
self:SetStatRawL("Primary.Force", self:GetStatRawL("Force") or (math.sqrt(self:GetStatRawL("Primary.Damage") / 16) * 3 / math.sqrt(self:GetStatRawL("Primary.NumShots"))))
end
end
function SWEP:AutoDetectPenetrationPower()
local self2 = self:GetTable()
if self:GetStatRawL("Primary.PenetrationPower") == -1 or not self:GetStatRawL("Primary.PenetrationPower") then
local am = string.lower(self:GetStatL("Primary.Ammo"))
local m = 1
if (am == "pistol") then
m = 0.4
elseif (am == "357") then
m = 1.75
elseif (am == "smg1") then
m = 0.34
elseif (am == "ar2") then
m = 1.1
elseif (am == "buckshot") then
m = 0.3
elseif (am == "airboatgun") then
m = 2.25
elseif (am == "sniperpenetratedround") then
m = 3
end
self:SetStatRawL("Primary.PenetrationPower", self:GetStatRawL("PenetrationPower") or math.sqrt(self:GetStatRawL("Primary.Force") * 200 * m))
end
end
--[[
Function Name: AutoDetectKnockback
Syntax: self:AutoDetectKnockback(). Call only once. Hopefully you call this only once on like SWEP:Initialize() or something.
Returns: Nothing.
Notes: Detects knockback from force
Purpose: Autodetection
]]
--
function SWEP:AutoDetectKnockback()
local self2 = self:GetTable()
if self:GetStatRawL("Primary.Knockback") == -1 or not self:GetStatRawL("Primary.Knockback") then
self:SetStatRawL("Primary.Knockback", self:GetStatRawL("Knockback") or math.max(math.pow(self:GetStatRawL("Primary.Force") - 3.25, 2), 0) * math.pow(self:GetStatRawL("Primary.NumShots"), 1 / 3))
end
end
--[[
Function Name: IconFix
Syntax: self:IconFix(). Call only once. Hopefully you call this only once on like SWEP:Initialize() or something.
Returns: Nothing.
Notes: Fixes the icon. Call this if you give it a texture path, or just nothing.
Purpose: Autodetection
]]
--
local selicon_final = {}
function SWEP:IconFix()
local self2 = self:GetTable()
if not surface then return end
local class = self2.ClassName
if selicon_final[class] then
self:SetStatRawL("WepSelectIcon", selicon_final[class])
return
end
if self2.WepSelectIcon and type(self2.WepSelectIcon) == "string" then
self:SetStatRawL("WepSelectIcon", surface.GetTextureID(self2.WepSelectIcon))
else
if file.Exists("materials/vgui/hud/" .. class .. ".png", "GAME") then
self:SetStatRawL("WepSelectIcon", Material("vgui/hud/" .. class .. ".png", "smooth noclamp")) -- NOTHING should access this variable directly and our DrawWeaponSelection override supports IMaterial.
elseif file.Exists("materials/vgui/hud/" .. class .. ".vmt", "GAME") then
self:SetStatRawL("WepSelectIcon", surface.GetTextureID("vgui/hud/" .. class))
end
end
selicon_final[class] = self2.WepSelectIcon
end
--[[
Function Name: CorrectScopeFOV
Syntax: self:CorrectScopeFOV( fov ). Call only once. Hopefully you call this only once on like SWEP:Initialize() or something.
Returns: Nothing.
Notes: If you're using scopezoom instead of FOV, this translates it.
Purpose: Autodetection
]]
--
function SWEP:CorrectScopeFOV(fov)
local self2 = self:GetTable()
fov = fov or self:GetStatRawL("DefaultFOV")
if not self:GetStatRawL("Secondary.OwnerFOV") or self:GetStatRawL("Secondary.OwnerFOV") <= 0 then
if self:GetStatRawL("Scoped") then
self:SetStatRawL("Secondary.OwnerFOV", fov / (self:GetStatRawL("Secondary.ScopeZoom") and self:GetStatRawL("Secondary.ScopeZoom") or 2))
else
self:SetStatRawL("Secondary.OwnerFOV", 32)
end
end
end
--[[
Function Name: CreateFireModes
Syntax: self:CreateFireModes( is first draw). Call as much as you like. isfirstdraw controls whether the default fire mode is set.
Returns: Nothing.
Notes: Autodetects fire modes depending on what params you set up.
Purpose: Autodetection
]]
--
SWEP.FireModeCache = {}
function SWEP:CreateFireModes(isfirstdraw)
local self2 = self:GetTable()
if not self2.FireModes then
self:SetStatRawL("FireModes", {})
local burstcnt = self:FindEvenBurstNumber()
if self2.SelectiveFire then
if self2.OnlyBurstFire then
if burstcnt then
self2.FireModes[1] = burstcnt .. "Burst"
self2.FireModes[2] = "Single"
else
self2.FireModes[1] = "Single"
end
else
self2.FireModes[1] = "Automatic"
if self2.DisableBurstFire then
self2.FireModes[2] = "Single"
else
if burstcnt then
self2.FireModes[2] = burstcnt .. "Burst"
self2.FireModes[3] = "Single"
else
self2.FireModes[2] = "Single"
end
end
end
else
if self2.Primary_TFA.Automatic then
self2.FireModes[1] = "Automatic"
if self2.OnlyBurstFire and burstcnt then
self2.FireModes[1] = burstcnt .. "Burst"
end
else
self2.FireModes[1] = "Single"
end
end
end
if self2.FireModes[#self2.FireModes] ~= "Safe" then
self2.FireModes[#self2.FireModes + 1] = "Safe"
end
if not self2.FireModeCache or #self2.FireModeCache <= 0 then
for k, v in ipairs(self2.FireModes) do
self2.FireModeCache[v] = k
end
if type(self2.DefaultFireMode) == "number" then
self:SetFireMode(self2.DefaultFireMode or (self2.Primary_TFA.Automatic and 1 or #self2.FireModes - 1))
else
self:SetFireMode(self2.FireModeCache[self2.DefaultFireMode] or (self2.Primary_TFA.Automatic and 1 or #self2.FireModes - 1))
end
end
end
--[[
Function Name: CacheAnimations
Syntax: self:CacheAnimations(). Call as much as you like.
Returns: Nothing.
Notes: This is what autodetects animations for the SWEP.SequenceEnabled and SWEP.SequenceLength tables.
Purpose: Autodetection
]]
--
--SWEP.actlist = {ACT_VM_DRAW, ACT_VM_DRAW_EMPTY, ACT_VM_DRAW_SILENCED, ACT_VM_DRAW_DEPLOYED, ACT_VM_HOLSTER, ACT_VM_HOLSTER_EMPTY, ACT_VM_IDLE, ACT_VM_IDLE_EMPTY, ACT_VM_IDLE_SILENCED, ACT_VM_PRIMARYATTACK, ACT_VM_PRIMARYATTACK_1, ACT_VM_PRIMARYATTACK_EMPTY, ACT_VM_PRIMARYATTACK_SILENCED, ACT_VM_SECONDARYATTACK, ACT_VM_RELOAD, ACT_VM_RELOAD_EMPTY, ACT_VM_RELOAD_SILENCED, ACT_VM_ATTACH_SILENCER, ACT_VM_RELEASE, ACT_VM_DETACH_SILENCER, ACT_VM_FIDGET, ACT_VM_FIDGET_EMPTY, ACT_VM_FIDGET_SILENCED, ACT_SHOTGUN_RELOAD_START, ACT_VM_DRYFIRE, ACT_VM_DRYFIRE_SILENCED }
--If you really want, you can remove things from SWEP.actlist and manually enable animations and set their lengths.
SWEP.SequenceEnabled = {}
SWEP.SequenceLength = {}
SWEP.SequenceLengthOverride = {} --Override this if you want to change the length of a sequence but not the next idle
SWEP.ActCache = {}
local vm, seq
function SWEP:CacheAnimations()
local self2 = self:GetTable()
table.Empty(self2.ActCache)
if self:GetStatRawL("CanBeSilenced") and self2.SequenceEnabled[ACT_VM_IDLE_SILENCED] == nil then
self2.SequenceEnabled[ACT_VM_IDLE_SILENCED] = true
end
if not self:VMIV() then return end
vm = self2.OwnerViewModel
if IsValid(vm) then
self:BuildAnimActivities()
for _, v in ipairs(table.GetKeys(self2.AnimationActivities)) do
if isnumber(v) then
seq = vm:SelectWeightedSequence(v)
if seq ~= -1 and vm:GetSequenceActivity(seq) == v and not self2.ActCache[seq] then
self2.SequenceEnabled[v] = true
self2.SequenceLength[v] = vm:SequenceDuration(seq)
self2.ActCache[seq] = v
else
self2.SequenceEnabled[v] = false
self2.SequenceLength[v] = 0.0
end
else
local s = vm:LookupSequence(v)
if s and s > 0 then
self2.SequenceEnabled[v] = true
self2.SequenceLength[v] = vm:SequenceDuration(s)
self2.ActCache[s] = v
else
self2.SequenceEnabled[v] = false
self2.SequenceLength[v] = 0.0
end
end
end
else
return false
end
if self:GetStatRawL("ProceduralHolsterEnabled") == nil then
if self2.SequenceEnabled[ACT_VM_HOLSTER] then
self:SetStatRawL("ProceduralHolsterEnabled", false)
else
self:SetStatRawL("ProceduralHolsterEnabled", true)
end
end
self:SetStatRawL("HasDetectedValidAnimations", true)
return true
end
function SWEP:GetType()
local self2 = self:GetTable()
if self:GetStatRawL("Type") then return self:GetStatRawL("Type") end
local at = string.lower(self:GetStatRawL("Primary.Ammo") or "")
local ht = string.lower((self:GetStatRawL("DefaultHoldType") or self:GetStatRawL("HoldType")) or "")
local rpm = self:GetStatRawL("Primary.RPM_Displayed") or self:GetStatRawL("Primary.RPM") or 600
if self:GetStatRawL("Primary.ProjectileEntity") or self:GetStatRawL("ProjectileEntity") then
if (self:GetStatRawL("ProjectileVelocity") or self:GetStatRawL("Primary.ProjectileVelocity")) > 400 then
self:SetStatRawL("Type", "Launcher")
else
self:SetStatRawL("Type", "Grenade")
end
return
end
if at == "buckshot" then
self:SetStatRawL("Type", "Shotgun")
return self:GetType()
end
if self:GetStatRawL("Pistol") or (at == "pistol" and ht == "pistol") then
self:SetStatRawL("Type", "Pistol")
return self:GetType()
end
if self:GetStatRawL("SMG") or (at == "smg1" and (ht == "smg" or ht == "pistol" or ht == "357")) then
self:SetStatRawL("Type", "Sub-Machine Gun")
return self:GetType()
end
if self:GetStatRawL("Revolver") or (at == "357" and ht == "revolver") then
self:SetStatRawL("Type", "Revolver")
return self:GetType()
end
--Detect Sniper Type
if ( (self:GetStatRawL("Scoped") or self:GetStatRawL("Scoped_3D")) and rpm < 600 ) or at == "sniperpenetratedround" then
if rpm > 180 and (self:GetStatRawL("Primary.Automatic") or self:GetStatRawL("Primary.SelectiveFire")) then
self:SetStatRawL("Type", "Designated Marksman Rifle")
return self:GetType()
else
self:SetStatRawL("Type", "Sniper Rifle")
return self:GetType()
end
end
--Detect based on holdtype
if ht == "pistol" then
if self:GetStatRawL("Primary.Automatic") then
self:SetStatRawL("Type", "Machine Pistol")
else
self:SetStatRawL("Type", "Pistol")
end
return self:GetType()
end
if ht == "duel" then
if at == "pistol" then
self:SetStatRawL("Type", "Dual Pistols")
return self:GetType()
elseif at == "357" then
self:SetStatRawL("Type", "Dual Revolvers")
return self:GetType()
elseif at == "smg1" then
self:SetStatRawL("Type", "Dual Sub-Machine Guns")
return self:GetType()
else
self:SetStatRawL("Type", "Dual Guns")
return self:GetType()
end
end
--If it's using rifle ammo, it's a rifle or a carbine
if at == "ar2" then
if self:GetStatRawL("Primary.ClipSize") >= 60 then
self:SetStatRawL("Type", "Light Machine Gun")
return self:GetType()
elseif ht == "rpg" or ht == "revolver" then
self:SetStatRawL("Type", "Carbine")
return self:GetType()
else
self:SetStatRawL("Type", "Rifle")
return self:GetType()
end
end
--Check SMG one last time
if ht == "smg" or at == "smg1" then
self:SetStatRawL("Type", "Sub-Machine Gun")
return self:GetType()
end
--Fallback to generic
self:SetStatRawL("Type", "Weapon")
return self:GetType()
end
function SWEP:SetUpSpreadLegacy()
local self2 = self:GetTable()
local ht = self:GetStatRawL("DefaultHoldType") and self:GetStatRawL("DefaultHoldType") or self:GetStatRawL("HoldType")
if not self:GetStatRawL("Primary.SpreadMultiplierMax") or self:GetStatRawL("Primary.SpreadMultiplierMax") <= 0 or self:GetStatRawL("AutoDetectSpreadMultiplierMax") then
self:SetStatRawL("Primary.SpreadMultiplierMax", 2.5 * math.max(self:GetStatRawL("Primary.RPM"), 400) / 600 * math.sqrt(self:GetStatRawL("Primary.Damage") / 30 * self:GetStatRawL("Primary.NumShots"))) --How far the spread can expand when you shoot.
if ht == "smg" then
self:SetStatRawL("Primary.SpreadMultiplierMax", self:GetStatRawL("Primary.SpreadMultiplierMax") * 0.8)
end
if ht == "revolver" then
self:SetStatRawL("Primary.SpreadMultiplierMax", self:GetStatRawL("Primary.SpreadMultiplierMax") * 2)
end
if self:GetStatRawL("Scoped") then
self:SetStatRawL("Primary.SpreadMultiplierMax", self:GetStatRawL("Primary.SpreadMultiplierMax") * 1.5)
end
self:SetStatRawL("AutoDetectSpreadMultiplierMax", true)
end
if not self:GetStatRawL("Primary.SpreadIncrement") or self:GetStatRawL("Primary.SpreadIncrement") <= 0 or self:GetStatRawL("AutoDetectSpreadIncrement") then
self:SetStatRawL("AutoDetectSpreadIncrement", true)
self:SetStatRawL("Primary.SpreadIncrement", 1 * math.Clamp(math.sqrt(self:GetStatRawL("Primary.RPM")) / 24.5, 0.7, 3) * math.sqrt(self:GetStatRawL("Primary.Damage") / 30 * self:GetStatRawL("Primary.NumShots"))) --What percentage of the modifier is added on, per shot.
if ht == "revolver" then
self:SetStatRawL("Primary.SpreadIncrement", self:GetStatRawL("Primary.SpreadIncrement") * 2)
end
if ht == "pistol" then
self:SetStatRawL("Primary.SpreadIncrement", self:GetStatRawL("Primary.SpreadIncrement") * 1.35)
end
if ht == "ar2" or ht == "rpg" then
self:SetStatRawL("Primary.SpreadIncrement", self:GetStatRawL("Primary.SpreadIncrement") * 0.65)
end
if ht == "smg" then
self:SetStatRawL("Primary.SpreadIncrement", self:GetStatRawL("Primary.SpreadIncrement") * 1.75)
self:SetStatRawL("Primary.SpreadIncrement", self:GetStatRawL("Primary.SpreadIncrement") * (math.Clamp((self:GetStatRawL("Primary.RPM") - 650) / 150, 0, 1) + 1))
end
if ht == "pistol" and self:GetStatRawL("Primary.Automatic") == true then
self:SetStatRawL("Primary.SpreadIncrement", self:GetStatRawL("Primary.SpreadIncrement") * 1.5)
end
if self:GetStatRawL("Scoped") then
self:SetStatRawL("Primary.SpreadIncrement", self:GetStatRawL("Primary.SpreadIncrement") * 1.25)
end
self:SetStatRawL("Primary.SpreadIncrement", self:GetStatRawL("Primary.SpreadIncrement") * math.sqrt(self:GetStatRawL("Primary.Recoil") * (self:GetStatRawL("Primary.KickUp") + self:GetStatRawL("Primary.KickDown") + self:GetStatRawL("Primary.KickHorizontal"))) * 0.8)
end
if not self:GetStatRawL("Primary.SpreadRecovery") or self:GetStatRawL("Primary.SpreadRecovery") <= 0 or self:GetStatRawL("AutoDetectSpreadRecovery") then
self:SetStatRawL("AutoDetectSpreadRecovery", true)
self:SetStatRawL("Primary.SpreadRecovery", math.sqrt(math.max(self:GetStatRawL("Primary.RPM"), 300)) / 29 * 4) --How much the spread recovers, per second.
if ht == "smg" then
self:SetStatRawL("Primary.SpreadRecovery", self:GetStatRawL("Primary.SpreadRecovery") * (1 - math.Clamp((self:GetStatRawL("Primary.RPM") - 600) / 200, 0, 1) * 0.33))
end
end
end
SWEP.LowAmmoSoundTypeBlacklist = {
["launcher"] = true,
["grenade"] = true,
}
SWEP.LowAmmoSoundByType = {
["handgun"] = "TFA.LowAmmo.Handgun",
["pistol"] = "TFA.LowAmmo.Handgun",
["dualpistols"] = "TFA.LowAmmo.Handgun",
["machinepistol"] = "TFA.LowAmmo.Handgun",
["handcannon"] = "TFA.LowAmmo.Revolver",
["revolver"] = "TFA.LowAmmo.Revolver",
["dualrevolvers"] = "TFA.LowAmmo.Revolver",
["shotgun"] = "TFA.LowAmmo.Shotgun",
["machinegun"] = "TFA.LowAmmo.MachineGun",
["lightmachinegun"] = "TFA.LowAmmo.MachineGun",
["heavymachinegun"] = "TFA.LowAmmo.MachineGun",
["carbine"] = "TFA.LowAmmo.AssaultRifle",
["rifle"] = "TFA.LowAmmo.AssaultRifle",
["assaultrifle"] = "TFA.LowAmmo.AssaultRifle",
["dmr"] = "TFA.LowAmmo.DMR",
["designatedmarksmanrifle"] = "TFA.LowAmmo.DMR",
["sniperrifle"] = "TFA.LowAmmo.Sniper",
["smg"] = "TFA.LowAmmo.SMG",
["submachinegun"] = "TFA.LowAmmo.SMG",
}
SWEP.LastAmmoSoundByType = {
["handgun"] = "TFA.LowAmmo.Handgun_Dry",
["pistol"] = "TFA.LowAmmo.Handgun_Dry",
["dualpistols"] = "TFA.LowAmmo.Handgun_Dry",
["machinepistol"] = "TFA.LowAmmo.Handgun_Dry",
["handcannon"] = "TFA.LowAmmo.Revolver_Dry",
["revolver"] = "TFA.LowAmmo.Revolver_Dry",
["dualrevolvers"] = "TFA.LowAmmo.Revolver_Dry",
["shotgun"] = "TFA.LowAmmo.Shotgun_Dry",
["machinegun"] = "TFA.LowAmmo.MachineGun_Dry",
["lightmachinegun"] = "TFA.LowAmmo.MachineGun_Dry",
["heavymachinegun"] = "TFA.LowAmmo.MachineGun_Dry",
["carbine"] = "TFA.LowAmmo.AssaultRifle_Dry",
["rifle"] = "TFA.LowAmmo.AssaultRifle_Dry",
["assaultrifle"] = "TFA.LowAmmo.AssaultRifle_Dry",
["dmr"] = "TFA.LowAmmo.DMR_Dry",
["designatedmarksmanrifle"] = "TFA.LowAmmo.DMR_Dry",
["sniperrifle"] = "TFA.LowAmmo.Sniper_Dry",
["smg"] = "TFA.LowAmmo.SMG_Dry",
["submachinegun"] = "TFA.LowAmmo.SMG_Dry",
}
function SWEP:AutoDetectLowAmmoSound()
if not self.FireSoundAffectedByClipSize then return end
local t1, t2 = self:GetType():lower():gsub("[^%w]+", ""), (self:GetStatRawL("Type_Displayed") or ""):lower():gsub("[^%w]+", "")
if self.LowAmmoSoundTypeBlacklist[t2] or self.LowAmmoSoundTypeBlacklist[t1] then return end
local clip1 = self:GetStatRawL("Primary.ClipSize")
if (not clip1 or clip1 <= 4) then return end
if not self.LowAmmoSound then
local snd = self.LowAmmoSoundByType[t2] or self.LowAmmoSoundByType[t1] or "TFA.LowAmmo"
if (t2 == "shotgun" or t1 == "shotgun") and not self:GetStatL("LoopedReload") then
snd = "TFA.LowAmmo.AutoShotgun"
end
self:SetStatRawL("LowAmmoSound", snd)
end
if not self.LastAmmoSound then
local snd = self.LastAmmoSoundByType[t2] or self.LastAmmoSoundByType[t1] or "TFA.LowAmmo_Dry"
if (t2 == "shotgun" or t1 == "shotgun") and not self:GetStatL("LoopedReload") then
snd = "TFA.LowAmmo.AutoShotgun_Dry"
end
self:SetStatRawL("LastAmmoSound", snd)
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,313 @@
--[[
| 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.
TFA.GUESS_NPC_WALKSPEED = 160
local function l_Lerp(t, a, b) return a + (b - a) * t end
local function l_mathMin(a, b) return (a < b) and a or b end
local function l_mathMax(a, b) return (a > b) and a or b end
local function l_ABS(a) return (a < 0) and -a or a end
local function l_mathClamp(t, a, b)
if a > b then return b end
if t > b then
return b
end
if t < a then
return a
end
return t
end
local function l_mathApproach(a, b, delta)
if a < b then
return l_mathMin(a + l_ABS(delta), b)
else
return l_mathMax(a - l_ABS(delta), b)
end
end
local sprint_cv = GetConVar("sv_tfa_sprint_enabled")
local sv_tfa_weapon_weight = GetConVar("sv_tfa_weapon_weight")
function SWEP:TFAFinishMove(ply, velocity, movedata)
local ft = FrameTime()
local self2 = self:GetTable()
local isply = ply:IsPlayer()
if CLIENT then
self2.LastUnpredictedVelocity = velocity
end
local speedmult = Lerp(self:GetIronSightsProgress(), sv_tfa_weapon_weight:GetBool() and self:GetStatL("RegularMoveSpeedMultiplier") or 1, self:GetStatL("AimingDownSightsSpeedMultiplier"))
local jr_targ = math.min(math.abs(velocity.z) / 500, 1)
self:SetJumpRatio(l_mathApproach(self:GetJumpRatio(), jr_targ, (jr_targ - self:GetJumpRatio()) * ft * 20))
self2.JumpRatio = self:GetJumpRatio()
self:SetCrouchingRatio(l_mathApproach(self:GetCrouchingRatio(), (self:IsOwnerCrouching()) and 1 or 0, ft / self2.ToCrouchTime))
self2.CrouchingRatio = self:GetCrouchingRatio()
local status = self2.GetStatus(self)
local oldsprinting, oldwalking = self:GetSprinting(), self:GetWalking()
local vellen = velocity:Length2D()
--if TFA.Enum.ReloadStatus[status] then
-- self:SetSprinting(false)
--elseif sprint_cv:GetBool() and not self:GetStatL("AllowSprintAttack", false) and movedata then
if sprint_cv:GetBool() and not self:GetStatL("AllowSprintAttack", false) and movedata then
self:SetSprinting(vellen > ply:GetRunSpeed() * 0.6 * speedmult and movedata:KeyDown(IN_SPEED) and ply:OnGround())
else
self:SetSprinting(false)
end
self:SetWalking(vellen > ((isply and ply:GetWalkSpeed() or TFA.GUESS_NPC_WALKSPEED) * (sv_tfa_weapon_weight:GetBool() and self:GetStatL("RegularMoveSpeedMultiplier", 1) or 1) * .75) and ply:GetNW2Bool("TFA_IsWalking") and ply:OnGround() and not self:GetSprinting() and not self:GetCustomizing())
self2.walking_updated = oldwalking ~= self:GetWalking()
self2.sprinting_updated = oldsprinting ~= self:GetSprinting()
if self:GetCustomizing() and (self2.GetIronSights(self) or self:GetSprinting() or not TFA.Enum.ReadyStatus[status]) then
self:ToggleCustomize()
end
local spr = self:GetSprinting()
local walk = self:GetWalking()
local sprt = spr and 1 or 0
local walkt = walk and 1 or 0
local adstransitionspeed = (spr or walk) and 7.5 or 12.5
self:SetSprintProgress(l_mathApproach(self:GetSprintProgress(), sprt, (sprt - self:GetSprintProgress()) * ft * adstransitionspeed))
self:SetWalkProgress(l_mathApproach(self:GetWalkProgress(), walkt, (walkt - self:GetWalkProgress()) * ft * adstransitionspeed))
self:SetLastVelocity(vellen)
end
local sp = game.SinglePlayer()
local sv_tfa_recoil_legacy = GetConVar("sv_tfa_recoil_legacy")
function SWEP:CalculateRatios()
local owent = self:GetOwner()
--if not IsValid(owent) or not owent:IsPlayer() then return end
if not IsValid(owent) then return end
local self2 = self:GetTable()
if self2.ratios_calc == nil then
self2.ratios_calc = true
end
local ft = FrameTime()
local time = CurTime()
if ft <= 0 then return end
local is = self2.GetIronSights(self)
local spr = self2.GetSprinting(self)
local walk = self2.GetWalking(self)
local ist = is and 1 or 0
local sprt = spr and 1 or 0
local adstransitionspeed
if is then
adstransitionspeed = 12.5 / (self:GetStatL("IronSightTime") / 0.3)
elseif spr or walk then
adstransitionspeed = 7.5
else
adstransitionspeed = 12.5
end
if not owent:IsPlayer() then
self:TFAFinishMove(owent, owent:GetVelocity())
end
local lastrecoiltime = self2.GetLastRecoil(self, -1)
if lastrecoiltime < 0 or time >= (lastrecoiltime + self2.GetStatL(self, "Primary.SpreadRecoveryDelay")) then
self:SetSpreadRatio(l_mathClamp(self:GetSpreadRatio() - self2.GetStatL(self, "Primary.SpreadRecovery") * ft, 1, self2.GetStatL(self, "Primary.SpreadMultiplierMax")))
end
self:SetIronSightsProgress(l_mathApproach(self:GetIronSightsProgress(), ist, (ist - self:GetIronSightsProgress()) * ft * adstransitionspeed))
self:SetProceduralHolsterProgress(l_mathApproach(self:GetProceduralHolsterProgress(), sprt, (sprt - self:GetSprintProgress()) * ft * self2.ProceduralHolsterTime * 15))
self:SetInspectingProgress(l_mathApproach(self:GetInspectingProgress(), self:GetCustomizing() and 1 or 0, ((self:GetCustomizing() and 1 or 0) - self:GetInspectingProgress()) * ft * 10))
if self:GetRecoilThink() then
if self:GetRecoilLoop() then
-- loop or after loop
if self:GetRecoilLoopWait() < time then
self:SetRecoilOutProgress(l_mathMin(1, self:GetRecoilOutProgress() + ft / self2.Primary_TFA.RecoilLUT["out"].cooldown_speed))
if self:GetRecoilOutProgress() == 1 then
self:SetRecoilThink(false)
self:SetRecoilLoop(false)
self:SetRecoilLoopProgress(0)
self:SetRecoilInProgress(0)
self:SetRecoilOutProgress(0)
end
end
else
-- IN only
if self:GetRecoilInWait() < time then
self:SetRecoilInProgress(l_mathMax(0, self:GetRecoilInProgress() - ft / self2.Primary_TFA.RecoilLUT["in"].cooldown_speed))
if self:GetRecoilInProgress() == 0 then
self:SetRecoilThink(false)
end
end
end
end
if not sv_tfa_recoil_legacy:GetBool() then
ft = l_mathClamp(ft, 0, 1)
self:SetViewPunchBuild(l_mathMax(0, self:GetViewPunchBuild() - self:GetViewPunchBuild() * ft))
local build = l_mathMax(0, 4.5 - self:GetViewPunchBuild())
ft = ft * build * build
self:SetViewPunchP(self:GetViewPunchP() - self:GetViewPunchP() * ft)
self:SetViewPunchY(self:GetViewPunchY() - self:GetViewPunchY() * ft)
end
self2.SpreadRatio = self:GetSpreadRatio()
self2.IronSightsProgress = self:GetIronSightsProgress()
self2.SprintProgress = self:GetSprintProgress()
self2.WalkProgress = self:GetWalkProgress()
self2.ProceduralHolsterProgress = self:GetProceduralHolsterProgress()
self2.InspectingProgress = self:GetInspectingProgress()
if sp and CLIENT then
self2.Inspecting = self:GetCustomizing() --compatibility
end
self2.CLIronSightsProgress = self:GetIronSightsProgress() --compatibility
end
SWEP.Primary.IronRecoilMultiplier = 0.5 --Multiply recoil by this factor when we're in ironsights. This is proportional, not inversely.
SWEP.CrouchRecoilMultiplier = 0.65 --Multiply recoil by this factor when we're crouching. This is proportional, not inversely.
SWEP.JumpRecoilMultiplier = 1.3 --Multiply recoil by this factor when we're crouching. This is proportional, not inversely.
SWEP.WallRecoilMultiplier = 1.1 --Multiply recoil by this factor when we're changing state e.g. not completely ironsighted. This is proportional, not inversely.
SWEP.ChangeStateRecoilMultiplier = 1.3 --Multiply recoil by this factor when we're crouching. This is proportional, not inversely.
SWEP.CrouchAccuracyMultiplier = 0.5 --Less is more. Accuracy * 0.5 = Twice as accurate, Accuracy * 0.1 = Ten times as accurate
SWEP.ChangeStateAccuracyMultiplier = 1.5 --Less is more. A change of state is when we're in the progress of doing something, like crouching or ironsighting. Accuracy * 2 = Half as accurate. Accuracy * 5 = 1/5 as accurate
SWEP.JumpAccuracyMultiplier = 2 --Less is more. Accuracy * 2 = Half as accurate. Accuracy * 5 = 1/5 as accurate
SWEP.WalkAccuracyMultiplier = 1.35 --Less is more. Accuracy * 2 = Half as accurate. Accuracy * 5 = 1/5 as accurate
SWEP.ToCrouchTime = 0.25
local mult_cvar = GetConVar("sv_tfa_spread_multiplier")
local dynacc_cvar = GetConVar("sv_tfa_dynamicaccuracy")
local ccon, crec
SWEP.JumpRatio = 0
function SWEP:CalculateConeRecoil()
local dynacc = false
local self2 = self:GetTable()
local isr = self:GetIronSightsProgress()
if dynacc_cvar:GetBool() and (self2.GetStatL(self, "Primary.NumShots") <= 1) then
dynacc = true
end
local isr_1 = l_mathClamp(isr * 2, 0, 1)
local isr_2 = l_mathClamp((isr - 0.5) * 2, 0, 1)
local acv = self2.GetStatL(self, "Primary.Spread") or self2.GetStatL(self, "Primary.Accuracy")
local recv = self2.GetStatL(self, "Primary.Recoil") * 5
if dynacc then
ccon = l_Lerp(isr_2, l_Lerp(isr_1, acv, acv * self2.GetStatL(self, "ChangeStateAccuracyMultiplier")), self2.GetStatL(self, "Primary.IronAccuracy"))
crec = l_Lerp(isr_2, l_Lerp(isr_1, recv, recv * self2.GetStatL(self, "ChangeStateRecoilMultiplier")), recv * self2.GetStatL(self, "Primary.IronRecoilMultiplier"))
else
ccon = l_Lerp(isr, acv, self2.GetStatL(self, "Primary.IronAccuracy"))
crec = l_Lerp(isr, recv, recv * self2.GetStatL(self, "Primary.IronRecoilMultiplier"))
end
local crc_1 = l_mathClamp(self:GetCrouchingRatio() * 2, 0, 1)
local crc_2 = l_mathClamp((self:GetCrouchingRatio() - 0.5) * 2, 0, 1)
if dynacc then
ccon = l_Lerp(crc_2, l_Lerp(crc_1, ccon, ccon * self2.GetStatL(self, "ChangeStateAccuracyMultiplier")), ccon * self2.GetStatL(self, "CrouchAccuracyMultiplier"))
crec = l_Lerp(crc_2, l_Lerp(crc_1, crec, self2.GetStatL(self, "Primary.Recoil") * self2.GetStatL(self, "ChangeStateRecoilMultiplier")), crec * self2.GetStatL(self, "CrouchRecoilMultiplier"))
end
local owner = self:GetOwner()
local isply = owner:IsPlayer()
local ovel
if IsValid(owner) then
if owner:IsPlayer() then
ovel = self:GetLastVelocity()
else
ovel = owner:GetVelocity():Length2D()
end
else
ovel = 0
end
local vfc_1 = l_mathClamp(ovel / (isply and owner:GetWalkSpeed() or TFA.GUESS_NPC_WALKSPEED), 0, 2)
if dynacc then
ccon = l_Lerp(vfc_1, ccon, ccon * self2.GetStatL(self, "WalkAccuracyMultiplier"))
crec = l_Lerp(vfc_1, crec, crec * self2.GetStatL(self, "WallRecoilMultiplier"))
end
local jr = self:GetJumpRatio()
if dynacc then
ccon = l_Lerp(jr, ccon, ccon * self2.GetStatL(self, "JumpAccuracyMultiplier"))
crec = l_Lerp(jr, crec, crec * self2.GetStatL(self, "JumpRecoilMultiplier"))
end
ccon = ccon * self:GetSpreadRatio()
if mult_cvar then
ccon = ccon * mult_cvar:GetFloat()
end
if not isply and IsValid(owner) then
local prof = owner:GetCurrentWeaponProficiency()
if prof == WEAPON_PROFICIENCY_POOR then
ccon = ccon * 8
elseif prof == WEAPON_PROFICIENCY_AVERAGE then
ccon = ccon * 5
elseif prof == WEAPON_PROFICIENCY_GOOD then
ccon = ccon * 3
elseif prof == WEAPON_PROFICIENCY_VERY_GOOD then
ccon = ccon * 2
elseif prof == WEAPON_PROFICIENCY_PERFECT then
ccon = ccon * 1.5
end
end
return ccon, crec
end

View File

@@ -0,0 +1,383 @@
--[[
| 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 fx, sp = nil, game.SinglePlayer()
local shelltype
function SWEP:PCFTracer(bul, hitpos, ovrride)
if bul.PCFTracer then
self:UpdateMuzzleAttachment()
local mzp = self:GetMuzzlePos()
if bul.PenetrationCount > 0 and not ovrride then return end --Taken care of with the pen effect
if (CLIENT or game.SinglePlayer()) and self.Scoped and self:IsCurrentlyScoped() and self:IsFirstPerson() then
TFA.ParticleTracer(bul.PCFTracer, self:GetOwner():GetShootPos() - self:GetOwner():EyeAngles():Up() * 5, hitpos, false, 0, -1)
else
local vent = self
if (CLIENT or game.SinglePlayer()) and self:IsFirstPerson() then
vent = self.OwnerViewModel
end
if sp and not self:IsFirstPerson() then
TFA.ParticleTracer(bul.PCFTracer, self:GetOwner():GetShootPos() + self:GetOwner():GetAimVector() * 32, hitpos, false)
else
TFA.ParticleTracer(bul.PCFTracer, mzp.Pos, hitpos, false, vent, self.MuzzleAttachmentRaw or 1)
end
end
end
end
function SWEP:EventShell()
if SERVER and self.processing_events and sp then return end
if SERVER then
net.Start("tfaBaseShellSV", true)
net.WriteEntity(self)
if self:GetOwner():IsPlayer() then
if sp then
net.Broadcast()
else
net.SendOmit(self:GetOwner())
end
else
net.SendPVS(self:GetPos())
end
return
end
self:MakeShellBridge()
end
function SWEP:MakeShellBridge(ifp)
if ifp == false then return end
if self.LuaShellEjectDelay > 0 then
self.LuaShellRequestTime = CurTime() + self.LuaShellEjectDelay / self:GetAnimationRate(ACT_VM_PRIMARYATTACK)
else
self:MakeShell()
end
end
SWEP.ShellEffectOverride = nil -- ???
SWEP.ShellEjectionQueue = 0
function SWEP:GetShellAttachmentID(ent, isVM)
local raw = self:GetStatL("ShellAttachmentRaw")
local israw = false
local attid
if raw and ent:GetAttachment(raw) then
attid = raw
israw = true
else
attid = ent:LookupAttachment(self:GetStatL("ShellAttachment"))
end
if self:GetStatL("IsAkimbo") and not israw then
return 3 + self:GetAnimCycle()
end
if attid and attid <= 0 then attid = 2 end
attid = math.Clamp(attid and attid or 2, 1, 127)
return attid
end
function SWEP:GetShellEjectPosition(ent, isVM)
local attid = self:GetShellAttachmentID(ent, isVM)
local angpos = ent:GetAttachment(attid)
if angpos then
return angpos.Pos, angpos.Ang, attid
end
end
function SWEP:MakeShell(eject_now)
if not self:IsValid() then return end -- what
if self.current_event_iftp == false then return end
local retVal = hook.Run("TFA_MakeShell", self)
if retVal ~= nil then
return retVal
end
if self:GetStatL("ShellEffectOverride") then
shelltype = self:GetStatL("ShellEffectOverride")
elseif TFA.GetLegacyShellsEnabled() then
shelltype = "tfa_shell_legacy"
else
shelltype = "tfa_shell"
end
local ent = self
local isVM = false
if self:IsFirstPerson() then
if not eject_now and CLIENT then
self.ShellEjectionQueue = self.ShellEjectionQueue + 1
return
end
ent = self.OwnerViewModel or self
isVM = ent == self.OwnerViewModel
end
self:EjectionSmoke(true)
if not isstring(shelltype) or shelltype == "" then return end -- allows to disable shells by setting override to "" - will shut up all rp fags
if not IsValid(ent) then return end
local pos, ang, attid = self:GetShellEjectPosition(ent, isVM)
if not pos then return end
fx = EffectData()
fx:SetEntity(self)
fx:SetAttachment(attid)
fx:SetMagnitude(1)
fx:SetScale(1)
fx:SetOrigin(pos)
fx:SetNormal(ang:Forward())
TFA.Effects.Create(shelltype, fx)
end
--[[
Function Name: CleanParticles
Syntax: self:CleanParticles().
Returns: Nothing.
Notes: Cleans up particles.
Purpose: FX
]]
--
function SWEP:CleanParticles()
if not IsValid(self) then return end
if self.StopParticles then
self:StopParticles()
end
if self.StopParticleEmission then
self:StopParticleEmission()
end
if not self:VMIV() then return end
local vm = self.OwnerViewModel
if IsValid(vm) then
if vm.StopParticles then
vm:StopParticles()
end
if vm.StopParticleEmission then
vm:StopParticleEmission()
end
end
end
--[[
Function Name: EjectionSmoke
Syntax: self:EjectionSmoke().
Returns: Nothing.
Notes: Puff of smoke on shell attachment.
Purpose: FX
]]
--
function SWEP:EjectionSmoke(ovrr)
local retVal = hook.Run("TFA_EjectionSmoke",self)
if retVal ~= nil then
return retVal
end
if TFA.GetEJSmokeEnabled() and (self:GetStatL("EjectionSmokeEnabled") or ovrr) then
local vm = self:IsFirstPerson() and self.OwnerViewModel or self
if IsValid(vm) then
local att = vm:LookupAttachment(self:GetStatL("ShellAttachment"))
if not att or att <= 0 then
att = 2
end
local oldatt = att
att = self:GetStatL("ShellAttachmentRaw", att)
local angpos = vm:GetAttachment(att)
if not angpos then
att = oldatt
angpos = vm:GetAttachment(att)
end
if angpos then
fx = EffectData()
fx:SetEntity(self)
fx:SetOrigin(angpos.Pos)
fx:SetAttachment(att)
fx:SetNormal(angpos.Ang:Forward())
TFA.Effects.Create("tfa_shelleject_smoke", fx)
end
end
end
end
--[[
Function Name: ShootEffectsCustom
Syntax: self:ShootEffectsCustom().
Returns: Nothing.
Notes: Calls the proper muzzleflash, muzzle smoke, muzzle light code.
Purpose: FX
]]
--
function SWEP:MuzzleSmoke(spv)
local retVal = hook.Run("TFA_MuzzleSmoke",self)
if retVal ~= nil then
return retVal
end
if self.SmokeParticle == nil then
self.SmokeParticle = self.SmokeParticles[self.DefaultHoldType or self.HoldType]
end
if self:GetStatL("SmokeParticle") and self:GetStatL("SmokeParticle") ~= "" then
self:UpdateMuzzleAttachment()
local att = self:GetMuzzleAttachment()
fx = EffectData()
fx:SetOrigin(self:GetOwner():GetShootPos())
fx:SetNormal(self:GetOwner():EyeAngles():Forward())
fx:SetEntity(self)
fx:SetAttachment(att)
TFA.Effects.Create("tfa_muzzlesmoke", fx)
end
end
function SWEP:MuzzleFlashCustom(spv)
local retVal = hook.Run("TFA_MuzzleFlash",self)
if retVal ~= nil then
return retVal
end
local att = self:GetMuzzleAttachment()
fx = EffectData()
fx:SetOrigin(self:GetOwner():GetShootPos())
fx:SetNormal(self:GetOwner():EyeAngles():Forward())
fx:SetEntity(self)
fx:SetAttachment(att)
local mzsil = self:GetStatL("MuzzleFlashEffectSilenced")
if (self:GetSilenced() and mzsil and mzsil ~= "") then
TFA.Effects.Create(mzsil, fx)
else
TFA.Effects.Create(self:GetStatL("MuzzleFlashEffect", self.MuzzleFlashEffect or ""), fx)
end
end
function SWEP:ShootEffectsCustom(ifp)
if self.DoMuzzleFlash ~= nil then
self.MuzzleFlashEnabled = self.DoMuzzleFlash
self.DoMuzzleFlash = nil
end
if not self.MuzzleFlashEnabled then return end
if self:IsFirstPerson() and not self:VMIV() then return end
if not self:GetOwner().GetShootPos then return end
ifp = ifp or IsFirstTimePredicted()
if (SERVER and sp and self.ParticleMuzzleFlash) or (SERVER and not sp) then
net.Start("tfa_base_muzzle_mp", true)
net.WriteEntity(self)
if sp or not self:GetOwner():IsPlayer() then
net.SendPVS(self:GetPos())
else
net.SendOmit(self:GetOwner())
end
return
end
if (CLIENT and ifp and not sp) or (sp and SERVER) then
self:UpdateMuzzleAttachment()
self:MuzzleFlashCustom(sp)
self:MuzzleSmoke(sp)
end
end
--[[
Function Name: CanDustEffect
Syntax: self:CanDustEffect( concise material name ).
Returns: True/False
Notes: Used for the impact effect. Should be used with GetMaterialConcise.
Purpose: Utility
]]
--
local DustEffects = {
[MAT_DIRT] = true,
[MAT_CONCRETE] = true,
[MAT_PLASTIC] = true,
[MAT_WOOD] = true
}
function SWEP:CanDustEffect(matv)
if DustEffects[matv] then return true end
return false
end
--[[
Function Name: CanSparkEffect
Syntax: self:CanSparkEffect( concise material name ).
Returns: True/False
Notes: Used for the impact effect. Should be used with GetMaterialConcise.
Purpose: Utility
]]
--
local SparkEffects = {
[MAT_METAL] = true,
[MAT_GRATE] = true,
[MAT_VENT] = true
}
function SWEP:CanSparkEffect(matv)
if SparkEffects[matv] then return true end
return false
end
-- Returns muzzle attachment position for HL2 tracers
function SWEP:GetTracerOrigin(...)
local att = self:GetMuzzleAttachment()
local attpos = (self:IsFirstPerson() and self.OwnerViewModel or self):GetAttachment(att)
if attpos and attpos.Pos then
return attpos.Pos
end
end

View File

@@ -0,0 +1,625 @@
--[[
| 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 lshift = bit.lshift
local band = bit.band
local bor = bit.bor
local sp = game.SinglePlayer()
local l_CT = CurTime
local is, spr, wlk, cst
--[[
Function Name: ResetEvents
Syntax: self:ResetEvents()
Returns: Nothing.
Purpose: Cleans up events table.
]]--
function SWEP:ResetEvents()
self:SetEventStatus1(0x00000000)
self:SetEventStatus2(0x00000000)
self:SetEventStatus3(0x00000000)
self:SetEventStatus4(0x00000000)
self:SetEventStatus5(0x00000000)
self:SetEventStatus6(0x00000000)
self:SetEventStatus7(0x00000000)
self:SetEventStatus8(0x00000000)
self:SetEventTimer(l_CT())
-- self:SetFirstDeployEvent(false)
if self.EventTable then
for _, eventtable in pairs(self.EventTable) do
for i = 1, #eventtable do
eventtable[i].called = false
end
end
end
if self.event_table_overflow then
local editcts = self.EventTableEdict
if editcts[0] then
editcts[0].called = false
for i = 1, #editcts do
editcts[i].called = false
end
end
end
if sp then
self:CallOnClient("ResetEvents", "")
end
end
function SWEP:GetEventPlayed(event_slot)
if self.event_table_overflow then
return assert(self.EventTableEdict[event_slot], string.format("Unknown event %d", event_slot)).called
end
local inner_index = event_slot % 32
local outer_index = (event_slot - inner_index) / 32 + 1
local lindex = lshift(1, inner_index)
return band(self.get_event_status_lut[outer_index](self), lindex) ~= 0, inner_index, outer_index, lindex
end
function SWEP:SetEventPlayed(event_slot)
if self.event_table_overflow then
assert(self.EventTableEdict[event_slot], string.format("Unknown event %d", event_slot)).called = true
return
end
local inner_index = event_slot % 32
local outer_index = (event_slot - inner_index) / 32 + 1
local lindex = lshift(1, inner_index)
self.set_event_status_lut[outer_index](self, bor(self.get_event_status_lut[outer_index](self), lindex))
return inner_index, outer_index, lindex
end
--[[
Function Name: ProcessEvents
Syntax: self:ProcessEvents().
Returns: Nothing.
Notes: Critical for the event table to function.
Purpose: Main SWEP function
]]--
SWEP._EventSlotCount = 0
SWEP.EventTableEdict = {}
function SWEP:DispatchLuaEvent(arg)
if not self.event_table_built then
self:RebuildEventEdictTable()
end
local fn = assert(assert(self.EventTableEdict[tonumber(arg)], "No such event with edict " .. arg).value, "Event is missing a function to call")
assert(isfunction(fn), "Event " .. arg .. " is not a Lua event")
fn(self, self:VMIV(), true)
end
function SWEP:DispatchBodygroupEvent(arg)
if not self.event_table_built then
self:RebuildEventEdictTable()
end
local event = assert(self.EventTableEdict[tonumber(arg)], "No such event with edict " .. arg)
assert(isstring(event.name), "Event " .. arg .. " is missing bodygroup name to set")
assert(isstring(event.value), "Event " .. arg .. " is missing bodygroup value to set")
if event.view then
self.ViewModelBodygroups[event.name] = event.value
end
if event.world then
self.WorldModelBodygroups[event.name] = event.value
end
end
local isstring = isstring
local function eventtablesorter(a, b)
local sa, sb = isstring(a), isstring(b)
if sa and not sb or not sa and sb then
if sa then
return false
end
return true
end
return a < b
end
function SWEP:RebuildEventEdictTable()
local self2 = self:GetTable()
local slot = 0
for i = #self2.EventTableEdict, 0, -1 do
self2.EventTableEdict[i] = nil
end
self:ResetEvents()
local eventtable = self2.EventTable
local keys = table.GetKeys(eventtable)
table.sort(keys, eventtablesorter)
for _, key in ipairs(keys) do
local value = eventtable[key]
if istable(value) then
for _, event in SortedPairs(value) do
if istable(event) then
event.slot = slot
slot = slot + 1
if not event.autodetect then
if event.type == "lua" then
if event.server == nil then
event.server = true
end
elseif event.type == "snd" or event.type == "sound" then
if event.server == nil then
event.server = false
end
elseif event.type == "bg" or event.type == "bodygroup" then
if event.server == nil then event.server = true end
if event.view == nil then event.view = true end
if event.world == nil then event.world = true end
end
if event.client == nil then
event.client = true
end
event.autodetect = true
end
event.called = false
if slot > 256 and not self.event_table_warning then
ErrorNoHalt("[TFA Base] Weapon " .. self:GetClass() .. " got too many events! 256 is maximum! Event table would NOT be properly predicted this time!\n")
self.event_table_warning = true
end
self2.EventTableEdict[event.slot] = event
end
end
end
end
self.event_table_overflow = slot > 256
self._built_event_debug_string_fn = nil
self._EventSlotCount = math.ceil(slot / 32)
self._EventSlotNum = slot - 1
self.event_table_built = true
end
function SWEP:ProcessEvents(firstprediction)
local viewmodel = self:VMIVNPC()
if not viewmodel then return end
if not self.event_table_built then
self:RebuildEventEdictTable()
end
if sp and CLIENT then return end
if sp and SERVER then return self:ProcessEventsSP() end
local ply = self:GetOwner()
local isplayer = ply:IsPlayer()
local evtbl = self.EventTable[self:GetLastActivity() or -1] or self.EventTable[viewmodel:GetSequenceName(viewmodel:GetSequence())]
if not evtbl then return end
local curtime = l_CT()
local eventtimer = self:GetEventTimer()
local is_local = CLIENT and ply == LocalPlayer()
local animrate = self:GetAnimationRate(self:GetLastActivity() or -1)
self.current_event_iftp = firstprediction
self.processing_events = true
for i = 1, #evtbl do
local event = evtbl[i]
if self:GetEventPlayed(event.slot) or curtime < eventtimer + event.time / animrate then goto CONTINUE end
self:SetEventPlayed(event.slot)
event.called = true
if not event.autodetect then
if event.type == "lua" then
if event.server == nil then
event.server = true
end
elseif event.type == "snd" or event.type == "sound" then
if event.server == nil then
event.server = false
end
elseif event.type == "bg" or event.type == "bodygroup" then
if event.server == nil then event.server = true end
if event.view == nil then event.view = true end
if event.world == nil then event.world = true end
end
if event.client == nil then
event.client = true
end
event.autodetect = true
end
if event.type == "lua" then
if ((event.client and CLIENT and (not event.client_predictedonly or is_local)) or (event.server and SERVER)) and event.value then
event.value(self, viewmodel, firstprediction)
end
elseif event.type == "snd" or event.type == "sound" then
if SERVER then
if event.client then
if not isplayer and player.GetCount() ~= 0 then
net.Start("tfaSoundEvent", true)
net.WriteEntity(self)
net.WriteString(event.value or "")
net.SendPVS(self:GetPos())
elseif isplayer then
net.Start("tfaSoundEvent", true)
net.WriteEntity(self)
net.WriteString(event.value or "")
net.SendOmit(ply)
end
elseif event.server and event.value and event.value ~= "" then
self:EmitSound(event.value)
end
elseif event.client and is_local and not sp and event.value and event.value ~= "" then
if firstprediction or firstprediction == nil then
if event.time <= 0.01 then
self:EmitSoundSafe(event.value)
else
self:EmitSound(event.value)
end
end
end
elseif event.type == "bg" or event.type == "bodygroup" then
if ((event.client and CLIENT and (not event.client_predictedonly or is_local)) or
(event.server and SERVER)) and (event.name and event.value and event.value ~= "") then
if event.view then
self.ViewModelBodygroups[event.name] = event.value
end
if event.world then
self.WorldModelBodygroups[event.name] = event.value
end
end
end
::CONTINUE::
end
self.processing_events = false
self.current_event_iftp = nil
end
-- This function is exclusively targeting singleplayer
function SWEP:ProcessEventsSP(firstprediction)
local viewmodel = self:VMIVNPC()
if not viewmodel then return end
local evtbl = self.EventTable[self:GetLastActivity() or -1] or self.EventTable[viewmodel:GetSequenceName(viewmodel:GetSequence())]
if not evtbl then return end
local curtime = l_CT()
local eventtimer = self:GetEventTimer()
local is_local = self:GetOwner() == Entity(1)
local animrate = self:GetAnimationRate(self:GetLastActivity() or -1)
self.processing_events = true
for i = 1, #evtbl do
local event = evtbl[i]
if self:GetEventPlayed(event.slot) or curtime < eventtimer + event.time / animrate then goto CONTINUE end
self:SetEventPlayed(event.slot)
event.called = true
if not event.autodetect then
if event.type == "lua" then
if event.server == nil then
event.server = true
end
elseif event.type == "snd" or event.type == "sound" then
if event.server == nil then
event.server = false
end
elseif event.type == "bg" or event.type == "bodygroup" then
if event.server == nil then event.server = true end
if event.view == nil then event.view = true end
if event.world == nil then event.world = true end
end
if event.client == nil then
event.client = true
end
event.autodetect = true
end
if event.type == "lua" then
if event.value then
if event.server then
event.value(self, viewmodel, true)
end
if event.client and (not event.client_predictedonly or is_local) then
self:CallOnClient("DispatchLuaEvent", tostring(event.slot))
end
end
elseif event.type == "snd" or event.type == "sound" then
if event.client then
net.Start("tfaSoundEvent", true)
net.WriteEntity(self)
net.WriteString(event.value or "")
net.Broadcast()
elseif event.server and event.value and event.value ~= "" then
self:EmitSound(event.value)
end
elseif event.type == "bg" or event.type == "bodygroup" then
if event.name and event.value and event.value ~= "" then
if event.server then
if event.view then
self.ViewModelBodygroups[event.name] = event.value
end
if event.world then
self.WorldModelBodygroups[event.name] = event.value
end
end
if event.client and (not event.client_predictedonly or is_local) then
self:CallOnClient("DispatchBodygroupEvent", tostring(event.slot))
end
end
end
::CONTINUE::
end
self.processing_events = false
end
function SWEP:EmitSoundSafe(snd)
timer.Simple(0, function()
if IsValid(self) and snd then self:EmitSound(snd) end
end)
end
local ct, stat, statend, finalstat, waittime, lact
function SWEP:ProcessStatus()
local self2 = self:GetTable()
is = self2.GetIronSightsRaw(self)
spr = self2.GetSprinting(self)
wlk = self2.GetWalking(self)
cst = self2.GetCustomizing(self)
local ply = self:GetOwner()
local isplayer = ply:IsPlayer()
if stat == TFA.Enum.STATUS_FIDGET and is then
self:SetStatusEnd(0)
self2.Idle_Mode_Old = self2.Idle_Mode
self2.Idle_Mode = TFA.Enum.IDLE_BOTH
self2.ChooseIdleAnim(self)
if sp then
self:CallOnClient("ChooseIdleAnim", "")
end
self2.Idle_Mode = self2.Idle_Mode_Old
self2.Idle_Mode_Old = nil
statend = -1
end
is = self:GetIronSights()
stat = self:GetStatus()
statend = self:GetStatusEnd()
ct = l_CT()
if stat ~= TFA.Enum.STATUS_IDLE and ct > statend then
self:SetFirstDeployEvent(false)
finalstat = TFA.Enum.STATUS_IDLE
--Holstering
if stat == TFA.Enum.STATUS_HOLSTER then
finalstat = TFA.Enum.STATUS_HOLSTER_READY
self:SetStatusEnd(ct)
elseif stat == TFA.Enum.STATUS_HOLSTER_READY then
self2.FinishHolster(self)
finalstat = TFA.Enum.STATUS_HOLSTER_FINAL
self:SetStatusEnd(ct + 0.6)
elseif stat == TFA.Enum.STATUS_RELOADING_LOOP_START_EMPTY then
--Shotgun Reloading from empty
if not self2.IsJammed(self) then
self2.TakePrimaryAmmo(self, 1, true)
self2.TakePrimaryAmmo(self, -1)
end
if self2.Ammo1(self) <= 0 or self:Clip1() >= self2.GetPrimaryClipSize(self) or self:GetReloadLoopCancel() then
finalstat = TFA.Enum.STATUS_RELOADING_LOOP_END
local _, tanim = self2.ChooseShotgunPumpAnim(self)
self:SetStatusEnd(ct + self:GetActivityLength(tanim))
self:SetReloadLoopCancel(false)
if not self:GetReloadLoopCancel() then
self:SetJammed(false)
end
else
lact = self:GetLastActivity()
waittime = self2.GetActivityLength(self, lact, false) - self2.GetActivityLength(self, lact, true)
if waittime > 0.01 then
finalstat = TFA.Enum.STATUS_RELOADING_WAIT
self:SetStatusEnd(ct + waittime)
else
finalstat = self2.LoadShell(self)
end
self:SetJammed(false)
--finalstat = self:LoadShell()
--self:SetStatusEnd( self:GetNextPrimaryFire() )
end
elseif stat == TFA.Enum.STATUS_RELOADING_LOOP_START then
--Shotgun Reloading
finalstat = self2.LoadShell(self)
elseif stat == TFA.Enum.STATUS_RELOADING_LOOP then
self2.TakePrimaryAmmo(self, 1, true)
self2.TakePrimaryAmmo(self, -1)
lact = self:GetLastActivity()
if self2.GetActivityLength(self, lact, true) < self2.GetActivityLength(self, lact, false) - 0.01 then
local sht = self2.GetStatL(self, "LoopedReloadInsertTime")
if sht then
sht = sht / self2.GetAnimationRate(self, ACT_VM_RELOAD)
end
waittime = (sht or self2.GetActivityLength(self, lact, false)) - self2.GetActivityLength(self, lact, true)
else
waittime = 0
end
if waittime > 0.01 then
finalstat = TFA.Enum.STATUS_RELOADING_WAIT
self:SetStatusEnd(ct + waittime)
else
if self2.Ammo1(self) <= 0 or self:Clip1() >= self:GetPrimaryClipSize() or self:GetReloadLoopCancel() then
finalstat = TFA.Enum.STATUS_RELOADING_LOOP_END
local _, tanim = self2.ChooseShotgunPumpAnim(self)
self:SetStatusEnd(ct + self:GetActivityLength(tanim))
self:SetReloadLoopCancel(false)
else
finalstat = self2.LoadShell(self)
end
end
elseif stat == TFA.Enum.STATUS_RELOADING then
self2.CompleteReload(self)
lact = self:GetLastActivity()
waittime = self2.GetActivityLength(self, lact, false) - self2.GetActivityLength(self, lact, true)
if waittime > 0.01 then
finalstat = TFA.Enum.STATUS_RELOADING_WAIT
self:SetStatusEnd(ct + waittime)
end
elseif stat == TFA.Enum.STATUS_SILENCER_TOGGLE then
--self:SetStatusEnd( self:GetNextPrimaryFire() )
self:SetSilenced(not self:GetSilenced())
self2.Silenced = self:GetSilenced()
elseif stat == TFA.Enum.STATUS_RELOADING_WAIT and self:GetStatL("LoopedReload") then
if self2.Ammo1(self) <= 0 or self:Clip1() >= self:GetPrimaryClipSize() or self:GetReloadLoopCancel() then
finalstat = TFA.Enum.STATUS_RELOADING_LOOP_END
local _, tanim = self2.ChooseShotgunPumpAnim(self)
self:SetStatusEnd(ct + self:GetActivityLength(tanim))
--self:SetReloadLoopCancel( false )
else
finalstat = self2.LoadShell(self)
end
elseif stat == TFA.Enum.STATUS_RELOADING_LOOP_END and self:GetStatL("LoopedReload") then
self:SetReloadLoopCancel(false)
elseif self2.GetStatL(self, "PumpAction") and stat == TFA.Enum.STATUS_PUMP then
self:SetReloadLoopCancel(false)
elseif stat == TFA.Enum.STATUS_SHOOTING and self2.GetStatL(self, "PumpAction") then
if self:Clip1() == 0 and self2.GetStatL(self, "PumpAction").value_empty then
--finalstat = TFA.Enum.STATUS_PUMP_READY
self:SetReloadLoopCancel(true)
elseif (self2.GetStatL(self, "Primary.ClipSize") < 0 or self:Clip1() > 0) and self2.GetStatL(self, "PumpAction").value then
--finalstat = TFA.Enum.STATUS_PUMP_READY
self:SetReloadLoopCancel(true)
end
end
--self:SetStatusEnd( math.huge )
self:SetStatus(finalstat)
local smi = self2.Sights_Mode == TFA.Enum.LOCOMOTION_HYBRID or self2.Sights_Mode == TFA.Enum.LOCOMOTION_ANI
local spi = self2.Sprint_Mode == TFA.Enum.LOCOMOTION_HYBRID or self2.Sprint_Mode == TFA.Enum.LOCOMOTION_ANI
local wmi = self2.Walk_Mode == TFA.Enum.LOCOMOTION_HYBRID or self2.Walk_Mode == TFA.Enum.LOCOMOTION_ANI
local cmi = self2.Customize_Mode == TFA.Enum.LOCOMOTION_HYBRID or self2.Customize_Mode == TFA.Enum.LOCOMOTION_ANI
if
not TFA.Enum.ReadyStatus[stat] and
stat ~= TFA.Enum.STATUS_SHOOTING and
stat ~= TFA.Enum.STATUS_PUMP and
finalstat == TFA.Enum.STATUS_IDLE and
((smi or spi) or (cst and cmi))
then
is = self2.GetIronSights(self, true)
if (is and smi) or (spr and spi) or (wlk and wmi) or (cst and cmi) then
local success, _ = self2.Locomote(self, is and smi, is, spr and spi, spr, wlk and wmi, wlk, cst and cmi, cst)
if success == false then
self:SetNextIdleAnim(-1)
else
self:SetNextIdleAnim(math.max(self:GetNextIdleAnim(), ct + 0.1))
end
end
end
self2.LastBoltShoot = nil
if self:GetBurstCount() > 0 then
if finalstat ~= TFA.Enum.STATUS_SHOOTING and finalstat ~= TFA.Enum.STATUS_IDLE then
self:SetBurstCount(0)
elseif self:GetBurstCount() < self:GetMaxBurst() and self:Clip1() > 0 then
self:PrimaryAttack()
else
self:SetBurstCount(0)
self:SetNextPrimaryFire(self2.GetNextCorrectedPrimaryFire(self, self2.GetBurstDelay(self)))
end
end
end
--if stat == TFA.Enum.STATUS_IDLE and self:GetReloadLoopCancel() and (self2.GetStatL(self, "AllowSprintAttack") or self:GetSprintProgress() < 0.1) then
if stat == TFA.Enum.STATUS_IDLE and self:GetReloadLoopCancel() then
if self2.GetStatL(self, "PumpAction") then
if ct > self:GetNextPrimaryFire() and not self:KeyDown(IN_ATTACK) then
self2.DoPump(self)
end
else
self:SetReloadLoopCancel(false)
end
end
end

View File

@@ -0,0 +1,126 @@
--[[
| 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.
SWEP.OldPaP = false
SWEP.OldSpCola = false
SWEP.SpeedColaFactor = 2 --Amount to speed up by when u get dat speed cola
SWEP.SpeedColaActivities = {
[ACT_VM_DRAW] = true,
[ACT_VM_DRAW_EMPTY] = true,
[ACT_VM_DRAW_SILENCED] = true,
[ACT_VM_DRAW_DEPLOYED or 0] = true,
[ACT_VM_RELOAD] = true,
[ACT_VM_RELOAD_EMPTY] = true,
[ACT_VM_RELOAD_SILENCED] = true,
[ACT_VM_HOLSTER] = true,
[ACT_VM_HOLSTER_EMPTY] = true,
[ACT_VM_HOLSTER_SILENCED] = true,
[ACT_SHOTGUN_RELOAD_START] = true,
[ACT_SHOTGUN_RELOAD_FINISH] = true
}
SWEP.DTapActivities = {
[ACT_VM_PRIMARYATTACK] = true,
[ACT_VM_PRIMARYATTACK_EMPTY] = true,
[ACT_VM_PRIMARYATTACK_SILENCED] = true,
[ACT_VM_PRIMARYATTACK_1] = true,
[ACT_VM_SECONDARYATTACK] = true,
[ACT_VM_HITCENTER] = true,
[ACT_SHOTGUN_PUMP] = true
}
SWEP.DTapSpeed = 1 / 0.8
SWEP.DTap2Speed = 1 / 0.8
local nzombies
local count, upperclamp
function SWEP:NZMaxAmmo()
if nzombies == nil then
nzombies = engine.ActiveGamemode() == "nzombies"
end
local at = self:GetPrimaryAmmoType()
local at2 = self.GetSecondaryAmmoType and self:GetSecondaryAmmoType() or self.Secondary_TFA.Ammo
if IsValid(self:GetOwner()) then
if self:GetStatL("Primary.ClipSize") <= 0 then
count = math.Clamp(10, 300 / (self:GetStatL("Primary.Damage") / 30), 10, 300)
if self.Primary_TFA.NZMaxAmmo and self.Primary_TFA.NZMaxAmmo > 0 then
count = self.Primary_TFA.NZMaxAmmo
if self:GetPaP() then
count = count * 5 / 3
end
end
self:GetOwner():SetAmmo(count, at)
else
upperclamp = self:GetPaP() and 600 or 300
count = math.Clamp(math.abs(self:GetStatL("Primary.ClipSize")) * 10, 10, upperclamp)
count = count + self:GetStatL("Primary.ClipSize") - self:Clip1()
if self.Primary_TFA.NZMaxAmmo and self.Primary_TFA.NZMaxAmmo > 0 then
count = self.Primary_TFA.NZMaxAmmo
if self:GetPaP() then
count = count * 5 / 3
end
end
self:GetOwner():SetAmmo(count, at)
end
if self:GetStatL("Secondary.ClipSize") > 0 or self:GetSecondaryAmmoType() >= 0 then
if self:GetStatL("Secondary.ClipSize") <= 0 then
count = math.ceil( math.Clamp(10, 300 / math.pow( ( self:GetStatL("Secondary.Damage") or 100 ) / 30, 2 ), 10, 300) / 5 ) * 5
if self.Secondary_TFA.NZMaxAmmo and self.Secondary_TFA.NZMaxAmmo > 0 then
count = self.Secondary_TFA.NZMaxAmmo
if self:GetPaP() then
count = count * 5 / 3
end
end
self:GetOwner():SetAmmo(count, at2)
else
upperclamp = self:GetPaP() and 600 or 300
count = math.Clamp(math.abs(self:GetStatL("Secondary.ClipSize")) * 10, 10, upperclamp)
count = count + self:GetStatL("Secondary.ClipSize") - self:Clip2()
if self.Secondary_TFA.NZMaxAmmo and self.Secondary_TFA.NZMaxAmmo > 0 then
count = self.Secondary_TFA.NZMaxAmmo
if self:GetPaP() then
count = count * 5 / 3
end
end
self:GetOwner():SetAmmo(count, at2)
end
end
end
end
function SWEP:GetPaP()
return ( self.HasNZModifier and self:HasNZModifier("pap") ) or self.pap or false
end
function SWEP:IsPaP()
return self:GetPaP()
end

View File

@@ -0,0 +1,69 @@
--[[
| 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.
SWEP.MaterialTable = {}
SWEP.MaterialTable_V = {}
SWEP.MaterialTable_W = {}
function SWEP:InitializeMaterialTable()
if not self.HasSetMaterialMeta then
setmetatable(self.MaterialTable_V, {
["__index"] = function(t,k) return self:GetStatL("MaterialTable")[k] end
})
setmetatable(self.MaterialTable_W, {
["__index"] = function(t,k) return self:GetStatL("MaterialTable")[k] end
})
self.HasSetMaterialMeta = true
end
end
--if both nil then we can just clear it all
function SWEP:ClearMaterialCache(view, world)
if view == nil and world == nil then
self.MaterialCached_V = nil
self.MaterialCached_W = nil
self.MaterialCached = nil
self.SCKMaterialCached_V = nil
self.SCKMaterialCached_W = nil
else
if view then
self.MaterialCached_V = nil
self.SCKMaterialCached_V = nil
end
if world then
self.MaterialCached_W = nil
self.SCKMaterialCached_W = nil
end
end
end

View File

@@ -0,0 +1,413 @@
--[[
| 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 tableCopy = table.Copy
function SWEP:GetStatRecursive(srctbl, stbl, ...)
local val = srctbl[stbl[1]]
for i = 2, #stbl do
if (val) then
val = val[stbl[i]]
else
return true, ...
end
end
if val == nil then
return true, ...
end
if istable(val) and val.functionTable then
local currentStat, isFinal, nocache, nct
nocache = false
for i = 1, #val do
local v = val[i]
if isfunction(v) then
if currentStat == nil then
currentStat, isFinal, nct = v(self, ...)
else
currentStat, isFinal, nct = v(self, currentStat)
end
nocache = nocache or nct
if isFinal then break end
elseif v then
currentStat = v
end
end
if currentStat ~= nil then
return false, currentStat, nocache
end
return true, ...
end
return false, val
end
SWEP.StatCache_Blacklist = {
["ViewModelBoneMods"] = true,
["WorldModelBoneMods"] = true,
["MaterialTable"] = true,
["MaterialTable_V"] = true,
["MaterialTable_W"] = true,
["ViewModelBodygroups"] = true,
["Bodygroups_V"] = true,
["WorldModelBodygroups"] = true,
["Skin"] = true
}
SWEP.StatCache = {}
SWEP.StatCache2 = {}
SWEP.StatStringCache = {}
SWEP.LastClearStatCache = 0
SWEP.ClearStatCacheWarnCount = 0
SWEP.ClearStatCacheWarned = false
local IdealCSCDeltaTime = engine.TickInterval() * 2
local LatestDataVersion = TFA.LatestDataVersion
function SWEP:ClearStatCache(vn)
return self:ClearStatCacheVersioned(vn, 0)
end
function SWEP:ClearStatCacheL(vn)
return self:ClearStatCacheVersioned(vn, LatestDataVersion)
end
local trigger_lut_rebuild = {
FalloffMetricBased = true,
Range = true,
RangeFalloff = true,
}
function SWEP:ClearStatCacheVersioned(vn, path_version)
local self2 = self:GetTable()
self2.ignore_stat_cache = true
local getpath, getpath2
if isstring(vn) then
vn = TFA.RemapStatPath(vn, path_version, self.TFADataVersion)
end
if not vn and not self2.ClearStatCacheWarned then
local ct = CurTime()
local delta = ct - self2.LastClearStatCache
if delta < IdealCSCDeltaTime and debug.traceback():find("Think2") then
self2.ClearStatCacheWarnCount = self2.ClearStatCacheWarnCount + 1
if self2.ClearStatCacheWarnCount >= 5 then
self2.ClearStatCacheWarned = true
print(("[TFA Base] Weapon %s (%s) is abusing ClearStatCache function from Think2! This will lead to really bad performance issues, tell weapon's author to fix it ASAP!"):format(self2.PrintName, self:GetClass()))
end
elseif self2.ClearStatCacheWarnCount > 0 then
self2.ClearStatCacheWarnCount = 0
end
self2.LastClearStatCache = ct
end
if vn then
local list = TFA.GetStatPathChildren(vn, path_version, self.TFADataVersion)
for i = 1, #list do
self2.StatCache[list[i]] = nil
self2.StatCache2[list[i]] = nil
end
getpath2 = self2.GetStatPath(self, vn)
getpath = getpath2[1]
else
table.Empty(self2.StatCache)
table.Empty(self2.StatCache2)
end
if vn == "Primary" or not vn then
table.Empty(self2.Primary)
local temp = {}
setmetatable(self2.Primary, {
__index = function(self3, key)
return self2.GetStatVersioned(self, "Primary." .. key, self2.TFADataVersion)
end,
__newindex = function() end
})
for k in pairs(self2.Primary_TFA) do
if isstring(k) then
temp[k] = self2.GetStatVersioned(self, "Primary." .. k, self2.TFADataVersion)
end
end
setmetatable(self2.Primary, nil)
for k, v in pairs(temp) do
self2.Primary[k] = v
end
if self2.Primary_TFA.RangeFalloffLUT_IsConverted then
self2.Primary_TFA.RangeFalloffLUT = nil
self2.AutoDetectRange(self)
end
local getLUT = self2.GetStatL(self, "Primary.RangeFalloffLUT", nil, true)
if getLUT then
self2.Primary.RangeFalloffLUTBuilt = self:BuildFalloffTable(getLUT)
end
if self2.Primary_TFA.RecoilLUT then
if self2.Primary_TFA.RecoilLUT["in"] then
self2.Primary_TFA.RecoilLUT["in"].points_p = {0}
self2.Primary_TFA.RecoilLUT["in"].points_y = {0}
for _, point in ipairs(self2.Primary_TFA.RecoilLUT["in"].points) do
table.insert(self2.Primary_TFA.RecoilLUT["in"].points_p, point.p)
table.insert(self2.Primary_TFA.RecoilLUT["in"].points_y, point.y)
end
end
if self2.Primary_TFA.RecoilLUT["loop"] then
self2.Primary_TFA.RecoilLUT["loop"].points_p = {}
self2.Primary_TFA.RecoilLUT["loop"].points_y = {}
for _, point in ipairs(self2.Primary_TFA.RecoilLUT["loop"].points) do
table.insert(self2.Primary_TFA.RecoilLUT["loop"].points_p, point.p)
table.insert(self2.Primary_TFA.RecoilLUT["loop"].points_y, point.y)
end
table.insert(self2.Primary_TFA.RecoilLUT["loop"].points_p, self2.Primary_TFA.RecoilLUT["loop"].points[1].p)
table.insert(self2.Primary_TFA.RecoilLUT["loop"].points_y, self2.Primary_TFA.RecoilLUT["loop"].points[1].y)
end
if self2.Primary_TFA.RecoilLUT["out"] then
self2.Primary_TFA.RecoilLUT["out"].points_p = {0}
self2.Primary_TFA.RecoilLUT["out"].points_y = {0}
for _, point in ipairs(self2.Primary_TFA.RecoilLUT["out"].points) do
table.insert(self2.Primary_TFA.RecoilLUT["out"].points_p, point.p)
table.insert(self2.Primary_TFA.RecoilLUT["out"].points_y, point.y)
end
table.insert(self2.Primary_TFA.RecoilLUT["out"].points_p, 0)
table.insert(self2.Primary_TFA.RecoilLUT["out"].points_y, 0)
end
end
elseif getpath == "Primary_TFA" and isstring(getpath2[2]) then
if trigger_lut_rebuild[getpath2[2]] and self2.Primary_TFA.RangeFalloffLUT_IsConverted then
self2.Primary_TFA.RangeFalloffLUT = nil
self2.AutoDetectRange(self)
end
self2.Primary[getpath[2]] = self2.GetStatVersioned(self, vn, path_version)
end
if vn == "Secondary" or not vn then
table.Empty(self2.Secondary)
local temp = {}
setmetatable(self2.Secondary, {
__index = function(self3, key)
return self2.GetStatVersioned(self, "Secondary." .. key, self2.TFADataVersion)
end,
__newindex = function() end
})
for k in pairs(self.Secondary_TFA) do
if isstring(k) then
temp[k] = self2.GetStatVersioned(self, "Secondary." .. k, self2.TFADataVersion)
end
end
setmetatable(self2.Secondary, nil)
for k, v in pairs(temp) do
self2.Secondary[k] = v
end
elseif getpath == "Secondary_TFA" and isstring(getpath2[2]) then
self2.Secondary[getpath[2]] = self2.GetStatVersioned(self, vn, path_version)
end
if CLIENT then
self:RebuildModsRenderOrder()
end
self2.ignore_stat_cache = false
hook.Run("TFA_ClearStatCache", self)
end
local ccv = GetConVar("cl_tfa_debug_cache")
function SWEP:GetStatPath(stat, path_version)
return TFA.GetStatPath(stat, path_version or 0, self.TFADataVersion)
end
function SWEP:RemapStatPath(stat, path_version)
return TFA.RemapStatPath(stat, path_version or 0, self.TFADataVersion)
end
function SWEP:GetStatPathRaw(stat)
return TFA.GetStatPathRaw(stat)
end
function SWEP:GetStatRaw(stat, path_version)
local self2 = self:GetTable()
local path = TFA.GetStatPath(stat, path_version or 0, self2.TFADataVersion)
local value = self2[path[1]]
for i = 2, #path do
if not istable(value) then return end
value = value[path[i]]
end
return value
end
function SWEP:GetStatRawL(stat)
return self:GetStatRaw(stat, LatestDataVersion)
end
function SWEP:SetStatRaw(stat, path_version, _value)
local self2 = self:GetTable()
local path = TFA.GetStatPath(stat, path_version or 0, self2.TFADataVersion)
if #path == 1 then
self2[path[1]] = _value
return self
end
local value = self2[path[1]]
for i = 2, #path - 1 do
if not istable(value) then return self end
value = value[path[i]]
end
if istable(value) then
value[path[#path]] = _value
end
return self
end
function SWEP:SetStatRawL(stat, _value)
return self:SetStatRaw(stat, LatestDataVersion, _value)
end
function SWEP:GetStat(stat, default, dontMergeTables)
return self:GetStatVersioned(stat, 0, default, dontMergeTables)
end
function SWEP:GetStatL(stat, default, dontMergeTables)
return self:GetStatVersioned(stat, LatestDataVersion, default, dontMergeTables)
end
function SWEP:GetStatVersioned(stat, path_version, default, dontMergeTables)
local self2 = self:GetTable()
local statPath, currentVersionStat, translate = self2.GetStatPath(self, stat, path_version)
if self2.StatCache2[currentVersionStat] ~= nil then
local finalReturn
if self2.StatCache[currentVersionStat] ~= nil then
finalReturn = self2.StatCache[currentVersionStat]
else
local isDefault, retval = self2.GetStatRecursive(self, self2, statPath)
if retval ~= nil then
if not isDefault then
self2.StatCache[currentVersionStat] = retval
end
finalReturn = retval
else
finalReturn = istable(default) and tableCopy(default) or default
end
end
--local getstat = hook.Run("TFA_GetStat", self, currentVersionStat, finalReturn)
--if getstat ~= nil then return translate(getstat) end
return translate(finalReturn)
end
if not self2.OwnerIsValid(self) then
local finalReturn = default
if IsValid(self) then
local _
_, finalReturn = self2.GetStatRecursive(self, self2, statPath, istable(default) and tableCopy(default) or default)
end
--local getstat = hook.Run("TFA_GetStat", self, currentVersionStat, finalReturn)
--if getstat ~= nil then return translate(getstat) end
return translate(finalReturn)
end
local isDefault, statSelf = self2.GetStatRecursive(self, self2, statPath, istable(default) and tableCopy(default) or default)
local isDefaultAtt, statAttachment, noCache = self2.GetStatRecursive(self, self2.AttachmentTableCache, statPath, istable(statSelf) and tableCopy(statSelf) or statSelf)
local shouldCache = not noCache and
not (self2.StatCache_Blacklist_Real or self2.StatCache_Blacklist)[currentVersionStat] and
not (self2.StatCache_Blacklist_Real or self2.StatCache_Blacklist)[statPath[1]] and
not (ccv and ccv:GetBool())
if istable(statAttachment) and istable(statSelf) and not dontMergeTables then
statSelf = table.Merge(tableCopy(statSelf), statAttachment)
else
statSelf = statAttachment
end
if shouldCache and not self2.ignore_stat_cache then
if not isDefault or not isDefaultAtt then
self2.StatCache[currentVersionStat] = statSelf
end
self2.StatCache2[currentVersionStat] = true
end
--local getstat = hook.Run("TFA_GetStat", self, currentVersionStat, statSelf)
--if getstat ~= nil then return translate(getstat) end
return translate(statSelf)
end

View File

@@ -0,0 +1,224 @@
--[[
| 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.
SWEP.HeadshotMultiplier = 2.7
SWEP.StoredAmmo = 0
SWEP.IsDropped = false
SWEP.DeploySpeed = 1.4
SWEP.fingerprints = {}
-- crosshair
if CLIENT then
-- luacheck: globals LANG Key
local SafeTranslation = function(x) return x end
local GetPTranslation = LANG and LANG.GetParamTranslation or SafeTranslation
-- Many non-gun weapons benefit from some help
local help_spec = {
text = "",
font = "TabLarge",
xalign = TEXT_ALIGN_CENTER
}
function SWEP:DrawHelp()
local data = self.HUDHelp
local translate = data.translatable
local primary = data.primary
local secondary = data.secondary
if translate then
primary = primary and GetPTranslation(primary, data.translate_params)
secondary = secondary and GetPTranslation(secondary, data.translate_params)
end
help_spec.pos = {ScrW() / 2.0, ScrH() - 40}
help_spec.text = secondary or primary
draw.TextShadow(help_spec, 2)
-- if no secondary exists, primary is drawn at the bottom and no top line
-- is drawn
if secondary then
help_spec.pos[2] = ScrH() - 60
help_spec.text = primary
draw.TextShadow(help_spec, 2)
end
end
local function SafeKey(binding, default)
local b = input.LookupBinding(binding)
if not b then return default end
return string.upper(b)
end
local Key = Key or SafeKey
-- mousebuttons are enough for most weapons
local default_key_params = {
primaryfire = Key("+attack", "LEFT MOUSE"),
secondaryfire = Key("+attack2", "RIGHT MOUSE"),
usekey = Key("+use", "USE")
}
function SWEP:AddHUDHelp(primary_text, secondary_text, translate, extra_params)
extra_params = extra_params or {}
self.HUDHelp = {
primary = primary_text,
secondary = secondary_text,
translatable = translate,
translate_params = table.Merge(extra_params, default_key_params)
}
end
end
function SWEP:GetHeadshotMultiplier(victim, dmginfo)
return self.HeadshotMultiplier or 2
end
function SWEP:IsEquipment()
-- luacheck: globals WEPS
if WEPS and WEPS.IsEquipment then
local val = WEPS.IsEquipment(self)
if val ~= nil then
return val
else
return false
end
else
return false
end
end
-- The OnDrop() hook is useless for this as it happens AFTER the drop. OwnerChange
-- does not occur when a drop happens for some reason. Hence this thing.
function SWEP:PreDrop()
if not IsValid(self) then return end
if not self.Ammo1 then return end
if SERVER and IsValid(self:GetOwner()) and self.Primary_TFA.Ammo ~= "none" then
local ammo = self:Ammo1()
-- Do not drop ammo if we have another gun that uses this type
for _, w in pairs(self:GetOwner():GetWeapons()) do
if IsValid(w) and w ~= self and w:GetPrimaryAmmoType() == self:GetPrimaryAmmoType() then
ammo = 0
end
end
self.StoredAmmo = ammo
if ammo > 0 then
self:GetOwner():RemoveAmmo(ammo, self.Primary_TFA.Ammo)
end
end
end
function SWEP:DampenDrop()
if not IsValid(self) then return end
-- For some reason gmod drops guns on death at a speed of 400 units, which
-- catapults them away from the body. Here we want people to actually be able
-- to find a given corpse's weapon, so we override the velocity here and call
-- this when dropping guns on death.
local phys = self:GetPhysicsObject()
if IsValid(phys) then
phys:SetVelocityInstantaneous(Vector(0, 0, -75) + phys:GetVelocity() * 0.001)
phys:AddAngleVelocity(phys:GetAngleVelocity() * -0.99)
end
end
local SF_WEAPON_START_CONSTRAINED = 1
-- Picked up by player. Transfer of stored ammo and such.
function SWEP:EquipTTT(newowner)
if engine.ActiveGamemode() ~= "terrortown" then return end
if SERVER then
if self:IsOnFire() then
self:Extinguish()
end
self.fingerprints = self.fingerprints or {}
if not table.HasValue(self.fingerprints, newowner) then
table.insert(self.fingerprints, newowner)
end
if self:HasSpawnFlags(SF_WEAPON_START_CONSTRAINED) then
-- If this weapon started constrained, unset that spawnflag, or the
-- weapon will be re-constrained and float
local flags = self:GetSpawnFlags()
local newflags = bit.band(flags, bit.bnot(SF_WEAPON_START_CONSTRAINED))
self:SetKeyValue("spawnflags", newflags)
end
end
if not self.Ammo1 then return end
if SERVER and IsValid(newowner) and self.StoredAmmo > 0 and self.Primary_TFA.Ammo ~= "none" then
local ammo = newowner:GetAmmoCount(self.Primary_TFA.Ammo)
self.Primary_TFA.ClipMax = self.Primary_TFA.ClipMax or (math.abs(self.Primary_TFA.ClipSize) * 4)
local given = math.min(self.StoredAmmo, self.Primary_TFA.ClipMax - ammo)
newowner:GiveAmmo(given, self.Primary_TFA.Ammo)
self.StoredAmmo = 0
end
end
-- We were bought as special equipment, some weapons will want to do something
-- extra for their buyer
function SWEP:WasBought(buyer)
end
function SWEP:DyingShot()
local fired = false
-- if self:GetIronSightsProgress() and self:GetIronSightsProgress() > 0.01 then
self:SetIronSightsRaw(false)
if self:GetNextPrimaryFire() > CurTime() then return fired end
-- Owner should still be alive here
if IsValid(self:GetOwner()) then
local punch = self.Primary_TFA.Recoil or 5
-- Punch view to disorient aim before firing dying shot
local eyeang = self:GetOwner():EyeAngles()
eyeang.pitch = eyeang.pitch - math.Rand(-punch, punch)
eyeang.yaw = eyeang.yaw - math.Rand(-punch, punch)
self:GetOwner():SetEyeAngles(eyeang)
MsgN(self:GetOwner():Nick() .. " fired his DYING SHOT")
self:GetOwner().dying_wep = self
self:PrimaryAttack()
fired = true
end
-- end
return fired
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,107 @@
--[[
| 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 angle_zero = Angle()
SWEP.WeaponLength = 0
SWEP.NearWallVector = Vector(0.091287083923817, -0.4564354121685, -0.18257416784763)
SWEP.NearWallVectorADS = Vector(0, 0, 0)
SWEP.ViewModelPunchPitchMultiplier = 0.5
SWEP.ViewModelPunchPitchMultiplier_IronSights = 0.09
SWEP.ViewModelPunch_MaxVertialOffset = 3
SWEP.ViewModelPunch_MaxVertialOffset_IronSights = 1.95
SWEP.ViewModelPunch_VertialMultiplier = 1
SWEP.ViewModelPunch_VertialMultiplier_IronSights = 0.25
SWEP.ViewModelPunchYawMultiplier = 0.6
SWEP.ViewModelPunchYawMultiplier_IronSights = 0.25
local onevec = Vector(1, 1, 1)
local function RBP(vm)
local bc = vm:GetBoneCount()
if not bc or bc <= 0 then return end
for i = 0, bc do
vm:ManipulateBoneScale(i, onevec)
vm:ManipulateBoneAngles(i, angle_zero)
vm:ManipulateBonePosition(i, vector_origin)
end
end
function SWEP:ApplyViewModelModifications()
local self2 = self:GetTable()
if not self2.VMIV(self) then return end
local vm = self2.OwnerViewModel
local bgcount = #(vm:GetBodyGroups() or {})
local ViewModelBodygroups = self2.GetStatRawL(self, "ViewModelBodygroups")
local bgt = ViewModelBodygroups or self2.Bodygroups or {}
for i = 0, bgcount - 1 do
vm:SetBodygroup(i, bgt[i] or 0)
end
local skinind = self2.GetStatL(self, "Skin")
if skinind and isnumber(skinind) then
vm:SetSkin(skinind)
self:SetSkin(skinind)
end
self2.ClearMaterialCache(self)
end
function SWEP:ResetViewModelModifications()
local self2 = self:GetTable()
if not self2.VMIV(self) then return end
local vm = self2.OwnerViewModel
RBP(vm)
vm:SetSkin(0)
local matcount = #(vm:GetMaterials() or {})
for i = 0, matcount do
vm:SetSubMaterial(i, "")
end
for i = 0, #(vm:GetBodyGroups() or {}) - 1 do
vm:SetBodygroup(i, 0)
end
end

View File

@@ -0,0 +1,162 @@
--[[
| 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.
include("shared.lua")
include("common/ai_translations.lua")
include("common/anims.lua")
include("common/autodetection.lua")
include("common/utils.lua")
include("common/stat.lua")
include("common/attachments.lua")
include("common/bullet.lua")
include("common/effects.lua")
include("common/calc.lua")
include("common/akimbo.lua")
include("common/events.lua")
include("common/nzombies.lua")
include("common/ttt.lua")
include("common/viewmodel.lua")
include("common/skins.lua")
AddCSLuaFile("common/ai_translations.lua")
AddCSLuaFile("common/anims.lua")
AddCSLuaFile("common/autodetection.lua")
AddCSLuaFile("common/utils.lua")
AddCSLuaFile("common/stat.lua")
AddCSLuaFile("common/attachments.lua")
AddCSLuaFile("common/bullet.lua")
AddCSLuaFile("common/effects.lua")
AddCSLuaFile("common/calc.lua")
AddCSLuaFile("common/akimbo.lua")
AddCSLuaFile("common/events.lua")
AddCSLuaFile("common/nzombies.lua")
AddCSLuaFile("common/ttt.lua")
AddCSLuaFile("common/viewmodel.lua")
AddCSLuaFile("common/skins.lua")
AddCSLuaFile("shared.lua")
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("client/effects.lua")
AddCSLuaFile("client/viewbob.lua")
AddCSLuaFile("client/hud.lua")
AddCSLuaFile("client/mods.lua")
AddCSLuaFile("client/laser.lua")
AddCSLuaFile("client/fov.lua")
AddCSLuaFile("client/flashlight.lua")
AddCSLuaFile("client/viewmodel.lua")
AddCSLuaFile("client/bobcode.lua")
SWEP.Weight = 60 -- Decides whether we should switch from/to this
SWEP.AutoSwitchTo = true -- Auto switch to
SWEP.AutoSwitchFrom = true -- Auto switch from
local sv_tfa_npc_burst = GetConVar("sv_tfa_npc_burst")
function SWEP:NPCShoot_Primary()
if self:Clip1() <= 0 and self:GetMaxClip1() > 0 then
self:GetOwner():SetSchedule(SCHED_RELOAD)
return
end
return self:PrimaryAttack()
end
function SWEP:GetNPCRestTimes()
if sv_tfa_npc_burst:GetBool() or self:GetStatL("NPCBurstOverride", false) then
return self:GetStatL("NPCMinRest", self:GetFireDelay()), self:GetStatL("NPCMaxRest", self:GetFireDelay() * 2)
end
if self:GetStatL("Primary.Automatic") then
return 0, 0
else
return self:GetFireDelay(), self:GetFireDelay() * 2
end
end
function SWEP:GetNPCBurstSettings()
if sv_tfa_npc_burst:GetBool() or self:GetStatL("NPCBurstOverride", false) then
return self:GetStatL("NPCMinBurst", 1), self:GetStatL("NPCMinBurst", 6), self:GetStatL("NPCBurstDelay", self:GetFireDelay() * self:GetMaxBurst())
end
if self:GetMaxClip1() > 0 then
local burst = self:GetMaxBurst()
local value = math.ceil(self:Clip1() / burst)
local delay = self:GetFireDelay() * burst
if self:GetStatL("Primary.Automatic") then
return math.min(4, value), math.min(12, value), delay
else
return 1, math.min(4, value), delay
end
else
return 1, 30, self:GetFireDelay() * self:GetMaxBurst()
end
end
function SWEP:GetNPCBulletSpread()
return 1 -- we handle this manually, in calculate cone, recoil and shootbullet
end
function SWEP:CanBePickedUpByNPCs()
return true
end
local sv_tfa_npc_randomize_atts = GetConVar("sv_tfa_npc_randomize_atts")
function SWEP:Equip(...)
local owner = self:GetOwner()
if owner:IsNPC() then
self.IsNPCOwned = true
if not self.IsFirstEquip and sv_tfa_npc_randomize_atts:GetBool() then
self:RandomizeAttachments(true)
end
local function closure()
self:NPCWeaponThinkHook()
end
hook.Add("TFA_NPCWeaponThink", self, function()
ProtectedCall(closure)
end)
else
self.IsNPCOwned = false
end
self.IsFirstEquip = true
self.OwnerViewModel = nil
self:EquipTTT(...)
end
TFA.FillMissingMetaValues(SWEP)

File diff suppressed because it is too large Load Diff