--[[ | 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.Category = "" --The category. Please, just choose something generic or something I've already done if you plan on only doing like one swep. SWEP.Author = "TheForgottenArchitect" SWEP.Contact = "theforgottenarchitect" SWEP.Purpose = "" SWEP.Instructions = "" SWEP.DrawCrosshair = true SWEP.DrawCrosshairIronSights = false SWEP.ViewModelFOV = 65 SWEP.ViewModelFlip = false SWEP.Skin = 0 --Viewmodel skin SWEP.Spawnable = false SWEP.IsTFAWeapon = true SWEP.LoopedReload = false SWEP.ShotgunEmptyAnim = false SWEP.ShotgunEmptyAnim_Shell = true SWEP.ShotgunStartAnimShell = false --shotgun start anim inserts shell SWEP.Secondary.IronSightsEnabled = true SWEP.RegularMoveSpeedMultiplier = 1 SWEP.FireSoundAffectedByClipSize = true SWEP.Primary.Damage = -1 SWEP.Primary.DamageTypeHandled = true --true will handle damagetype in base SWEP.Primary.NumShots = 1 SWEP.Primary.Force = -1 SWEP.Primary.Knockback = -1 SWEP.Primary.Recoil = 1 SWEP.Primary.RPM = 600 SWEP.Primary.RPM_Semi = -1 SWEP.Primary.RPM_Burst = -1 SWEP.Primary.StaticRecoilFactor = 0.5 SWEP.Primary.KickUp = 0.5 SWEP.Primary.KickDown = 0.5 SWEP.Primary.KickRight = 0.5 SWEP.Primary.KickHorizontal = 0.5 SWEP.Primary.DamageType = nil SWEP.Primary.Ammo = "smg1" SWEP.Primary.AmmoConsumption = 1 SWEP.Primary.Spread = 0 SWEP.Primary.DisplaySpread = true SWEP.Primary.SpreadMultiplierMax = -1 --How far the spread can expand when you shoot. SWEP.Primary.SpreadIncrement = -1 --What percentage of the modifier is added on, per shot. SWEP.Primary.SpreadRecovery = -1 --How much the spread recovers, per second. SWEP.Primary.SpreadRecoveryDelay = 0 SWEP.Primary.IronAccuracy = 0 SWEP.Primary.Range = -1--1200 SWEP.Primary.RangeFalloff = -1--0.5 SWEP.Primary.PenetrationMultiplier = 1 SWEP.Primary.DryFireDelay = nil --[[Actual clientside values]]-- SWEP.DrawAmmo = true -- Should draw the default HL2 ammo counter SWEP.DrawWeaponInfoBox = false -- Should draw the weapon info box SWEP.BounceWeaponIcon = false -- Should the weapon icon bounce? local sv_tfa_jamming = GetConVar("sv_tfa_jamming") local sv_tfa_jamming_mult = GetConVar("sv_tfa_jamming_mult") local sv_tfa_jamming_factor = GetConVar("sv_tfa_jamming_factor") local sv_tfa_jamming_factor_inc = GetConVar("sv_tfa_jamming_factor_inc") -- RP owners always like realism, so this feature might be something they like. Enable it for them! TFA_AUTOJAMMING_ENABLED = string.find(engine.ActiveGamemode(), 'rp') or string.find(engine.ActiveGamemode(), 'roleplay') or string.find(engine.ActiveGamemode(), 'nutscript') or string.find(engine.ActiveGamemode(), 'serious') or TFA_ENABLE_JAMMING_BY_DEFAULT SWEP.CanJam = tobool(TFA_AUTOJAMMING_ENABLED) SWEP.JamChance = 0.04 SWEP.JamFactor = 0.06 SWEP.BoltAction = false --Unscope/sight after you shoot? SWEP.BoltAction_Forced = false SWEP.Scoped = false --Draw a scope overlay? SWEP.ScopeOverlayThreshold = 0.875 --Percentage you have to be sighted in to see the scope. SWEP.BoltTimerOffset = 0.25 --How long you stay sighted in after shooting, with a bolt action. SWEP.ScopeScale = 0.5 SWEP.ReticleScale = 0.7 SWEP.MuzzleAttachment = "1" SWEP.ShellAttachment = "2" SWEP.MuzzleFlashEnabled = true SWEP.MuzzleFlashEffect = nil SWEP.MuzzleFlashEffectSilenced = "tfa_muzzleflash_silenced" SWEP.CustomMuzzleFlash = true SWEP.EjectionSmokeEnabled = true SWEP.LuaShellEject = false SWEP.LuaShellEjectDelay = 0 SWEP.LuaShellEffect = nil --Defaults to blowback SWEP.SmokeParticle = nil --Smoke particle (ID within the PCF), defaults to something else based on holdtype SWEP.StatusLengthOverride = {} --Changes the status delay of a given animation; only used on reloads. Otherwise, use SequenceLengthOverride or one of the others SWEP.SequenceLengthOverride = {} --Changes both the status delay and the nextprimaryfire of a given animation SWEP.SequenceTimeOverride = {} --Like above but changes animation length to a target SWEP.SequenceRateOverride = {} --Like above but scales animation length rather than being absolute SWEP.BlowbackEnabled = false --Enable Blowback? SWEP.BlowbackVector = Vector(0, -1, 0) --Vector to move bone relative to bone orientation. SWEP.BlowbackCurrentRoot = 0 --Amount of blowback currently, for root SWEP.BlowbackCurrent = 0 --Amount of blowback currently, for bones SWEP.BlowbackBoneMods = nil --Viewmodel bone mods via SWEP Creation Kit SWEP.Blowback_Only_Iron = true --Only do blowback on ironsights SWEP.Blowback_PistolMode = false --Do we recover from blowback when empty? SWEP.BlowbackAllowAnimation = false SWEP.ProceduralHolsterEnabled = nil SWEP.ProceduralHolsterTime = 0.3 SWEP.ProceduralHolsterPosition = Vector(3, 0, -5) SWEP.ProceduralHolsterAngle = Vector(-40, -30, 10) SWEP.IsProceduralReloadBased = false --Do we reload using lua instead of a .mdl animation SWEP.ProceduralReloadTime = 1 --Time to take when procedurally reloading, including transition in (but not out) SWEP.Blowback_PistolMode_Disabled = { [ACT_VM_RELOAD] = true, [ACT_VM_RELOAD_EMPTY] = true, [ACT_VM_DRAW_EMPTY] = true, [ACT_VM_IDLE_EMPTY] = true, [ACT_VM_HOLSTER_EMPTY] = true, [ACT_VM_DRYFIRE] = true, [ACT_VM_FIDGET] = true, [ACT_VM_FIDGET_EMPTY] = true } SWEP.Blowback_Shell_Enabled = true SWEP.Blowback_Shell_Effect = "ShellEject" SWEP.Secondary.Ammo = "" SWEP.Secondary.ClipSize = -1 SWEP.Secondary.DefaultClip = 0 SWEP.Sights_Mode = TFA.Enum.LOCOMOTION_LUA -- ANI = mdl, HYBRID = lua but continue idle, Lua = stop mdl animation SWEP.Sprint_Mode = TFA.Enum.LOCOMOTION_LUA -- ANI = mdl, HYBRID = ani + lua, Lua = lua only SWEP.Walk_Mode = TFA.Enum.LOCOMOTION_LUA -- ANI = mdl, HYBRID = ani + lua, Lua = lua only SWEP.Customize_Mode = TFA.Enum.LOCOMOTION_LUA -- ANI = mdl, HYBRID = ani + lua, Lua = lua only SWEP.SprintFOVOffset = 5 SWEP.Idle_Mode = TFA.Enum.IDLE_BOTH --TFA.Enum.IDLE_DISABLED = no idle, TFA.Enum.IDLE_LUA = lua idle, TFA.Enum.IDLE_ANI = mdl idle, TFA.Enum.IDLE_BOTH = TFA.Enum.IDLE_ANI + TFA.Enum.IDLE_LUA SWEP.Idle_Blend = 0.25 --Start an idle this far early into the end of a transition SWEP.Idle_Smooth = 0.05 --Start an idle this far early into the end of another animation SWEP.IronSightTime = 0.3 SWEP.IronSightsSensitivity = 1 SWEP.InspectPosDef = Vector(9.779, -11.658, -2.241) SWEP.InspectAngDef = Vector(24.622, 42.915, 15.477) SWEP.SprintViewModelPosition = Vector(0,0,0) SWEP.SprintViewModelAngle = Vector(0,0,0) SWEP.AllowSprintAttack = false --Shoot while sprinting? SWEP.CrouchViewModelPosition = Vector(0, -1, -.5) SWEP.CrouchViewModelAngle = Vector(0, 0, 0) SWEP.Primary.RecoilLUT_IronSightsMult = 0.5 SWEP.Primary.RecoilLUT_AnglePunchMult = 0.25 SWEP.Primary.RecoilLUT_ViewPunchMult = 1 SWEP.EventTable = {} SWEP.RTMaterialOverride = nil SWEP.RTOpaque = false SWEP.RTCode = nil--function(self) return end SWEP.RTBGBlur = true SWEP.ViewModelPosition = Vector(0,0,0) SWEP.ViewModelAngle = Vector(0,0,0) SWEP.CameraOffset = Angle(0, 0, 0) SWEP.AdditiveViewModelPosition = true SWEP.AllowIronSightsDoF = true SWEP.Primary.DisplayFalloff = true SWEP.IronAnimation = { --[[ ["in"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "Idle_To_Iron", --Number for act, String/Number for sequence ["value_empty"] = "Idle_To_Iron_Dry", ["transition"] = true }, --Inward transition ["loop"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "Idle_Iron", --Number for act, String/Number for sequence ["value_empty"] = "Idle_Iron_Dry" }, --Looping Animation ["out"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "Iron_To_Idle", --Number for act, String/Number for sequence ["value_empty"] = "Iron_To_Idle_Dry", ["transition"] = true }, --Outward transition ["shoot"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "Fire_Iron", --Number for act, String/Number for sequence ["value_last"] = "Fire_Iron_Last", ["value_empty"] = "Fire_Iron_Dry" } --What do you think ]]-- } SWEP.SprintAnimation = { --[[ ["in"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "Idle_to_Sprint", --Number for act, String/Number for sequence ["value_empty"] = "Idle_to_Sprint_Empty", ["transition"] = true }, --Inward transition ["loop"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "Sprint_", --Number for act, String/Number for sequence ["value_empty"] = "Sprint_Empty_", ["is_idle"] = true },--looping animation ["out"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "Sprint_to_Idle", --Number for act, String/Number for sequence ["value_empty"] = "Sprint_to_Idle_Empty", ["transition"] = true } --Outward transition ]]-- } SWEP.ShootAnimation = {--[[ ["in"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "shoot_loop_start", --Number for act, String/Number for sequence ["value_is"] = "shoot_loop_iron_start" }, ["loop"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "shoot_loop", --Number for act, String/Number for sequence ["value_is"] = "shoot_loop_iron", ["is_idle"] = true }, ["out"] = { ["type"] = TFA.Enum.ANIMATION_SEQ, --Sequence or act ["value"] = "shoot_loop_end", --Number for act, String/Number for sequence ["value_is"] = "shoot_loop_iron_end" }]]-- } SWEP.FirstDeployEnabled = nil--Force first deploy enabled --[[Dont edit under this unless you know what u r doing]] SWEP.IronSightsProgress = 0 SWEP.CLIronSightsProgress = 0 SWEP.SprintProgress = 0 SWEP.WalkProgress = 0 SWEP.SpreadRatio = 0 SWEP.CrouchingRatio = 0 SWEP.SmokeParticles = { pistol = "tfa_ins2_weapon_muzzle_smoke", smg = "tfa_ins2_weapon_muzzle_smoke", grenade = "tfa_ins2_weapon_muzzle_smoke", ar2 = "tfa_ins2_weapon_muzzle_smoke", shotgun = "tfa_ins2_weapon_muzzle_smoke", rpg = "tfa_ins2_weapon_muzzle_smoke", physgun = "tfa_ins2_weapon_muzzle_smoke", crossbow = "tfa_ins2_weapon_muzzle_smoke", melee = "tfa_ins2_weapon_muzzle_smoke", slam = "tfa_ins2_weapon_muzzle_smoke", normal = "tfa_ins2_weapon_muzzle_smoke", melee2 = "tfa_ins2_weapon_muzzle_smoke", knife = "tfa_ins2_weapon_muzzle_smoke", duel = "tfa_ins2_weapon_muzzle_smoke", camera = "tfa_ins2_weapon_muzzle_smoke", magic = "tfa_ins2_weapon_muzzle_smoke", revolver = "tfa_ins2_weapon_muzzle_smoke", silenced = "tfa_ins2_weapon_muzzle_smoke" } --[[ SWEP.SmokeParticles = { pistol = "weapon_muzzle_smoke", smg = "weapon_muzzle_smoke", grenade = "weapon_muzzle_smoke", ar2 = "weapon_muzzle_smoke", shotgun = "weapon_muzzle_smoke_long", rpg = "weapon_muzzle_smoke_long", physgun = "weapon_muzzle_smoke_long", crossbow = "weapon_muzzle_smoke_long", melee = "weapon_muzzle_smoke", slam = "weapon_muzzle_smoke", normal = "weapon_muzzle_smoke", melee2 = "weapon_muzzle_smoke", knife = "weapon_muzzle_smoke", duel = "weapon_muzzle_smoke", camera = "weapon_muzzle_smoke", magic = "weapon_muzzle_smoke", revolver = "weapon_muzzle_smoke_long", silenced = "weapon_muzzle_smoke" }--]] --[[ SWEP.SmokeParticles = { pistol = "smoke_trail_controlled", smg = "smoke_trail_tfa", grenade = "smoke_trail_tfa", ar2 = "smoke_trail_tfa", shotgun = "smoke_trail_wild", rpg = "smoke_trail_tfa", physgun = "smoke_trail_tfa", crossbow = "smoke_trail_tfa", melee = "smoke_trail_tfa", slam = "smoke_trail_tfa", normal = "smoke_trail_tfa", melee2 = "smoke_trail_tfa", knife = "smoke_trail_tfa", duel = "smoke_trail_tfa", camera = "smoke_trail_tfa", magic = "smoke_trail_tfa", revolver = "smoke_trail_tfa", silenced = "smoke_trail_controlled" } ]]-- SWEP.Inspecting = false SWEP.InspectingProgress = 0 SWEP.LuaShellRequestTime = -1 SWEP.BobScale = 0 SWEP.SwayScale = 0 SWEP.BoltDelay = 1 SWEP.ProceduralHolsterProgress = 0 SWEP.BurstCount = 0 SWEP.DefaultFOV = 90 SWEP.m_WeaponDeploySpeed = 255 --[[ Localize Functions ]] local function l_Lerp(v, f, t) return f + (t - f) * v end local l_mathApproach = math.Approach local l_CT = CurTime --[[Frequently Reused Local Vars]] local stat --Weapon status local ct = 0--Curtime, frametime, real frametime local sp = game.SinglePlayer() --Singleplayer local developer = GetConVar("developer") function SWEP:NetworkVarTFA(typeIn, nameIn) if not self.TrackedDTTypes then self.TrackedDTTypes = { Angle = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, Bool = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, Entity = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, Float = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, Int = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, String = {0, 1, 2, 3}, Vector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, } if istable(self.dt) then local meta = getmetatable(self.dt) if istable(meta) and isfunction(meta.__index) then local name, value = debug.getupvalue(meta.__index, 1) if name == "datatable" and istable(value) then for variableName, variableData in SortedPairs(value) do if istable(variableData) and isstring(variableData.typename) and isnumber(variableData.index) then local trackedData = self.TrackedDTTypes[variableData.typename] if trackedData then table.RemoveByValue(trackedData, variableData.index) end end end end end end end if not self.TrackedDTTypes[typeIn] then error("Variable type " .. typeIn .. " is invalid") end local gatherindex = table.remove(self.TrackedDTTypes[typeIn], 1) if gatherindex then (self["NetworkVar_TFA"] or self["NetworkVar"])(self, typeIn, gatherindex, nameIn) return end local get = self["GetNW2" .. typeIn] local set = self["SetNW2" .. typeIn] self["Set" .. nameIn] = function(_self, value) set(_self, nameIn, value) end self["Get" .. nameIn] = function(_self, def) return get(_self, nameIn, def) end if developer:GetBool() then print("[TFA Base] developer 1: Variable " .. nameIn .. " can not use DTVars due to " .. typeIn .. " index exhaust") end end local IsFirstTimePredicted = IsFirstTimePredicted --[[ Function Name: SetupDataTables Syntax: Should not be manually called. Returns: Nothing. Simple sets up DTVars to be networked. Purpose: Networking. ]] function SWEP:SetupDataTables() self.TrackedDTTypes = nil self.NetworkVar_TFA = self.NetworkVar --self:NetworkVarTFA("Bool", "IronSights") self:NetworkVarTFA("Bool", "IronSightsRaw") self:NetworkVarTFA("Bool", "Sprinting") self:NetworkVarTFA("Bool", "Silenced") self:NetworkVarTFA("Bool", "ReloadLoopCancel") self:NetworkVarTFA("Bool", "Walking") self:NetworkVarTFA("Bool", "Customizing") self.GetShotgunCancel = self.GetReloadLoopCancel self.SetShotgunCancel = self.SetReloadLoopCancel self:NetworkVarTFA("Bool", "FlashlightEnabled") self:NetworkVarTFA("Bool", "Jammed") self:NetworkVarTFA("Bool", "FirstDeployEvent") self:NetworkVarTFA("Bool", "IsCyclingSafety") self:NetworkVarTFA("Bool", "SafetyCycleAnimated") self:NetworkVarTFA("Bool", "HasPlayedEmptyClick") self:NetworkVarTFA("Float", "StatusEnd") self:NetworkVarTFA("Float", "NextIdleAnim") self:NetworkVarTFA("Float", "NextLoopSoundCheck") self:NetworkVarTFA("Float", "JamFactor") self:NetworkVarTFA("Float", "EventTimer") self:NetworkVarTFA("Float", "LastGunFire") self:NetworkVarTFA("Int", "StatusRaw") self:NetworkVarTFA("Int", "FireMode") self:NetworkVarTFA("Int", "LastActivity") self:NetworkVarTFA("Int", "BurstCount") self:NetworkVarTFA("Int", "ShootStatus") self:NetworkVarTFA("Int", "EventStatus1") self:NetworkVarTFA("Int", "EventStatus2") self:NetworkVarTFA("Int", "EventStatus3") self:NetworkVarTFA("Int", "EventStatus4") self:NetworkVarTFA("Int", "EventStatus5") self:NetworkVarTFA("Int", "EventStatus6") self:NetworkVarTFA("Int", "EventStatus7") self:NetworkVarTFA("Int", "EventStatus8") self:NetworkVarTFA("Bool", "RecoilLoop") self:NetworkVarTFA("Bool", "RecoilThink") self:NetworkVarTFA("Float", "RecoilInProgress") self:NetworkVarTFA("Float", "RecoilInWait") self:NetworkVarTFA("Float", "RecoilLoopProgress") self:NetworkVarTFA("Float", "RecoilLoopWait") self:NetworkVarTFA("Float", "RecoilOutProgress") self:NetworkVarTFA("Float", "LastRecoil") if not self.get_event_status_lut then self.get_event_status_lut = {} self.set_event_status_lut = {} for i = 1, 8 do self.get_event_status_lut[i] = self['GetEventStatus' .. i] self.set_event_status_lut[i] = self['SetEventStatus' .. i] end end self:NetworkVarTFA("Entity", "SwapTarget") self:NetworkVarNotify("Customizing", self.CustomizingUpdated) self:NetworkVarTFA("Float", "SpreadRatio") self:NetworkVarTFA("Float", "IronSightsProgress") self:NetworkVarTFA("Float", "ProceduralHolsterProgress") self:NetworkVarTFA("Float", "InspectingProgress") self:NetworkVarTFA("Float", "JumpRatio") self:NetworkVarTFA("Float", "CrouchingRatio") self:NetworkVarTFA("Float", "ViewPunchBuild") self:NetworkVarTFA("Float", "ViewPunchP") self:NetworkVarTFA("Float", "ViewPunchY") self:NetworkVarTFA("Float", "SprintProgress") self:NetworkVarTFA("Float", "WalkProgress") self:NetworkVarTFA("Float", "LastVelocity") self:NetworkVarTFA("Int", "AnimCycle") self:NetworkVarTFA("Vector", "QueuedRecoil") self:NetworkVarTFA("Float", "PrevRecoilAngleTime") self:NetworkVarTFA("Angle", "PrevRecoilAngle") self:NetworkVarTFA("Bool", "CustomizeUpdated") self:NetworkVarTFA("Bool", "IronSightsOldFinal") function self.NetworkVar(self2, typeIn, slotIn, nameIn) return self2:NetworkVarTFA(typeIn, nameIn) end self:NetworkVarTFA("Float", "StatusStart") self:NetworkVarTFA("Float", "LastSafetyShoot") self:NetworkVarTFA("Int", "LastSequence") self:NetworkVarTFA("Int", "DownButtons") self:NetworkVarTFA("Int", "LastPressedButtons") self:NetworkVarTFA("Float", "LastReloadPressed") self:NetworkVarTFA("Float", "LastIronSightsPressed") self.GetStatus = self.GetStatusRaw self.GetIronSights = self.GetIronSightsOldFinal self.GetIronSightsDirect = self.GetIronSightsOldFinal hook.Run("TFA_SetupDataTables", self) end function SWEP:GetStatusProgress(unpredicted) if self:GetStatus() == TFA.Enum.STATUS_IDLE then return 1 end local StatusStart = self:GetStatusStart() if StatusStart <= 0 then return end local StatusEnd = self:GetStatusEnd() if StatusStart > StatusEnd then return 1 end local time = unpredicted and (l_CT() + (self.CurTimePredictionAdvance or 0)) or l_CT() if StatusStart >= time then return 0 end if StatusEnd <= time then return 1 end return (time - StatusStart) / (StatusEnd - StatusStart) end function SWEP:GetStatusProgressTime(unpredicted) if self:GetStatus() == TFA.Enum.STATUS_IDLE then return 0 end local StatusStart = self:GetStatusStart() if StatusStart <= 0 then return end local StatusEnd = self:GetStatusEnd() if StatusStart > StatusEnd then return 0 end local time = unpredicted and (l_CT() + (self.CurTimePredictionAdvance or 0)) or l_CT() if StatusEnd <= time then return 0 end return StatusEnd - time end function SWEP:SetStatus(statusIn, timeOn) self:SetStatusRaw(statusIn) self:SetStatusStart(l_CT()) if timeOn ~= nil then self:SetStatusEnd(timeOn) end end function SWEP:ScheduleStatus(statusIn, timeFor) self:SetStatusRaw(statusIn) local time = l_CT() self:SetStatusStart(time) self:SetStatusEnd(time + timeFor) end function SWEP:ExtendStatus(timeFor) self:SetStatusEnd(self:GetStatusEnd() + timeFor) end function SWEP:ExtendStatusTo(timeFor) self:SetStatusEnd(math.max(self:GetStatusEnd(), timeFor)) end --[[ Function Name: Initialize Syntax: Should not be normally called. Notes: Called after actual SWEP code, but before deploy, and only once. Returns: Nothing. Sets the intial values for the SWEP when it's created. Purpose: Standard SWEP Function ]] local PistolHoldTypes = { ["pistol"] = true, ["357"] = true, ["revolver"] = true } local MeleeHoldTypes = { ["melee"] = true, ["melee2"] = true, ["knife"] = true } local patch_blacklist do local string_sub = string.sub function patch_blacklist(input, structure_version) local target = {} for key in pairs(input) do target[TFA.RemapStatPath(key, TFA.LatestDataVersion, structure_version)] = true end table.Empty(input) setmetatable(input, { __index = target, __newindex = function(_, key, value) target[TFA.RemapStatPath(key, TFA.LatestDataVersion, structure_version)] = value end }) return target end end function SWEP:Initialize() local self2 = self:GetTable() if self2.HasInitialized then ErrorNoHalt(debug.traceback("SWEP:Initialize was called out of order", 2) .. "\n") return end self2.HasInitialized = true --TFA.MigrateStructure(self, self2, self:GetClass(), true) hook.Run("TFA_PreInitialize", self) self2.DrawCrosshairDefault = self2.DrawCrosshair if not self2.BobScaleCustom or self2.BobScaleCustom <= 0 then self2.BobScaleCustom = 1 end TFA.UnfoldBaseClass(self2.Primary) TFA.UnfoldBaseClass(self2.Secondary) TFA.UnfoldBaseClass(self2.Primary.PenetrationMaterials) TFA.UnfoldBaseClass(self2.AttachmentTableOverride) --[[for k, v in pairs(self2.AttachmentTableOverride) do if istable(v) and k ~= "BaseClass" then TFA.MigrateStructure(self, v, self:GetClass(), false) end end]] self2.Primary.BaseClass = nil self2.Secondary.BaseClass = nil if self2.Primary.DisplayIronSpread == nil then self2.Primary.DisplayIronSpread = self2.Primary.DisplaySpread end self2.Primary_TFA = table.Copy(self2.Primary) self2.Secondary_TFA = table.Copy(self2.Secondary) self2.BobScale = 0 self2.SwayScaleCustom = 1 self2.SwayScale = 0 self2.SetSilenced(self, self2.Silenced or self2.DefaultSilenced) self2.Silenced = self2.Silenced or self2.DefaultSilenced self2.InitializeAnims(self) self2.InitializeMaterialTable(self) self2.PatchAmmoTypeAccessors(self) self2.FixRPM(self) self2.FixIdles(self) self2.FixIS(self) self2.FixCone(self) self2.FixProjectile(self) self2.AutoDetectMuzzle(self) self2.AutoDetectDamage(self) self2.AutoDetectDamageType(self) self2.AutoDetectForce(self) self2.AutoDetectPenetrationPower(self) self2.AutoDetectKnockback(self) self2.AutoDetectSpread(self) self2.AutoDetectRange(self) self2.AutoDetectLowAmmoSound(self) self2.IconFix(self) self2.CreateFireModes(self) self2.FixAkimbo(self) self2.FixSprintAnimBob(self) self2.FixWalkAnimBob(self) table.Merge(self2.Primary, self2.Primary_TFA) table.Merge(self2.Secondary, self2.Secondary_TFA) TFA.UnfoldBaseClass(self2.StatCache_Blacklist) self2.StatCache_Blacklist_Real = patch_blacklist(self2.StatCache_Blacklist, self2.TFADataVersion) TFA.UnfoldBaseClass(self2.Attachments) TFA.UnfoldBaseClass(self:GetStatRaw("ViewModelElements", TFA.LatestDataVersion)) TFA.UnfoldBaseClass(self2.ViewModelBoneMods) TFA.UnfoldBaseClass(self2.EventTable) TFA.UnfoldBaseClass(self2.Blowback_PistolMode_Disabled) TFA.UnfoldBaseClass(self2.IronAnimation) TFA.UnfoldBaseClass(self2.SprintAnimation) TFA.UnfoldBaseClass(self2.ShootAnimation) TFA.UnfoldBaseClass(self2.SmokeParticles) self2.ClearStatCache(self) self2.InitAttachments(self) self2.WorldModelBodygroups = self:GetStatRawL("WorldModelBodygroups") self2.ViewModelBodygroups = self:GetStatRawL("ViewModelBodygroups") if not self:GetStatRawL("AimingDownSightsSpeedMultiplier") then self:SetStatRawL("AimingDownSightsSpeedMultiplier", self:GetStatRawL("RegularMoveSpeedMultiplier") * 0.8) end if isnumber(self2.GetStatL(self, "Skin")) then self:SetSkin(self:GetStatL("Skin")) end self:SetNextLoopSoundCheck(-1) self:SetShootStatus(TFA.Enum.SHOOT_IDLE) if SERVER and self:GetOwner():IsNPC() then local seq = self:GetOwner():LookupSequence("shootp1") if MeleeHoldTypes[self2.DefaultHoldType or self2.HoldType] then if self:GetOwner():GetSequenceName(seq) == "shootp1" then self:SetWeaponHoldType("melee2") else self:SetWeaponHoldType("melee") end elseif PistolHoldTypes[self2.DefaultHoldType or self2.HoldType] then if self:GetOwner():GetSequenceName(seq) == "shootp1" then self:SetWeaponHoldType("pistol") else self:SetWeaponHoldType("smg") end else self:SetWeaponHoldType(self2.DefaultHoldType or self2.HoldType) end if self:GetOwner():GetClass() == "npc_citizen" then self:GetOwner():Fire( "DisableWeaponPickup", "", 0 ) end self:GetOwner():SetKeyValue("spawnflags", "256") return end hook.Run("TFA_Initialize", self) end function SWEP:NPCWeaponThinkHook() local self2 = self:GetTable() if not self:GetOwner():IsNPC() then hook.Remove("TFA_NPCWeaponThink", self) return end self2.Think(self) end --[[ Function Name: Deploy Syntax: self:Deploy() Notes: Called after self:Initialize(). Called each time you draw the gun. This is also essential to clearing out old networked vars and resetting them. Returns: True/False to allow quickswitch. Why not? You should really return true. Purpose: Standard SWEP Function ]] function SWEP:Deploy() local self2 = self:GetTable() hook.Run("TFA_PreDeploy", self) local ply = self:GetOwner() self2.IsNPCOwned = ply:IsNPC() if IsValid(ply) and IsValid(ply:GetViewModel()) then self2.OwnerViewModel = ply:GetViewModel() end if SERVER and self:GetStatL("FlashlightAttachment", 0) > 0 and IsValid(ply) and ply:IsPlayer() and ply:FlashlightIsOn() then if not self:GetFlashlightEnabled() then self:ToggleFlashlight(true) end ply:Flashlight(false) end if not self:VMIV() then print("Invalid VM on owner: ") print(ply) return end if not self2.HasDetectedValidAnimations then self:CacheAnimations() end local _, tanim, ttype = self:ChooseDrawAnim() if sp then self:CallOnClient("ChooseDrawAnim", "") end local len = self:GetActivityLength(tanim, false, ttype) self:ScheduleStatus(TFA.Enum.STATUS_DRAW, len) self:SetFirstDeployEvent(true) self:SetNextPrimaryFire(ct + len) self:SetIronSightsRaw(false) if not self:GetStatL("PumpAction") then self:SetReloadLoopCancel( false ) end self:SetBurstCount(0) self:SetIronSightsProgress(0) self:SetSprintProgress(0) self:SetInspectingProgress(0) self:SetProceduralHolsterProgress(0) if self:GetCustomizing() then self:ToggleCustomize() end self2.DefaultFOV = TFADUSKFOV or ( IsValid(ply) and ply:GetFOV() or 90 ) self:ApplyViewModelModifications() self:CallOnClient("ApplyViewModelModifications") local v = hook.Run("TFA_Deploy", self) if v ~= nil then return v end return true end --[[ Function Name: Holster Syntax: self:Holster( weapon entity to switch to ) Notes: This is kind of broken. I had to manually select the new weapon using ply:ConCommand. Returning true is simply not enough. This is also essential to clearing out old networked vars and resetting them. Returns: True/False to allow holster. Useful for animations. Purpose: Standard SWEP Function ]] function SWEP:Holster(target) local self2 = self:GetTable() local v = hook.Run("TFA_PreHolster", self, target) if v ~= nil then return v end if not IsValid(target) then self2.InspectingProgress = 0 return true end if not IsValid(self) then return end stat = self:GetStatus() if not TFA.Enum.HolsterStatus[stat] then if stat == TFA.Enum.STATUS_RELOADING_WAIT and self:Clip1() <= self:GetStatL("Primary.ClipSize") and (not self:GetStatL("Primary.DisableChambering")) and (not self:GetStatL("LoopedReload")) then self:ResetFirstDeploy() if sp then self:CallOnClient("ResetFirstDeploy", "") end end local success, tanim, ttype = self:ChooseHolsterAnim() if IsFirstTimePredicted() then self:SetSwapTarget(target) end self:ScheduleStatus(TFA.Enum.STATUS_HOLSTER, success and self:GetActivityLength(tanim, false, ttype) or (self:GetStatL("ProceduralHolsterTime") / self:GetAnimationRate(ACT_VM_HOLSTER))) return false elseif stat == TFA.Enum.STATUS_HOLSTER_READY or stat == TFA.Enum.STATUS_HOLSTER_FINAL then self:ResetViewModelModifications() return true end end function SWEP:FinishHolster() local self2 = self:GetTable() self:CleanParticles() local v2 = hook.Run("TFA_Holster", self) if self:GetOwner():IsNPC() then return end if v2 ~= nil then return v2 end if SERVER then local ent = self:GetSwapTarget() self:Holster(ent) if IsValid(ent) and ent:IsWeapon() then self:GetOwner():SelectWeapon(ent:GetClass()) if ent.IsTFAWeapon then ent:ApplyViewModelModifications() ent:CallOnClient("ApplyViewModelModifications") end self2.OwnerViewModel = nil end end end --[[ Function Name: OnRemove Syntax: self:OnRemove() Notes: Resets bone mods and cleans up. Returns: Nil. Purpose: Standard SWEP Function ]] function SWEP:OnRemove() local self2 = self:GetTable() if self2.CleanParticles then self2.CleanParticles(self) end if self2.ResetViewModelModifications then self2.ResetViewModelModifications(self) end return hook.Run("TFA_OnRemove", self) end --[[ Function Name: OnDrop Syntax: self:OnDrop() Notes: Resets bone mods and cleans up. Returns: Nil. Purpose: Standard SWEP Function ]] function SWEP:OnDrop() local self2 = self:GetTable() if self2.CleanParticles then self2.CleanParticles(self) end -- if self2.ResetViewModelModifications then -- self:ResetViewModelModifications() -- end return hook.Run("TFA_OnDrop", self) end function SWEP:OwnerChanged() -- TODO: sometimes not called after switching weapon ??? if not IsValid(self:GetOwner()) and self.ResetViewModelModifications then self:ResetViewModelModifications() end if SERVER then if self.IsNPCOwned and (not IsValid(self:GetOwner()) or not self:GetOwner():IsNPC()) then self:SetClip1(self:GetMaxClip1()) self:SetClip2(self:GetMaxClip2()) end end end --[[ Function Name: Think Syntax: self:Think() Returns: Nothing. Notes: This is blank. Purpose: Standard SWEP Function ]] function SWEP:Think() local self2 = self:GetTable() self2.CalculateRatios(self) if self:GetOwner():IsNPC() and SERVER then if self2.ThinkNPC then self2.ThinkNPC(self) end self2.Think2(self, false) end stat = self2.GetStatus(self) if (not sp or SERVER) and not self:GetFirstDeployEvent() then self2.ProcessEvents(self, sp or IsFirstTimePredicted()) end -- backward compatibility self2.AnimCycle = self:GetAnimCycle() if (not sp or SERVER) and ct > self:GetNextIdleAnim() and (TFA.Enum.ReadyStatus[stat] or (stat == TFA.Enum.STATUS_SHOOTING and TFA.Enum.ShootLoopingStatus[self:GetShootStatus()])) then self:ChooseIdleAnim() end self2.ProcessLoopFire(self) end function SWEP:PlayerThink(plyv, is_working_out_prediction_errors) if not self:NullifyOIV() then return end self:Think2(is_working_out_prediction_errors) end local sv_cheats = GetConVar("sv_cheats") local host_timescale = GetConVar("host_timescale") local function Clamp(a, b, c) if a < b then return b end if a > c then return c end return a end local Lerp = Lerp function SWEP:ShouldPlaySafetyAnim() if self:IsSafety() then return not self.SprintProgressUnpredicted2 or self.SprintProgressUnpredicted2 < 0.3 end if not TFA.FriendlyEncounter then return false end return not self:GetIronSights() and (self:GetLastGunFire() + 1 < CurTime()) and (not self.SprintProgressUnpredicted2 or self.SprintProgressUnpredicted2 < 0.3) end function SWEP:PlayerThinkCL(plyv) local self2 = self:GetTable() if not self:NullifyOIV() then return end self:SmokePCFLighting() if sp then self:Think2(false) end local ft = RealFrameTime() * game.GetTimeScale() * (sv_cheats:GetBool() and host_timescale:GetFloat() or 1) if self2.GetStatL(self, "BlowbackEnabled") then if not self2.Blowback_PistolMode or self:Clip1() == -1 or self:Clip1() > 0.1 or self2.Blowback_PistolMode_Disabled[self:GetLastActivity()] or self2.Blowback_PistolMode_Disabled[self:GetLastSequence()] or self2.Blowback_PistolMode_Disabled[self:GetLastSequenceString()] then self2.BlowbackCurrent = l_mathApproach(self2.BlowbackCurrent, 0, self2.BlowbackCurrent * ft * 15) end self2.BlowbackCurrentRoot = l_mathApproach(self2.BlowbackCurrentRoot, 0, self2.BlowbackCurrentRoot * ft * 15) end local is = self2.GetIronSights(self) local spr = self2.GetSprinting(self) local walk = self2.GetWalking(self) local status = self2.GetStatus(self) local ist = is and 1 or 0 local ist2 = TFA.Enum.ReloadStatus[self:GetStatus()] and ist * .25 or ist local reloadBlendMult, reloadBlendMult2 = 1, 1 if not self:GetStatL("LoopedReload") and (status == TFA.Enum.STATUS_RELOADING or status == TFA.Enum.STATUS_RELOADING_WAIT) and self2.ReloadAnimationEnd and self2.ReloadAnimationStart then local time = l_CT() local progress = Clamp((time - self2.ReloadAnimationStart) / (self2.ReloadAnimationEnd - self2.ReloadAnimationStart), 0, 1) reloadBlendMult = TFA.Cubic(math.max( Clamp(progress - 0.7, 0, 0.3) / 0.3, Clamp(0.1 - progress, 0, 0.1) / 0.1 )) reloadBlendMult2 = (1 + reloadBlendMult) / 2 elseif TFA.Enum.ReloadStatus[status] then reloadBlendMult = 0 reloadBlendMult2 = 0.5 end local fidgetBlendMult = 1 if status == TFA.Enum.STATUS_FIDGET then local progress = self:GetStatusProgress(true) fidgetBlendMult = TFA.Cubic(math.max( Clamp(progress - 0.8, 0, 0.2) / 0.2, Clamp(0.1 - progress, 0, 0.1) / 0.1 )) end local sprt = spr and reloadBlendMult or 0 local sprt2 = spr and (fidgetBlendMult * reloadBlendMult) or 0 local sprt3 = spr and reloadBlendMult2 or 0 local walkt = walk and 1 or 0 local IronSightsPosition = self2.GetStatL(self, "IronSightsPosition", self2.SightsPos) local IronSightsAngle = self2.GetStatL(self, "IronSightsAngle", self2.SightsAng) if IronSightsPosition then self2.IronSightsPositionCurrent = self2.IronSightsPositionCurrent or Vector(IronSightsPosition) self2.IronSightsAngleCurrent = self2.IronSightsAngleCurrent or Vector(IronSightsAngle) self2.IronSightsPositionCurrent.x = Lerp(ft * 11, self2.IronSightsPositionCurrent.x, IronSightsPosition.x) self2.IronSightsPositionCurrent.y = Lerp(ft * 11, self2.IronSightsPositionCurrent.y, IronSightsPosition.y) self2.IronSightsPositionCurrent.z = Lerp(ft * 11, self2.IronSightsPositionCurrent.z, IronSightsPosition.z) self2.IronSightsAngleCurrent.x = Lerp(ft * 11, self2.IronSightsAngleCurrent.x, self2.IronSightsAngleCurrent.x - math.AngleDifference(self2.IronSightsAngleCurrent.x, IronSightsAngle.x)) self2.IronSightsAngleCurrent.y = Lerp(ft * 11, self2.IronSightsAngleCurrent.y, self2.IronSightsAngleCurrent.y - math.AngleDifference(self2.IronSightsAngleCurrent.y, IronSightsAngle.y)) self2.IronSightsAngleCurrent.z = Lerp(ft * 11, self2.IronSightsAngleCurrent.z, self2.IronSightsAngleCurrent.z - math.AngleDifference(self2.IronSightsAngleCurrent.z, IronSightsAngle.z)) end local adstransitionspeed = is and (12.5 / (self:GetStatL("IronSightTime") / 0.3)) or (spr or walk) and 7.5 or 12.5 local ply = self:GetOwner() local velocity = self2.LastUnpredictedVelocity or ply:GetVelocity() local jr_targ = math.min(math.abs(velocity.z) / 500, 1) self2.JumpRatioUnpredicted = l_mathApproach((self2.JumpRatioUnpredicted or 0), jr_targ, (jr_targ - (self2.JumpRatioUnpredicted or 0)) * ft * 20) self2.CrouchingRatioUnpredicted = l_mathApproach((self2.CrouchingRatioUnpredicted or 0), ((ply:Crouching() or self2.KeyDown(self, IN_DUCK)) and ply:OnGround() and not ply:InVehicle()) and 1 or 0, ft / self2.ToCrouchTime) self2.IronSightsProgressUnpredicted = l_mathApproach(self2.IronSightsProgressUnpredicted or 0, ist, (ist - (self2.IronSightsProgressUnpredicted or 0)) * ft * adstransitionspeed * 1.2) self2.IronSightsProgressUnpredicted2 = l_mathApproach(self2.IronSightsProgressUnpredicted2 or 0, ist, (ist - (self2.IronSightsProgressUnpredicted2 or 0)) * ft * adstransitionspeed * 0.4) self2.IronSightsProgressUnpredicted3 = l_mathApproach(self2.IronSightsProgressUnpredicted3 or 0, ist2, (ist2 - (self2.IronSightsProgressUnpredicted3 or 0)) * ft * adstransitionspeed * 0.7) self2.SprintProgressUnpredicted = l_mathApproach(self2.SprintProgressUnpredicted or 0, sprt, (sprt - (self2.SprintProgressUnpredicted or 0)) * ft * adstransitionspeed) self2.SprintProgressUnpredicted2 = l_mathApproach(self2.SprintProgressUnpredicted2 or 0, sprt2, (sprt2 - (self2.SprintProgressUnpredicted2 or 0)) * ft * adstransitionspeed) self2.SprintProgressUnpredicted3 = l_mathApproach(self2.SprintProgressUnpredicted3 or 0, sprt3, (sprt3 - (self2.SprintProgressUnpredicted3 or 0)) * ft * adstransitionspeed) if is and not self2.VM_IronPositionScore then self2.VM_IronPositionScore = Clamp(self2.GetStatL(self, "ViewModelPosition"):Distance(self2.IronSightsPositionCurrent or self2.GetStatL(self, "IronSightsPosition", self2.GetStat(self, "SightsPos", vector_origin))) / 7, 0, 1) elseif not is and self2.VM_IronPositionScore and self2.IronSightsProgressUnpredicted2 <= 0.08 then self2.VM_IronPositionScore = nil end if self2.IronSightsProgressUnpredicted2 >= 0.8 and not self2.VM_IsScopedIn then self2.VM_IsScopedIn = true --elseif self2.IronSightsProgressUnpredicted2 <= 0.1 and self2.VM_IsScopedIn then elseif self2.IronSightsProgressUnpredicted2 <= 0.15 then self2.VM_IsScopedIn = false end local customizingTarget = self:GetCustomizing() and 1 or 0 self2.CustomizingProgressUnpredicted = l_mathApproach((self2.CustomizingProgressUnpredicted or 0), customizingTarget, (customizingTarget - (self2.CustomizingProgressUnpredicted or 0)) * ft * 5) self2.WalkProgressUnpredicted = l_mathApproach((self2.WalkProgressUnpredicted or 0), walkt, (walkt - (self2.WalkProgressUnpredicted or 0)) * ft * adstransitionspeed) if status ~= TFA.Enum.STATUS_FIREMODE or not self:GetIsCyclingSafety() then local safetyTarget = self:ShouldPlaySafetyAnim() and (fidgetBlendMult * reloadBlendMult) or 0 self2.SafetyProgressUnpredicted = l_mathApproach(self2.SafetyProgressUnpredicted or 0, safetyTarget, (safetyTarget - (self2.SafetyProgressUnpredicted or 0)) * ft * adstransitionspeed * 0.7) elseif status == TFA.Enum.STATUS_FIREMODE and self:GetIsCyclingSafety() then if not self:ShouldPlaySafetyAnim() then local safetyTarget = 0 if self:GetSafetyCycleAnimated() then self2.SafetyProgressUnpredicted = l_mathApproach(self2.SafetyProgressUnpredicted or 0, safetyTarget, (safetyTarget - (self2.SafetyProgressUnpredicted or 0)) * ft * adstransitionspeed * 1.1) else self2.SafetyProgressUnpredicted = l_mathApproach(self2.SafetyProgressUnpredicted or 0, safetyTarget, (safetyTarget - (self2.SafetyProgressUnpredicted or 0)) * ft * adstransitionspeed) end else local safetyTarget = fidgetBlendMult * reloadBlendMult if not self:GetSafetyCycleAnimated() then self2.SafetyProgressUnpredicted = l_mathApproach(self2.SafetyProgressUnpredicted or 0, safetyTarget, (safetyTarget - (self2.SafetyProgressUnpredicted or 0)) * ft * adstransitionspeed * 0.7) end end end end local UnPredictedCurTime = UnPredictedCurTime --[[ Function Name: Think2 Syntax: self:Think2(). Called from Think. Returns: Nothing. Notes: Essential for calling other important functions. Purpose: Standard SWEP Function ]] function SWEP:Think2(is_working_out_prediction_errors) local self2 = self:GetTable() ct = l_CT() if not is_working_out_prediction_errors then if CLIENT then self2.CurTimePredictionAdvance = ct - UnPredictedCurTime() end if self2.LuaShellRequestTime > 0 and ct > self2.LuaShellRequestTime then self2.LuaShellRequestTime = -1 self2.MakeShell(self) end if not self2.HasInitialized then self:Initialize() end if not self2.HasDetectedValidAnimations then self2.CacheAnimations(self) self2.ChooseDrawAnim(self) end self2.InitAttachments(self) self2.ProcessBodygroups(self) self2.ProcessHoldType(self) self2.ReloadCV(self) self2.IronSightSounds(self) self2.ProcessLoopSound(self) end self2.ProcessFireMode(self) if (not sp or SERVER) and self:GetFirstDeployEvent() then self2.ProcessEvents(self, sp or not is_working_out_prediction_errors) end --if is_working_out_prediction_errors then return end if not sp or SERVER then self2.IronSights(self) end self2.ProcessStatus(self) end SWEP.IronSightsReloadEnabled = false SWEP.IronSightsReloadLock = true function SWEP:IronSights() local self2 = self:GetTable() local owent = self:GetOwner() if not IsValid(owent) then return end ct = l_CT() stat = self:GetStatus() local issprinting = self:GetSprinting() local iswalking = self:GetWalking() local issighting = self:GetIronSightsRaw() local isplayer = owent:IsPlayer() local old_iron_sights_final = self:GetIronSightsOldFinal() if TFA.Enum.ReloadStatus[stat] and self2.GetStatL(self, "IronSightsReloadLock") then issighting = old_iron_sights_final end if issighting and isplayer and owent:InVehicle() and not owent:GetAllowWeaponsInVehicle() then issighting = false self:SetIronSightsRaw(false) end -- self:SetLastSightsStatusCached(false) local userstatus = issighting if issprinting then issighting = false end if issighting and not TFA.Enum.IronStatus[stat] and (not self:GetStatL("IronSightsReloadEnabled") or not TFA.Enum.ReloadStatus[stat]) then issighting = false end if issighting and self:IsSafety() then issighting = false end if stat == TFA.Enum.STATUS_FIREMODE and self:GetIsCyclingSafety() then issighting = false end if self2.GetStatL(self, "BoltAction") or self2.GetStatL(self, "BoltAction_Forced") then if stat == TFA.Enum.STATUS_SHOOTING then if not self2.LastBoltShoot then self2.LastBoltShoot = l_CT() end if l_CT() > self2.LastBoltShoot + self2.BoltTimerOffset then issighting = false end elseif (stat == TFA.Enum.STATUS_IDLE and self:GetReloadLoopCancel(true)) or stat == TFA.Enum.STATUS_PUMP then issighting = false else self2.LastBoltShoot = nil end end if old_iron_sights_final ~= issighting and self2.Sights_Mode == TFA.Enum.LOCOMOTION_LUA then -- and stat == TFA.Enum.STATUS_IDLE then self:SetNextIdleAnim(-1) end local smi = (self2.Sights_Mode == TFA.Enum.LOCOMOTION_HYBRID or self2.Sights_Mode == TFA.Enum.LOCOMOTION_ANI) and old_iron_sights_final ~= issighting local spi = (self2.Sprint_Mode == TFA.Enum.LOCOMOTION_HYBRID or self2.Sprint_Mode == TFA.Enum.LOCOMOTION_ANI) and self2.sprinting_updated local wmi = (self2.Walk_Mode == TFA.Enum.LOCOMOTION_HYBRID or self2.Walk_Mode == TFA.Enum.LOCOMOTION_ANI) and self2.walking_updated local cmi = (self2.Customize_Mode == TFA.Enum.LOCOMOTION_HYBRID or self2.Customize_Mode == TFA.Enum.LOCOMOTION_ANI) and self:GetCustomizeUpdated() self:SetCustomizeUpdated(false) if (smi or spi or wmi or cmi) and (self:GetStatus() == TFA.Enum.STATUS_IDLE or (self:GetStatus() == TFA.Enum.STATUS_SHOOTING and self:CanInterruptShooting())) and not self:GetReloadLoopCancel() then local toggle_is = old_iron_sights_final ~= issighting if issighting and self:GetSprinting() then toggle_is = true end local success, _ = self:Locomote(toggle_is and (self2.Sights_Mode ~= TFA.Enum.LOCOMOTION_LUA), issighting, spi, issprinting, wmi, iswalking, cmi, self:GetCustomizing()) if not success and (toggle_is and smi or spi or wmi or cmi) then self:SetNextIdleAnim(-1) end end self:SetIronSightsOldFinal(issighting) return userstatus, issighting end SWEP.is_sndcache_old = false function SWEP:IronSightSounds() local self2 = self:GetTable() local is = self:GetIronSights() if SERVER or IsFirstTimePredicted() then if is ~= self2.is_sndcache_old and hook.Run("TFA_IronSightSounds", self) == nil then if is then self:EmitSound(self:GetStatL("Secondary.IronSightsInSound", "TFA.IronIn")) else self:EmitSound(self:GetStatL("Secondary.IronSightsOutSound", "TFA.IronOut")) end end self2.is_sndcache_old = is end end local legacy_reloads_cv = GetConVar("sv_tfa_reloads_legacy") local dryfire_cvar = GetConVar("sv_tfa_allow_dryfire") SWEP.Primary.Sound_DryFire = Sound("Weapon_Pistol.Empty2") -- dryfire sound, played only once SWEP.Primary.Sound_DrySafety = Sound("Weapon_AR2.Empty2") -- safety click sound SWEP.Primary.Sound_Blocked = Sound("Weapon_AR2.Empty") -- underwater click sound SWEP.Primary.Sound_Jammed = Sound("Default.ClipEmpty_Rifle") -- jammed click sound SWEP.Primary.SoundHint_Fire = true SWEP.Primary.SoundHint_DryFire = true local function Dryfire(self, self2, reload) if not dryfire_cvar:GetBool() and reload then self:Reload(true) end if self2.GetHasPlayedEmptyClick(self) then return end self2.SetHasPlayedEmptyClick(self, true) if SERVER and self:GetStatL("Primary.SoundHint_DryFire") then sound.EmitHint(SOUND_COMBAT, self:GetPos(), 500, 0.2, self:GetOwner()) end if self:GetOwner():IsNPC() or self:KeyPressed(IN_ATTACK) then local enabled, tanim, ttype = self:ChooseDryFireAnim() if enabled then self:SetNextPrimaryFire(l_CT() + self:GetStatL("Primary.DryFireDelay", self:GetActivityLength(tanim, true, ttype))) return end end if IsFirstTimePredicted() then self:EmitSound(self:GetStatL("Primary.Sound_DryFire")) end end function SWEP:CanPrimaryAttack() local self2 = self:GetTable() local v = hook.Run("TFA_PreCanPrimaryAttack", self) if v ~= nil then return v end stat = self:GetStatus() if not TFA.Enum.ReadyStatus[stat] and stat ~= TFA.Enum.STATUS_SHOOTING then if self:GetStatL("LoopedReload") and TFA.Enum.ReloadStatus[stat] then self:SetReloadLoopCancel(true) end return false end if self:IsSafety() then if IsFirstTimePredicted() then self:EmitSound(self:GetStatL("Primary.Sound_DrySafety")) if SERVER and self:GetStatL("Primary.SoundHint_DryFire") then sound.EmitHint(SOUND_COMBAT, self:GetPos(), 200, 0.2, self:GetOwner()) end end if l_CT() < self:GetLastSafetyShoot() + 0.2 then self:CycleSafety() -- self:SetNextPrimaryFire(l_CT() + 0.1) end self:SetLastSafetyShoot(l_CT() + 0.2) return end if self:GetSprintProgress() >= 0.1 and not self:GetStatL("AllowSprintAttack", false) then return false end if self:GetStatL("Primary.ClipSize") <= 0 and self:Ammo1() < self:GetStatL("Primary.AmmoConsumption") then Dryfire(self, self2) return false end if self:GetPrimaryClipSize(true) > 0 and self:Clip1() < self:GetStatL("Primary.AmmoConsumption") then Dryfire(self, self2, true) return false end if self2.GetStatL(self, "Primary.FiresUnderwater") == false and self:GetOwner():WaterLevel() >= 3 then self:SetNextPrimaryFire(l_CT() + 0.5) self:EmitSound(self:GetStatL("Primary.Sound_Blocked")) return false end self2.SetHasPlayedEmptyClick(self, false) if l_CT() < self:GetNextPrimaryFire() then return false end local v2 = hook.Run("TFA_CanPrimaryAttack", self) if v2 ~= nil then return v2 end if self:CheckJammed() then if IsFirstTimePredicted() then self:EmitSound(self:GetStatL("Primary.Sound_Jammed")) end local typev, tanim = self:ChooseAnimation("shoot1_empty") if typev ~= TFA.Enum.ANIMATION_SEQ then self:SendViewModelAnim(tanim) else self:SendViewModelSeq(tanim) end self:SetNextPrimaryFire(l_CT() + 1) return false end return true end function SWEP:EmitGunfireLoop() local self2 = self:GetTable() local tgtSound = self:GetStatL("Primary.LoopSound") if self:GetSilenced() then tgtSound = self:GetStatL("Primary.LoopSoundSilenced", tgtSound) end if (not sp and SERVER) or not self:IsFirstPerson() then tgtSound = self:GetSilenced() and self:GetStatL("Primary.LoopSoundSilenced_World", tgtSound) or self:GetStatL("Primary.LoopSound_World", tgtSound) end if self:GetNextLoopSoundCheck() < 0 or (l_CT() >= self:GetNextLoopSoundCheck() and self2.LastLoopSound ~= tgtSound) then if self2.LastLoopSound ~= tgtSound and self2.LastLoopSound ~= nil then self:StopSound(self2.LastLoopSound) end self2.LastLoopSound = tgtSound self2.GunfireLoopIFTPHack = true self:EmitSoundNet(tgtSound) end self:SetNextLoopSoundCheck(CurTime() + self:GetFireDelay()) end function SWEP:EmitGunfireSound(soundscript) self:EmitSoundNet(soundscript) end local sv_tfa_nearlyempty = GetConVar("sv_tfa_nearlyempty") SWEP.LowAmmoSoundThreshold = 0.33 function SWEP:EmitLowAmmoSound() if not sv_tfa_nearlyempty:GetBool() then return end local self2 = self:GetTable() if not self2.FireSoundAffectedByClipSize then return end local clip1, maxclip1 = self:Clip1(), self:GetMaxClip1() if clip1 <= 0 then return end local nextclip1 = clip1 - self:GetStatL("Primary.AmmoConsumption", 1) if self:GetStatL("IsAkimbo") then nextclip1 = nextclip1 - self:GetAnimCycle() end local mult = nextclip1 / maxclip1 if mult >= self2.LowAmmoSoundThreshold then return end local soundname = (nextclip1 <= 0) and self:GetStatL("LastAmmoSound", "") or self:GetStatL("LowAmmoSound", "") if soundname and soundname ~= "" then self2.GonnaAdjustVol = true self2.RequiredVolume = 1 - (mult / math.max(self2.LowAmmoSoundThreshold, 0.01)) self:EmitSound(soundname) end end function SWEP:TriggerAttack(tableName, clipID) local self2 = self:GetTable() local ply = self:GetOwner() local fnname = clipID == 2 and "Secondary" or "Primary" if TFA.Enum.ShootReadyStatus[self:GetShootStatus()] then self:SetShootStatus(TFA.Enum.SHOOT_IDLE) end if self2.CanBeSilenced and (ply.KeyDown and self:KeyDown(IN_USE)) and (SERVER or not sp) then local _, tanim = self:ChooseSilenceAnim(not self:GetSilenced()) self:ScheduleStatus(TFA.Enum.STATUS_SILENCER_TOGGLE, self:GetActivityLength(tanim, true)) return end self["SetNext" .. fnname .. "Fire"](self, self2["GetNextCorrected" .. fnname .. "Fire"](self, self2.GetFireDelay(self))) if self:GetMaxBurst() > 1 then self:SetBurstCount(math.max(1, self:GetBurstCount() + 1)) end if self:GetStatL("PumpAction") and self:GetReloadLoopCancel() then return end self:SetStatus(TFA.Enum.STATUS_SHOOTING, self["GetNext" .. fnname .. "Fire"](self)) self:ToggleAkimbo() self:IncreaseRecoilLUT() local ifp = IsFirstTimePredicted() local _, tanim = self:ChooseShootAnim(ifp) if not sp or not self:IsFirstPerson() then ply:SetAnimation(PLAYER_ATTACK1) end if SERVER and self:GetStatL(tableName .. ".SoundHint_Fire") then sound.EmitHint(bit.bor(SOUND_COMBAT, SOUND_CONTEXT_GUNFIRE), self:GetPos(), self:GetSilenced() and 500 or 1500, 0.2, self:GetOwner()) end if self:GetStatL(tableName .. ".Sound") and ifp and not (sp and CLIENT) then if ply:IsPlayer() and self:GetStatL(tableName .. ".LoopSound") and (not self:GetStatL(tableName .. ".LoopSoundAutoOnly", false) or self2.Primary_TFA.Automatic) then self:EmitGunfireLoop() else local tgtSound = self:GetStatL(tableName .. ".Sound") if self:GetSilenced() then tgtSound = self:GetStatL(tableName .. ".SilencedSound", tgtSound) end if (not sp and SERVER) or not self:IsFirstPerson() then tgtSound = self:GetSilenced() and self:GetStatL(tableName .. ".SilencedSound_World", tgtSound) or self:GetStatL(tableName .. ".Sound_World", tgtSound) end self:EmitGunfireSound(tgtSound) end self:EmitLowAmmoSound() end self2["Take" .. fnname .. "Ammo"](self, self:GetStatL(tableName .. ".AmmoConsumption")) if self["Clip" .. clipID](self) == 0 and self:GetStatL(tableName .. ".ClipSize") > 0 then self["SetNext" .. fnname .. "Fire"](self, math.max(self["GetNext" .. fnname .. "Fire"](self), l_CT() + (self:GetStatL(tableName .. ".DryFireDelay", self:GetActivityLength(tanim, true))))) end self:ShootBulletInformation() self:UpdateJamFactor() local _, CurrentRecoil = self:CalculateConeRecoil() self:Recoil(CurrentRecoil, ifp) -- shouldn't this be not required since recoil state is completely networked? if sp and SERVER then self:CallOnClient("Recoil", "") end if self:GetStatL(tableName .. ".MuzzleFlashEnabled", self:GetStatL("MuzzleFlashEnabled")) and (not self:IsFirstPerson() or not self:GetStatL(tableName .. ".AutoDetectMuzzleAttachment", self:GetStatL("AutoDetectMuzzleAttachment"))) then self:ShootEffectsCustom() end if self:GetStatL(tableName .. ".EjectionSmoke", self:GetStatL("EjectionSmoke")) and CLIENT and ply == LocalPlayer() and ifp and not self:GetStatL(tableName .. ".LuaShellEject", self:GetStatL("LuaShellEject")) then self:EjectionSmoke() end self:DoAmmoCheck(clipID) -- Condition self:GetStatus() == TFA.Enum.STATUS_SHOOTING is always true? if self:GetStatus() == TFA.Enum.STATUS_SHOOTING and self:GetStatL("PumpAction") then if self["Clip" .. clipID](self) == 0 and self:GetStatL("PumpAction.value_empty") then self:SetReloadLoopCancel(true) elseif (self:GetStatL(tableName .. ".ClipSize") < 0 or self["Clip" .. clipID](self) > 0) and self:GetStatL("PumpAction.value") then self:SetReloadLoopCancel(true) end end self:RollJamChance() end function SWEP:PrimaryAttack() local self2 = self:GetTable() local ply = self:GetOwner() if not IsValid(ply) then return end if not IsValid(self) then return end if ply:IsPlayer() and not self:VMIV() then return end if not self:CanPrimaryAttack() then return end self:PrePrimaryAttack() if hook.Run("TFA_PrimaryAttack", self) then return end self:TriggerAttack("Primary", 1) self:PostPrimaryAttack() hook.Run("TFA_PostPrimaryAttack", self) end function SWEP:PrePrimaryAttack() -- override end function SWEP:PostPrimaryAttack() -- override end function SWEP:CanSecondaryAttack() -- override end function SWEP:SecondaryAttack() self:PreSecondaryAttack() if hook.Run("TFA_SecondaryAttack", self) then return end if not self:GetStatL("Secondary.IronSightsEnabled", false) and self.AltAttack and self:GetOwner():IsPlayer() then self:AltAttack() self:PostSecondaryAttack() return end self:PostSecondaryAttack() end function SWEP:PreSecondaryAttack() -- override end function SWEP:PostSecondaryAttack() -- override end function SWEP:GetLegacyReloads() return legacy_reloads_cv:GetBool() end do local bit_band = bit.band function SWEP:KeyDown(keyIn) return bit_band(self:GetDownButtons(), keyIn) == keyIn end function SWEP:KeyPressed(keyIn) return bit_band(self:GetLastPressedButtons(), keyIn) == keyIn end end if SERVER and sp then util.AddNetworkString("tfa_reload_blending") elseif CLIENT and sp then net.Receive("tfa_reload_blending", function() local self = net.ReadEntity() if not IsValid(self) then return end self.ReloadAnimationStart = net.ReadDouble() self.ReloadAnimationEnd = net.ReadDouble() end) end function SWEP:Reload(released) local self2 = self:GetTable() self:PreReload(released) if hook.Run("TFA_PreReload", self, released) then return end local isplayer = self:GetOwner():IsPlayer() local vm = self:VMIV() if isplayer and not vm then return end if not self:IsJammed() then if self:Ammo1() <= 0 then return end if self:GetStatL("Primary.ClipSize") < 0 then return end end if not released and not self:GetLegacyReloads() then return end if self:GetLegacyReloads() and not dryfire_cvar:GetBool() and not self:KeyDown(IN_RELOAD) then return end if self:KeyDown(IN_USE) then return end stat = self:GetStatus() if self:GetStatL("PumpAction") and self:GetReloadLoopCancel() then if stat == TFA.Enum.STATUS_IDLE then self:DoPump() end elseif TFA.Enum.ReadyStatus[stat] or (stat == TFA.Enum.STATUS_SHOOTING and self:CanInterruptShooting()) or self:IsJammed() then if self:Clip1() < self:GetPrimaryClipSize() or self:IsJammed() then if hook.Run("TFA_Reload", self) then return end self:SetBurstCount(0) if self:GetStatL("LoopedReload") then local _, tanim, ttype = self:ChooseShotgunReloadAnim() if self:GetStatL("ShotgunStartAnimShell") then self:SetStatus(TFA.Enum.STATUS_RELOADING_LOOP_START_EMPTY) elseif self2.ShotgunEmptyAnim then local _, tg = self:ChooseAnimation("reload_empty") local action = tanim if type(tg) == "string" and tonumber(tanim) and tonumber(tanim) > 0 and isplayer then if ttype == TFA.Enum.ANIMATION_ACT then action = vm:GetSequenceName(vm:SelectWeightedSequenceSeeded(tanim, self:GetSeedIrradical())) else action = vm:GetSequenceName(tanim) end end if action == tg and self:GetStatL("ShotgunEmptyAnim_Shell") then self:SetStatus(TFA.Enum.STATUS_RELOADING_LOOP_START_EMPTY) else self:SetStatus(TFA.Enum.STATUS_RELOADING_LOOP_START) end else self:SetStatus(TFA.Enum.STATUS_RELOADING_LOOP_START) end self:SetStatusEnd(ct + self:GetActivityLength(tanim, true, ttype)) --self:SetNextPrimaryFire(ct + self:GetActivityLength( tanim, false ) ) else local _, tanim, ttype = self:ChooseReloadAnim() self:SetStatus(TFA.Enum.STATUS_RELOADING) if self:GetStatL("IsProceduralReloadBased") then self:SetStatusEnd(ct + self:GetStatL("ProceduralReloadTime")) else self:SetStatusEnd(ct + self:GetActivityLength(tanim, true, ttype)) self:SetNextPrimaryFire(ct + self:GetActivityLength(tanim, false, ttype)) end if CLIENT then self2.ReloadAnimationStart = ct self2.ReloadAnimationEnd = ct + self:GetActivityLength(tanim, false, ttype) elseif sp then net.Start("tfa_reload_blending", true) net.WriteEntity(self) net.WriteDouble(ct) net.WriteDouble(ct + self:GetActivityLength(tanim, false, ttype)) net.Broadcast() end end if not sp or not self:IsFirstPerson() then self:GetOwner():SetAnimation(PLAYER_RELOAD) end if self:GetStatL("Primary.ReloadSound") and IsFirstTimePredicted() then self:EmitSound(self:GetStatL("Primary.ReloadSound")) end self:SetNextPrimaryFire( -1 ) elseif released or self:KeyPressed(IN_RELOAD) then--if self:GetOwner():KeyPressed(IN_RELOAD) or not self:GetLegacyReloads() then self:CheckAmmo() end end self:PostReload(released) hook.Run("TFA_PostReload", self) end function SWEP:PreReload(released) -- override end function SWEP:PostReload(released) -- override end function SWEP:Reload2(released) local self2 = self:GetTable() local ply = self:GetOwner() local isplayer = ply:IsPlayer() local vm = self:VMIV() if isplayer and not vm then return end if self:Ammo2() <= 0 then return end if self:GetStatL("Secondary.ClipSize") < 0 then return end if not released and not self:GetLegacyReloads() then return end if self:GetLegacyReloads() and not dryfire_cvar:GetBool() and not self:KeyDown(IN_RELOAD) then return end if self:KeyDown(IN_USE) then return end stat = self:GetStatus() if self:GetStatL("PumpAction") and self:GetReloadLoopCancel() then if stat == TFA.Enum.STATUS_IDLE then self:DoPump() end elseif TFA.Enum.ReadyStatus[stat] or ( stat == TFA.Enum.STATUS_SHOOTING and self:CanInterruptShooting() ) then if self:Clip2() < self:GetSecondaryClipSize() then if self:GetStatL("LoopedReload") then local _, tanim, ttype = self:ChooseShotgunReloadAnim() if self2.ShotgunEmptyAnim then local _, tg = self:ChooseAnimation("reload_empty") local action = tanim if type(tg) == "string" and tonumber(tanim) and tonumber(tanim) > 0 and isplayer then if ttype == TFA.Enum.ANIMATION_ACT then action = vm:GetSequenceName(vm:SelectWeightedSequenceSeeded(tanim, self:GetSeedIrradical())) else action = vm:GetSequenceName(tanim) end end if action == tg and self:GetStatL("ShotgunEmptyAnim_Shell") then self:SetStatus(TFA.Enum.STATUS_RELOADING_LOOP_START_EMPTY) else self:SetStatus(TFA.Enum.STATUS_RELOADING_LOOP_START) end else self:SetStatus(TFA.Enum.STATUS_RELOADING_LOOP_START) end self:SetStatusEnd(ct + self:GetActivityLength(tanim, true, ttype)) --self:SetNextPrimaryFire(ct + self:GetActivityLength( tanim, false ) ) else local _, tanim, ttype = self:ChooseReloadAnim() self:SetStatus(TFA.Enum.STATUS_RELOADING) if self:GetStatL("IsProceduralReloadBased") then self:SetStatusEnd(ct + self:GetStatL("ProceduralReloadTime")) else self:SetStatusEnd(ct + self:GetActivityLength(tanim, true, ttype)) self:SetNextPrimaryFire(ct + self:GetActivityLength(tanim, false, ttype)) end if CLIENT then self2.ReloadAnimationStart = ct self2.ReloadAnimationEnd = ct + self:GetActivityLength(tanim, false, ttype) end end if not sp or not self:IsFirstPerson() then ply:SetAnimation(PLAYER_RELOAD) end if self:GetStatL("Secondary.ReloadSound") and IsFirstTimePredicted() then self:EmitSound(self:GetStatL("Secondary.ReloadSound")) end self:SetNextPrimaryFire( -1 ) elseif released or self:KeyPressed(IN_RELOAD) then--if ply:KeyPressed(IN_RELOAD) or not self:GetLegacyReloads() then self:CheckAmmo() end end end function SWEP:DoPump() if hook.Run("TFA_Pump", self) then return end local _, tanim, activityType = self:PlayAnimation(self:GetStatL("PumpAction")) self:ScheduleStatus(TFA.Enum.STATUS_PUMP, self:GetActivityLength(tanim, true, activityType)) self:SetNextPrimaryFire(l_CT() + self:GetActivityLength(tanim, false, activityType)) self:SetNextIdleAnim(math.max(self:GetNextIdleAnim(), l_CT() + self:GetActivityLength(tanim, false, activityType))) end function SWEP:LoadShell() if hook.Run("TFA_LoadShell", self) then return end local _, tanim, ttype = self:ChooseReloadAnim() if self:GetActivityLength(tanim,true) < self:GetActivityLength(tanim, false, ttype) then self:SetStatusEnd(ct + self:GetActivityLength(tanim, true, ttype)) else local sht = self:GetStatL("LoopedReloadInsertTime") if sht then sht = sht / self:GetAnimationRate(ACT_VM_RELOAD) end self:SetStatusEnd(ct + ( sht or self:GetActivityLength(tanim, true, ttype))) end return TFA.Enum.STATUS_RELOADING_LOOP end function SWEP:CompleteReload() if hook.Run("TFA_CompleteReload", self) then return end local maxclip = self:GetPrimaryClipSizeForReload(true) local curclip = self:Clip1() local amounttoreplace = math.min(maxclip - curclip, self:Ammo1()) self:TakePrimaryAmmo(amounttoreplace * -1) self:TakePrimaryAmmo(amounttoreplace, true) self:SetJammed(false) end function SWEP:CheckAmmo() if hook.Run("TFA_CheckAmmo", self) then return end local self2 = self:GetTable() if self2.GetIronSights(self) or self2.GetSprinting(self) then return end --if self2.NextInspectAnim == nil then -- self2.NextInspectAnim = -1 --end if self:GetOwner().GetInfoNum and self:GetOwner():GetInfoNum("cl_tfa_keys_inspect", 0) > 0 then return end if (self:GetActivityEnabled(ACT_VM_FIDGET) or self2.InspectionActions) and self:GetStatus() == TFA.Enum.STATUS_IDLE then--and CurTime() > self2.NextInspectAnim then local _, tanim, ttype = self:ChooseInspectAnim() self:ScheduleStatus(TFA.Enum.STATUS_FIDGET, self:GetActivityLength(tanim, false, ttype)) end end local cv_strip = GetConVar("sv_tfa_weapon_strip") function SWEP:DoAmmoCheck(clipID) if self:GetOwner():IsNPC() then return end if clipID == nil then clipID = 1 end local self2 = self:GetTable() if IsValid(self) and SERVER and cv_strip:GetBool() and self["Clip" .. clipID](self) == 0 and self["Ammo" .. clipID](self) == 0 then timer.Simple(.1, function() if SERVER and IsValid(self) and self:OwnerIsValid() then self:GetOwner():StripWeapon(self2.ClassName) end end) end end --[[ Function Name: AdjustMouseSensitivity Syntax: Should not normally be called. Returns: SWEP sensitivity multiplier. Purpose: Standard SWEP Function ]] local fovv local sensval local sensitivity_cvar, sensitivity_fov_cvar, sensitivity_speed_cvar if CLIENT then sensitivity_cvar = GetConVar("cl_tfa_scope_sensitivity") sensitivity_fov_cvar = GetConVar("cl_tfa_scope_sensitivity_autoscale") sensitivity_speed_cvar = GetConVar("sv_tfa_scope_gun_speed_scale") end function SWEP:AdjustMouseSensitivity() sensval = 1 if self:GetIronSights() then sensval = sensval * sensitivity_cvar:GetFloat() / 100 if sensitivity_fov_cvar:GetBool() then fovv = self:GetStatL("Secondary.OwnerFOV") or 70 sensval = sensval * TFA.CalculateSensitivtyScale( fovv, nil, 1 ) else sensval = sensval end if sensitivity_speed_cvar:GetFloat() then -- weapon heaviness sensval = sensval * self:GetStatL("AimingDownSightsSpeedMultiplier") end end sensval = sensval * l_Lerp(self:GetIronSightsProgress(), 1, self:GetStatL( "IronSightsSensitivity" ) ) return sensval end --[[ Function Name: TranslateFOV Syntax: Should not normally be called. Takes default FOV as parameter. Returns: New FOV. Purpose: Standard SWEP Function ]] function SWEP:TranslateFOV(fov) local self2 = self:GetTable() self2.LastTranslatedFOV = fov local retVal = hook.Run("TFA_PreTranslateFOV", self,fov) if retVal then return retVal end self:CorrectScopeFOV() local nfov = l_Lerp(self2.IronSightsProgressUnpredicted3 or self:GetIronSightsProgress(), fov, fov * math.min(self:GetStatL("Secondary.OwnerFOV") / 90, 1)) local ret = l_Lerp(self2.SprintProgressUnpredicted or self:GetSprintProgress(), nfov, nfov + self2.SprintFOVOffset) if self:OwnerIsValid() and not self2.IsMelee then local vpa = self:GetOwner():GetViewPunchAngles() ret = ret + math.abs(vpa.p) / 4 + math.abs(vpa.y) / 4 + math.abs(vpa.r) / 4 end ret = hook.Run("TFA_TranslateFOV", self,ret) or ret return ret end function SWEP:GetPrimaryAmmoType() return self:GetStatL("Primary.Ammo") or "" end function SWEP:ToggleInspect() if self:GetOwner():IsNPC() then return false end -- NPCs can't look at guns silly local self2 = self:GetTable() if (self:GetSprinting() or self:GetIronSights() or self:GetStatus() ~= TFA.Enum.STATUS_IDLE) and not self:GetCustomizing() then return end self:SetCustomizing(not self:GetCustomizing()) self2.Inspecting = self:GetCustomizing() self:SetCustomizeUpdated(true) --if self2.Inspecting then -- gui.EnableScreenClicker(true) --else -- gui.EnableScreenClicker(false) --end return self:GetCustomizing() end SWEP.ToggleCustomize = SWEP.ToggleInspect function SWEP:GetIsInspecting() return self:GetCustomizing() end function SWEP:CustomizingUpdated(_, old, new) if old ~= new and self._inspect_hack ~= new then self._inspect_hack = new if new then self:OnCustomizationOpen() else self:OnCustomizationClose() end end end function SWEP:OnCustomizationOpen() -- override -- example: --[[ if CLIENT then surface.PlaySound("ui/buttonclickrelease.wav") end ]] end function SWEP:OnCustomizationClose() -- override end function SWEP:EmitSoundNet(sound) if CLIENT or sp then if sp and not IsFirstTimePredicted() then return end self:EmitSound(sound) return end local filter = RecipientFilter() filter:AddPAS(self:GetPos()) if IsValid(self:GetOwner()) then filter:RemovePlayer(self:GetOwner()) end net.Start("tfaSoundEvent", true) net.WriteEntity(self) net.WriteString(sound) net.Send(filter) end function SWEP:CanBeJammed() return self.CanJam and self:GetMaxClip1() > 0 and sv_tfa_jamming:GetBool() end -- Use this to increase/decrease factor added based on ammunition/weather conditions/etc function SWEP:GrabJamFactorMult() return 1 -- override end function SWEP:UpdateJamFactor() local self2 = self:GetTable() if not self:CanBeJammed() then return self end self:SetJamFactor(math.min(100, self:GetJamFactor() + self2.JamFactor * sv_tfa_jamming_factor_inc:GetFloat() * self:GrabJamFactorMult())) return self end function SWEP:IsJammed() if not self:CanBeJammed() then return false end return self:GetJammed() end function SWEP:NotifyJam() local ply = self:GetOwner() if IsValid(ply) and ply:IsPlayer() and IsFirstTimePredicted() and (not ply._TFA_LastJamMessage or ply._TFA_LastJamMessage < RealTime()) then ply:PrintMessage(HUD_PRINTCENTER, "#tfa.msg.weaponjammed") ply._TFA_LastJamMessage = RealTime() + 4 end end function SWEP:CheckJammed() if not self:IsJammed() then return false end self:NotifyJam() return true end function SWEP:RollJamChance() if not self:CanBeJammed() then return false end if self:IsJammed() then return true end local chance = self:GetJamChance() local roll = util.SharedRandom('tfa_base_jam', math.max(0.002711997795105, math.pow(chance, 1.19)), 1, l_CT()) if roll <= chance * sv_tfa_jamming_mult:GetFloat() then self:SetJammed(true) if IsFirstTimePredicted() then self:NotifyJam() end return true end return false end function SWEP:GrabJamChanceMult() return 1 -- override end function SWEP:GetJamChance() -- you can safely override this with your own logic if you desire local self2 = self:GetTable() if not self:CanBeJammed() then return 0 end return self:GetJamFactor() * sv_tfa_jamming_factor:GetFloat() * (self2.JamChance / 100) * self:GrabJamChanceMult() end SWEP.FlashlightSoundToggleOn = Sound("HL2Player.FlashLightOn") SWEP.FlashlightSoundToggleOff = Sound("HL2Player.FlashLightOff") function SWEP:ToggleFlashlight(toState) if toState == nil then toState = not self:GetFlashlightEnabled() end self:SetFlashlightEnabled(toState) self:EmitSoundNet(self:GetStatL("FlashlightSoundToggle" .. (toState and "On" or "Off"))) end -- source engine save load function SWEP:OnRestore() self:BuildAttachmentCache() self:InitializeAnims() self:InitializeMaterialTable() self:IconFix() do -- attempt to restore attachments; weapons DO have owner so we don't need the precautions local OldFD = self.IsFirstDeploy self.IsFirstDeploy = true -- so extmag attachments don't unload the clip for attName, sel in pairs(self.AttachmentCache or {}) do if sel then local att = TFA.Attachments.Atts[attName] if att and att.Attach then att:Attach(self) end end end self.IsFirstDeploy = OldFD end end -- lua autorefresh / weapons.Register function SWEP:OnReloaded() -- queue to next game frame since gmod is a fucking idiot timer.Simple(0, function() if not self:IsValid() then return end local baseclassSelf = table.Copy(baseclass.Get(self:GetClass())) if not baseclassSelf then return end local self2 = self:GetTable() self2.Primary_TFA.RangeFalloffLUTBuilt = nil self2.Primary.RangeFalloffLUTBuilt = nil --TFA.MigrateStructure(self, baseclassSelf, self:GetClass(), true) --TFA.MigrateStructure(self, self2, self:GetClass(), true) if istable(baseclassSelf.Primary) then self2.Primary_TFA = table.Copy(baseclassSelf.Primary) TFA.UnfoldBaseClass(baseclassSelf.Primary) end if istable(baseclassSelf.Secondary) then self2.Secondary_TFA = table.Copy(baseclassSelf.Secondary) TFA.UnfoldBaseClass(baseclassSelf.Secondary) end self2.StatCache_Blacklist = baseclassSelf.StatCache_Blacklist TFA.UnfoldBaseClass(self2.StatCache_Blacklist) if self2.StatCache_Blacklist_Real then table.Merge(self2.StatCache_Blacklist, self2.StatCache_Blacklist_Real) end self2.StatCache_Blacklist_Real = patch_blacklist(self2.StatCache_Blacklist, self2.TFADataVersion) self2.event_table_warning = false self2.event_table_built = false self2.AutoDetectMuzzle(self) self2.AutoDetectDamage(self) self2.AutoDetectDamageType(self) self2.AutoDetectForce(self) self2.AutoDetectPenetrationPower(self) self2.AutoDetectKnockback(self) self2.AutoDetectSpread(self) self2.AutoDetectRange(self) self2.ClearStatCache(self) end) end function SWEP:ProcessLoopSound() if sp and not SERVER then return end if self:GetNextLoopSoundCheck() < 0 or ct < self:GetNextLoopSoundCheck() or self:GetStatus() == TFA.Enum.STATUS_SHOOTING then return end self:SetNextLoopSoundCheck(-1) local tgtSound = self:GetStatL("Primary.LoopSound") if self:GetSilenced() then tgtSound = self:GetStatL("Primary.LoopSoundSilenced", tgtSound) end if tgtSound then self:StopSoundNet(tgtSound) end if (not sp and SERVER) or not self:IsFirstPerson() then tgtSound = self:GetSilenced() and self:GetStatL("Primary.LoopSoundSilenced_World", tgtSound) or self:GetStatL("Primary.LoopSound_World", tgtSound) if tgtSound then self:StopSoundNet(tgtSound) end end tgtSound = self:GetStatL("Primary.LoopSoundTail") if self:GetSilenced() then tgtSound = self:GetStatL("Primary.LoopSoundTailSilenced", tgtSound) end if (not sp and SERVER) or not self:IsFirstPerson() then tgtSound = self:GetSilenced() and self:GetStatL("Primary.LoopSoundTailSilenced_World", tgtSound) or self:GetStatL("Primary.LoopSoundTail_World", tgtSound) end if tgtSound and (SERVER or self.GunfireLoopIFTPHack) then self:EmitSoundNet(tgtSound) self.GunfireLoopIFTPHack = false end end function SWEP:ProcessLoopFire() local self2 = self:GetTable() if sp and not IsFirstTimePredicted() then return end if (self:GetStatus() == TFA.Enum.STATUS_SHOOTING ) then if TFA.Enum.ShootLoopingStatus[self:GetShootStatus()] then self:SetShootStatus(TFA.Enum.SHOOT_LOOP) end else --not shooting if (not TFA.Enum.ShootReadyStatus[self:GetShootStatus()]) then if ( self:GetShootStatus() ~= TFA.Enum.SHOOT_CHECK ) then self:SetShootStatus(TFA.Enum.SHOOT_CHECK) --move to check first else --if we've checked for one more tick that we're not shooting self:SetShootStatus(TFA.Enum.SHOOT_IDLE) --move to check first if not ( self:GetSprinting() and self2.Sprint_Mode ~= TFA.Enum.LOCOMOTION_LUA ) then --assuming we don't need to transition into sprint self:PlayAnimation(self:GetStatL("ShootAnimation.out")) --exit end end end end end