--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] -- Copyright (c) 2018-2020 TFA Base Devs -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and associated documentation files (the "Software"), to deal -- in the Software without restriction, including without limitation the rights -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- The above copyright notice and this permission notice shall be included in all -- copies or substantial portions of the Software. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. local fx, sp = nil, game.SinglePlayer() local shelltype function SWEP:PCFTracer(bul, hitpos, ovrride) if bul.PCFTracer then self:UpdateMuzzleAttachment() local mzp = self:GetMuzzlePos() if bul.PenetrationCount > 0 and not ovrride then return end --Taken care of with the pen effect if (CLIENT or game.SinglePlayer()) and self.Scoped and self:IsCurrentlyScoped() and self:IsFirstPerson() then TFA.ParticleTracer(bul.PCFTracer, self:GetOwner():GetShootPos() - self:GetOwner():EyeAngles():Up() * 5, hitpos, false, 0, -1) else local vent = self if (CLIENT or game.SinglePlayer()) and self:IsFirstPerson() then vent = self.OwnerViewModel end if sp and not self:IsFirstPerson() then TFA.ParticleTracer(bul.PCFTracer, self:GetOwner():GetShootPos() + self:GetOwner():GetAimVector() * 32, hitpos, false) else TFA.ParticleTracer(bul.PCFTracer, mzp.Pos, hitpos, false, vent, self.MuzzleAttachmentRaw or 1) end end end end function SWEP:EventShell() if SERVER and self.processing_events and sp then return end if SERVER then net.Start("tfaBaseShellSV", true) net.WriteEntity(self) if self:GetOwner():IsPlayer() then if sp then net.Broadcast() else net.SendOmit(self:GetOwner()) end else net.SendPVS(self:GetPos()) end return end self:MakeShellBridge() end function SWEP:MakeShellBridge(ifp) if ifp == false then return end if self.LuaShellEjectDelay > 0 then self.LuaShellRequestTime = CurTime() + self.LuaShellEjectDelay / self:GetAnimationRate(ACT_VM_PRIMARYATTACK) else self:MakeShell() end end SWEP.ShellEffectOverride = nil -- ??? SWEP.ShellEjectionQueue = 0 function SWEP:GetShellAttachmentID(ent, isVM) local raw = self:GetStatL("ShellAttachmentRaw") local israw = false local attid if raw and ent:GetAttachment(raw) then attid = raw israw = true else attid = ent:LookupAttachment(self:GetStatL("ShellAttachment")) end if self:GetStatL("IsAkimbo") and not israw then return 3 + self:GetAnimCycle() end if attid and attid <= 0 then attid = 2 end attid = math.Clamp(attid and attid or 2, 1, 127) return attid end function SWEP:GetShellEjectPosition(ent, isVM) local attid = self:GetShellAttachmentID(ent, isVM) local angpos = ent:GetAttachment(attid) if angpos then return angpos.Pos, angpos.Ang, attid end end function SWEP:MakeShell(eject_now) if not self:IsValid() then return end -- what if self.current_event_iftp == false then return end local retVal = hook.Run("TFA_MakeShell", self) if retVal ~= nil then return retVal end if self:GetStatL("ShellEffectOverride") then shelltype = self:GetStatL("ShellEffectOverride") elseif TFA.GetLegacyShellsEnabled() then shelltype = "tfa_shell_legacy" else shelltype = "tfa_shell" end local ent = self local isVM = false if self:IsFirstPerson() then if not eject_now and CLIENT then self.ShellEjectionQueue = self.ShellEjectionQueue + 1 return end ent = self.OwnerViewModel or self isVM = ent == self.OwnerViewModel end self:EjectionSmoke(true) if not isstring(shelltype) or shelltype == "" then return end -- allows to disable shells by setting override to "" - will shut up all rp fags if not IsValid(ent) then return end local pos, ang, attid = self:GetShellEjectPosition(ent, isVM) if not pos then return end fx = EffectData() fx:SetEntity(self) fx:SetAttachment(attid) fx:SetMagnitude(1) fx:SetScale(1) fx:SetOrigin(pos) fx:SetNormal(ang:Forward()) TFA.Effects.Create(shelltype, fx) end --[[ Function Name: CleanParticles Syntax: self:CleanParticles(). Returns: Nothing. Notes: Cleans up particles. Purpose: FX ]] -- function SWEP:CleanParticles() if not IsValid(self) then return end if self.StopParticles then self:StopParticles() end if self.StopParticleEmission then self:StopParticleEmission() end if not self:VMIV() then return end local vm = self.OwnerViewModel if IsValid(vm) then if vm.StopParticles then vm:StopParticles() end if vm.StopParticleEmission then vm:StopParticleEmission() end end end --[[ Function Name: EjectionSmoke Syntax: self:EjectionSmoke(). Returns: Nothing. Notes: Puff of smoke on shell attachment. Purpose: FX ]] -- function SWEP:EjectionSmoke(ovrr) local retVal = hook.Run("TFA_EjectionSmoke",self) if retVal ~= nil then return retVal end if TFA.GetEJSmokeEnabled() and (self:GetStatL("EjectionSmokeEnabled") or ovrr) then local vm = self:IsFirstPerson() and self.OwnerViewModel or self if IsValid(vm) then local att = vm:LookupAttachment(self:GetStatL("ShellAttachment")) if not att or att <= 0 then att = 2 end local oldatt = att att = self:GetStatL("ShellAttachmentRaw", att) local angpos = vm:GetAttachment(att) if not angpos then att = oldatt angpos = vm:GetAttachment(att) end if angpos then fx = EffectData() fx:SetEntity(self) fx:SetOrigin(angpos.Pos) fx:SetAttachment(att) fx:SetNormal(angpos.Ang:Forward()) TFA.Effects.Create("tfa_shelleject_smoke", fx) end end end end --[[ Function Name: ShootEffectsCustom Syntax: self:ShootEffectsCustom(). Returns: Nothing. Notes: Calls the proper muzzleflash, muzzle smoke, muzzle light code. Purpose: FX ]] -- function SWEP:MuzzleSmoke(spv) local retVal = hook.Run("TFA_MuzzleSmoke",self) if retVal ~= nil then return retVal end if self.SmokeParticle == nil then self.SmokeParticle = self.SmokeParticles[self.DefaultHoldType or self.HoldType] end if self:GetStatL("SmokeParticle") and self:GetStatL("SmokeParticle") ~= "" then self:UpdateMuzzleAttachment() local att = self:GetMuzzleAttachment() fx = EffectData() fx:SetOrigin(self:GetOwner():GetShootPos()) fx:SetNormal(self:GetOwner():EyeAngles():Forward()) fx:SetEntity(self) fx:SetAttachment(att) TFA.Effects.Create("tfa_muzzlesmoke", fx) end end function SWEP:MuzzleFlashCustom(spv) local retVal = hook.Run("TFA_MuzzleFlash",self) if retVal ~= nil then return retVal end local att = self:GetMuzzleAttachment() fx = EffectData() fx:SetOrigin(self:GetOwner():GetShootPos()) fx:SetNormal(self:GetOwner():EyeAngles():Forward()) fx:SetEntity(self) fx:SetAttachment(att) local mzsil = self:GetStatL("MuzzleFlashEffectSilenced") if (self:GetSilenced() and mzsil and mzsil ~= "") then TFA.Effects.Create(mzsil, fx) else TFA.Effects.Create(self:GetStatL("MuzzleFlashEffect", self.MuzzleFlashEffect or ""), fx) end end function SWEP:ShootEffectsCustom(ifp) if self.DoMuzzleFlash ~= nil then self.MuzzleFlashEnabled = self.DoMuzzleFlash self.DoMuzzleFlash = nil end if not self.MuzzleFlashEnabled then return end if self:IsFirstPerson() and not self:VMIV() then return end if not self:GetOwner().GetShootPos then return end ifp = ifp or IsFirstTimePredicted() if (SERVER and sp and self.ParticleMuzzleFlash) or (SERVER and not sp) then net.Start("tfa_base_muzzle_mp", true) net.WriteEntity(self) if sp or not self:GetOwner():IsPlayer() then net.SendPVS(self:GetPos()) else net.SendOmit(self:GetOwner()) end return end if (CLIENT and ifp and not sp) or (sp and SERVER) then self:UpdateMuzzleAttachment() self:MuzzleFlashCustom(sp) self:MuzzleSmoke(sp) end end --[[ Function Name: CanDustEffect Syntax: self:CanDustEffect( concise material name ). Returns: True/False Notes: Used for the impact effect. Should be used with GetMaterialConcise. Purpose: Utility ]] -- local DustEffects = { [MAT_DIRT] = true, [MAT_CONCRETE] = true, [MAT_PLASTIC] = true, [MAT_WOOD] = true } function SWEP:CanDustEffect(matv) if DustEffects[matv] then return true end return false end --[[ Function Name: CanSparkEffect Syntax: self:CanSparkEffect( concise material name ). Returns: True/False Notes: Used for the impact effect. Should be used with GetMaterialConcise. Purpose: Utility ]] -- local SparkEffects = { [MAT_METAL] = true, [MAT_GRATE] = true, [MAT_VENT] = true } function SWEP:CanSparkEffect(matv) if SparkEffects[matv] then return true end return false end -- Returns muzzle attachment position for HL2 tracers function SWEP:GetTracerOrigin(...) local att = self:GetMuzzleAttachment() local attpos = (self:IsFirstPerson() and self.OwnerViewModel or self):GetAttachment(att) if attpos and attpos.Pos then return attpos.Pos end end