mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
Upload
This commit is contained in:
247
lua/weapons/tfa_gun_base/client/bobcode.lua
Normal file
247
lua/weapons/tfa_gun_base/client/bobcode.lua
Normal 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
|
||||
202
lua/weapons/tfa_gun_base/client/effects.lua
Normal file
202
lua/weapons/tfa_gun_base/client/effects.lua
Normal 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
|
||||
213
lua/weapons/tfa_gun_base/client/flashlight.lua
Normal file
213
lua/weapons/tfa_gun_base/client/flashlight.lua
Normal 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
|
||||
77
lua/weapons/tfa_gun_base/client/fov.lua
Normal file
77
lua/weapons/tfa_gun_base/client/fov.lua
Normal 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
|
||||
1867
lua/weapons/tfa_gun_base/client/hud.lua
Normal file
1867
lua/weapons/tfa_gun_base/client/hud.lua
Normal file
File diff suppressed because it is too large
Load Diff
244
lua/weapons/tfa_gun_base/client/laser.lua
Normal file
244
lua/weapons/tfa_gun_base/client/laser.lua
Normal 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
|
||||
1351
lua/weapons/tfa_gun_base/client/mods.lua
Normal file
1351
lua/weapons/tfa_gun_base/client/mods.lua
Normal file
File diff suppressed because it is too large
Load Diff
170
lua/weapons/tfa_gun_base/client/viewbob.lua
Normal file
170
lua/weapons/tfa_gun_base/client/viewbob.lua
Normal 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
|
||||
788
lua/weapons/tfa_gun_base/client/viewmodel.lua
Normal file
788
lua/weapons/tfa_gun_base/client/viewmodel.lua
Normal 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
|
||||
Reference in New Issue
Block a user