diff --git a/lua/acf/ballistics/ballistics_sv.lua b/lua/acf/ballistics/ballistics_sv.lua index 7a14701e5..61bdfd9c6 100644 --- a/lua/acf/ballistics/ballistics_sv.lua +++ b/lua/acf/ballistics/ballistics_sv.lua @@ -2,6 +2,7 @@ local ACF = ACF local Ballistics = ACF.Ballistics local Damage = ACF.Damage local Clock = ACF.Utilities.Clock +local Effects = ACF.Utilities.Effects local Debug = ACF.Debug Ballistics.Bullets = Ballistics.Bullets or {} @@ -23,26 +24,17 @@ local HookRun = hook.Run function Ballistics.BulletClient(Bullet, Type, Hit, HitPos) if Bullet.NoEffect then return end -- No clientside effect will be created for this bullet - local Effect = EffectData() - Effect:SetDamageType(Bullet.Index) - Effect:SetStart(Bullet.Flight * 0.1) - Effect:SetAttachment(Bullet.Hide and 0 or 1) - - if Type == "Update" then - if Hit > 0 then - Effect:SetOrigin(HitPos) - else - Effect:SetOrigin(Bullet.Pos) - end - - Effect:SetScale(Hit) - else - Effect:SetOrigin(Bullet.Pos) - Effect:SetEntIndex(Bullet.Crate) - Effect:SetScale(0) - end - - util.Effect("ACF_Bullet_Effect", Effect, true, true) + local IsUpdate = Type == "Update" + local EffectTable = { + DamageType = Bullet.Index, + Start = Bullet.Flight * 0.1, + Attachment = Bullet.Hide and 0 or 1, + Origin = (IsUpdate and Hit > 0) and HitPos or Bullet.Pos, + Scale = IsUpdate and Hit or 0, + EntIndex = not IsUpdate and Bullet.Crate or nil, + } + + Effects.CreateEffect("ACF_Bullet_Effect", EffectTable, true, true) end function Ballistics.RemoveBullet(Bullet) diff --git a/lua/acf/core/utilities/effects/effects_cl.lua b/lua/acf/core/utilities/effects/effects_cl.lua index a08704040..9190e0513 100644 --- a/lua/acf/core/utilities/effects/effects_cl.lua +++ b/lua/acf/core/utilities/effects/effects_cl.lua @@ -1,12 +1,13 @@ local ACF = ACF -local Refills = {} - -ACF.Utilities.Effects.Refills = Refills +local Effects = ACF.Utilities.Effects do -- Resupply effect (applies to ammo and fuel) local render = render local Distance = ACF.RefillDistance + local Refills = {} + Effects.Refills = Refills + local function DrawSpheres(bDrawingDepth, _, isDraw3DSkybox) if bDrawingDepth or isDraw3DSkybox then return end render.SetColorMaterial() diff --git a/lua/acf/core/utilities/effects/effects_sh.lua b/lua/acf/core/utilities/effects/effects_sh.lua new file mode 100644 index 000000000..5ffb4cc48 --- /dev/null +++ b/lua/acf/core/utilities/effects/effects_sh.lua @@ -0,0 +1,29 @@ +local ACF = ACF +local Effects = ACF.Utilities.Effects + +do + --- Creates effects based on util.Effect with ACF-specific functionality. + --- @param EffectName string The name of the effect to create + --- @param EffectTable table The table containing all of the parameters for the effect (case-sensitive) + --- @param AllowOverride? boolean Whether Lua-defined effects should override engine-defined effects + --- @param Filter? any Can be either a boolean to ignore the prediction filter or a CRecipientFilter + function Effects.CreateEffect(EffectName, EffectTable, AllowOverride, Filter) + if not EffectName or not EffectTable then return end + + local Effect = EffectData() + + local NewName, NewTable = hook.Run("ACF_PreCreateEffect", EffectName, EffectTable) + EffectName = NewName or EffectName + EffectTable = NewTable or EffectTable + + -- Set values for all possible valid CEffectData attributes present in EffectTable + for Name, Value in pairs(EffectTable) do + local EffectFunc = Effect["Set" .. Name] + if not EffectFunc then continue end + + EffectFunc(Effect, Value) + end + + util.Effect(EffectName, Effect, AllowOverride, Filter) + end +end \ No newline at end of file diff --git a/lua/acf/damage/damage_cl.lua b/lua/acf/damage/damage_cl.lua index bc1f57daa..4f2222712 100644 --- a/lua/acf/damage/damage_cl.lua +++ b/lua/acf/damage/damage_cl.lua @@ -98,6 +98,7 @@ do end do -- Debris Effects ------------------------ + local Effects = ACF.Utilities.Effects local AllowDebris = GetConVar("acf_debris") local CollideAll = GetConVar("acf_debris_collision") local DebrisLife = GetConVar("acf_debris_lifetime") @@ -252,10 +253,12 @@ do -- Debris Effects ------------------------ end end - local Effect = EffectData() - Effect:SetOrigin(Data.Position) -- TODO: Change this to the hit vector, but we need to redefine HitVec as HitNorm - Effect:SetScale(20) - util.Effect("cball_explode", Effect) + local EffectTable = { + Origin = Data.Position, -- TODO: Change this to the hit vector, but we need to redefine HitVec as HitNorm + Scale = 20, + } + + Effects.CreateEffect("cball_explode", EffectTable) end) game.AddParticles("particles/fire_01.pcf") diff --git a/lua/acf/damage/explosion_sh.lua b/lua/acf/damage/explosion_sh.lua index f9cc340c9..21dc6e086 100644 --- a/lua/acf/damage/explosion_sh.lua +++ b/lua/acf/damage/explosion_sh.lua @@ -1,8 +1,8 @@ -local math = math -local util = util -local ACF = ACF -local Damage = ACF.Damage -local Down = Vector(0, 0, -1) +local math = math +local ACF = ACF +local Damage = ACF.Damage +local Effects = ACF.Utilities.Effects +local Down = Vector(0, 0, -1) --- Returns the blast radius based on a given amount of filler mass -- Note: Scaling law found on the net, based on 1PSI overpressure from 1 kg of TNT at 15m @@ -21,10 +21,11 @@ end function Damage.explosionEffect(Position, Direction, Filler) local Radius = math.max(1, Damage.getBlastRadius(Filler)) - local Effect = EffectData() - Effect:SetOrigin(Position) - Effect:SetNormal(Direction or Down) - Effect:SetScale(Radius) + local EffectTable = { + Origin = Position, + Normal = Direction or Down, + Scale = Radius, + } - util.Effect("ACF_Explosion", Effect) + Effects.CreateEffect("ACF_Explosion", EffectTable) end diff --git a/lua/acf/entities/ammo_types/ap.lua b/lua/acf/entities/ammo_types/ap.lua index 9f6e18739..394bd73ec 100644 --- a/lua/acf/entities/ammo_types/ap.lua +++ b/lua/acf/entities/ammo_types/ap.lua @@ -171,6 +171,8 @@ if SERVER then Ballistics.RemoveBullet(Bullet) end else + local Effects = ACF.Utilities.Effects + ACF.RegisterAmmoDecal("AP", "damage/ap_pen", "damage/ap_rico") local DecalIndex = ACF.GetAmmoDecalIndex @@ -201,37 +203,40 @@ else end function Ammo:ImpactEffect(_, Bullet) - local Effect = EffectData() - Effect:SetOrigin(Bullet.SimPos) - Effect:SetNormal(Bullet.SimFlight:GetNormalized()) - Effect:SetRadius(Bullet.Caliber) - Effect:SetDamageType(DecalIndex(Bullet.AmmoType)) - - util.Effect("ACF_Impact", Effect) + local EffectTable = { + Origin = Bullet.SimPos, + Normal = Bullet.SimFlight:GetNormalized(), + Radius = Bullet.Caliber, + DamageType = DecalIndex(Bullet.AmmoType), + } + + Effects.CreateEffect("ACF_Impact", EffectTable) end function Ammo:PenetrationEffect(_, Bullet) - local Effect = EffectData() - Effect:SetOrigin(Bullet.SimPos) - Effect:SetNormal(Bullet.SimFlight:GetNormalized()) - Effect:SetScale(Bullet.SimFlight:Length()) - Effect:SetMagnitude(Bullet.RoundMass) - Effect:SetRadius(Bullet.Caliber) - Effect:SetDamageType(DecalIndex(Bullet.AmmoType)) - - util.Effect("ACF_Penetration", Effect) + local EffectTable = { + Origin = Bullet.SimPos, + Normal = Bullet.SimFlight:GetNormalized(), + Scale = Bullet.SimFlight:Length(), + Magnitude = Bullet.RoundMass, + Radius = Bullet.Caliber, + DamageType = DecalIndex(Bullet.AmmoType), + } + + Effects.CreateEffect("ACF_Penetration", EffectTable) end function Ammo:RicochetEffect(_, Bullet) - local Effect = EffectData() - Effect:SetOrigin(Bullet.SimPos) - Effect:SetNormal(Bullet.SimFlight:GetNormalized()) - Effect:SetScale(Bullet.SimFlight:Length()) - Effect:SetMagnitude(Bullet.RoundMass) - Effect:SetRadius(Bullet.Caliber) - Effect:SetDamageType(DecalIndex(Bullet.AmmoType)) - - util.Effect("ACF_Ricochet", Effect) + local EffectTable = { + Origin = Bullet.SimPos, + Normal = Bullet.SimFlight:GetNormalized(), + Scale = Bullet.SimFlight:Length(), + Magnitude = Bullet.RoundMass, + Radius = Bullet.Caliber, + DamageType = DecalIndex(Bullet.AmmoType), + } + + Effects.CreateEffect("ACF_Ricochet", EffectTable) end function Ammo:AddCrateDataTrackers(Trackers) diff --git a/lua/acf/entities/ammo_types/heat.lua b/lua/acf/entities/ammo_types/heat.lua index 4b5151c93..8eb8af20d 100644 --- a/lua/acf/entities/ammo_types/heat.lua +++ b/lua/acf/entities/ammo_types/heat.lua @@ -446,6 +446,7 @@ if SERVER then else ACF.RegisterAmmoDecal("HEAT", "damage/heat_pen", "damage/heat_rico", function(Caliber) return Caliber * 0.1667 end) local DecalIndex = ACF.GetAmmoDecalIndex + local Effects = ACF.Utilities.Effects function Ammo:ImpactEffect(Effect, Bullet) if not Bullet.Detonated then @@ -456,24 +457,21 @@ else end function Ammo:PenetrationEffect(Effect, Bullet) - if Bullet.Detonated then - local Data = EffectData() - Data:SetOrigin(Bullet.SimPos) - Data:SetNormal(Bullet.SimFlight:GetNormalized()) - Data:SetScale(Bullet.SimFlight:Length()) - Data:SetMagnitude(Bullet.RoundMass) - Data:SetRadius(Bullet.Caliber) - Data:SetDamageType(DecalIndex(Bullet.AmmoType)) - - util.Effect("ACF_Penetration", Data) - else - local Data = EffectData() - Data:SetOrigin(Bullet.SimPos) - Data:SetNormal(Bullet.SimFlight:GetNormalized()) - Data:SetRadius(math.max(Bullet.FillerMass ^ 0.33 * 8 * 39.37, 1)) - - util.Effect("ACF_HEAT_Explosion", Data) - + local Detonated = Bullet.Detonated + local EffectName = Detonated and "ACF_Penetration" or "ACF_HEAT_Explosion" + local Radius = Detonated and Bullet.Caliber or math.max(Bullet.FillerMass ^ 0.33 * 8 * 39.37, 1) + local EffectTable = { + Origin = Bullet.SimPos, + Normal = Bullet.SimFlight:GetNormalized(), + Radius = Radius, + Magnitude = Detonated and Bullet.RoundMass or nil, + Scale = Detonated and Bullet.SimFlight:Length() or nil, + DamageType = Detonated and DecalIndex(Bullet.AmmoType) or nil, + } + + Effects.CreateEffect(EffectName, EffectTable) + + if not Detonated then Bullet.Detonated = true Bullet.LimitVel = 999999 @@ -482,14 +480,16 @@ else end function Ammo:RicochetEffect(_, Bullet) - local Effect = EffectData() - Effect:SetOrigin(Bullet.SimPos) - Effect:SetNormal(Bullet.SimFlight:GetNormalized()) - Effect:SetScale(Bullet.SimFlight:Length()) - Effect:SetMagnitude(Bullet.RoundMass) - Effect:SetRadius(Bullet.Caliber) - Effect:SetDamageType(DecalIndex(Bullet.AmmoType)) - util.Effect("ACF_Ricochet", Effect) + local EffectTable = { + Origin = Bullet.SimPos, + Normal = Bullet.SimFlight:GetNormalized(), + Scale = Bullet.SimFlight:Length(), + Magnitude = Bullet.RoundMass, + Radius = Bullet.Caliber, + DamageType = DecalIndex(Bullet.AmmoType), + } + + Effects.CreateEffect("ACF_Ricochet", EffectTable) end function Ammo:AddAmmoControls(Base, ToolData, BulletData) diff --git a/lua/acf/entities/ammo_types/smoke.lua b/lua/acf/entities/ammo_types/smoke.lua index 38947a63b..5aba1937b 100644 --- a/lua/acf/entities/ammo_types/smoke.lua +++ b/lua/acf/entities/ammo_types/smoke.lua @@ -168,21 +168,24 @@ if SERVER then return false end else + local Effects = ACF.Utilities.Effects + ACF.RegisterAmmoDecal("SM", "damage/he_pen", "damage/he_rico") function Ammo:ImpactEffect(_, Bullet) local Crate = Bullet.Crate local Color = IsValid(Crate) and Crate:GetColor() or Color(255, 255, 255) - local Effect = EffectData() - Effect:SetOrigin(Bullet.SimPos) - Effect:SetNormal(Bullet.SimFlight:GetNormalized()) - Effect:SetScale(math.max(Bullet.FillerMass * 8 * 39.37, 0)) - Effect:SetMagnitude(math.max(Bullet.WPMass * 8 * 39.37, 0)) - Effect:SetStart(Vector(Color.r, Color.g, Color.b)) - Effect:SetRadius(Bullet.Caliber) + local EffectTable = { + Origin = Bullet.SimPos, + Normal = Bullet.SimFlight:GetNormalized(), + Scale = math.max(Bullet.FillerMass * 8 * 39.37, 0), + Magnitude = math.max(Bullet.WPMass * 8 * 39.37, 0), + Start = Vector(Color.r, Color.g, Color.b), + Radius = Bullet.Caliber, + } - util.Effect("ACF_Smoke", Effect) + Effects.CreateEffect("ACF_Smoke", EffectTable) end function Ammo:AddAmmoControls(Base, ToolData, BulletData) diff --git a/lua/effects/acf_heat_explosion.lua b/lua/effects/acf_heat_explosion.lua index 9714996db..5f8737dab 100644 --- a/lua/effects/acf_heat_explosion.lua +++ b/lua/effects/acf_heat_explosion.lua @@ -1,15 +1,18 @@ +local Effects = ACF.Utilities.Effects + function EFFECT:Init(Data) local Origin = Data:GetOrigin() local Normal = Data:GetNormal() local Radius = math.max(Data:GetRadius() * 0.02, 1) local Emitter = ParticleEmitter(Origin) - local Effect = EffectData() - Effect:SetOrigin(Origin) - Effect:SetNormal(Normal) - Effect:SetScale(Radius * 50) + local EffectTable = { + Origin = Origin, + Normal = Normal, + Scale = Radius * 50, + } - util.Effect("ACF_Explosion", Effect) + Effects.CreateEffect("ACF_Explosion", EffectTable) if not IsValid(Emitter) then return end diff --git a/lua/effects/acf_impact.lua b/lua/effects/acf_impact.lua index 560ea2a52..88ca6fd34 100644 --- a/lua/effects/acf_impact.lua +++ b/lua/effects/acf_impact.lua @@ -1,8 +1,9 @@ -local TraceData = { start = true, endpos = true } -local TraceLine = util.TraceLine +local TraceData = { start = true, endpos = true } +local TraceLine = util.TraceLine +local Effects = ACF.Utilities.Effects local ValidDecal = ACF.IsValidAmmoDecal -local GetDecal = ACF.GetRicochetDecal -local GetScale = ACF.GetDecalScale +local GetDecal = ACF.GetRicochetDecal +local GetScale = ACF.GetDecalScale function EFFECT:Init(Data) local Caliber = Data:GetRadius() or 0 @@ -19,12 +20,13 @@ function EFFECT:Init(Data) local Trace = TraceLine(TraceData) -- Placeholder - local Effect = EffectData() - Effect:SetStart(Origin) - Effect:SetNormal(Trace.HitNormal) - Effect:SetMagnitude(0) + local EffectTable = { + Start = Origin, + Normal = Trace.HitNormal, + Magnitude = 0, + } - util.Effect("ElectricSpark", Effect) + Effects.CreateEffect("ElectricSpark", EffectTable) if IsValid(Trace.Entity) or Trace.HitWorld then local DecalType = ValidDecal(Type) and Type or 1 diff --git a/lua/effects/acf_penetration.lua b/lua/effects/acf_penetration.lua index 9e22badba..0ec3a487e 100644 --- a/lua/effects/acf_penetration.lua +++ b/lua/effects/acf_penetration.lua @@ -4,6 +4,7 @@ local ValidDecal = ACF.IsValidAmmoDecal local GetDecal = ACF.GetPenetrationDecal local GetScale = ACF.GetDecalScale local Sounds = ACF.Utilities.Sounds +local Effects = ACF.Utilities.Effects local Sound = "acf_base/fx/penetration%s.mp3" local White = Color(255, 255, 255) @@ -43,13 +44,15 @@ function EFFECT:Init(Data) end function EFFECT:Metal(Emitter, Origin, Scale, HitNormal) - local Sparks = EffectData() - Sparks:SetOrigin(Origin) - Sparks:SetNormal(HitNormal) - Sparks:SetMagnitude(Scale) - Sparks:SetScale(Scale) - Sparks:SetRadius(Scale) - util.Effect("Sparks", Sparks) + local EffectTable = { + Origin = Origin, + Normal = HitNormal, + Magnitude = Scale, + Scale = Scale, + Radius = Scale, + } + + Effects.CreateEffect("Sparks", EffectTable) if not IsValid(Emitter) then return end @@ -97,13 +100,15 @@ function EFFECT:Metal(Emitter, Origin, Scale, HitNormal) end function EFFECT:Concrete(Emitter, Origin, Scale, HitNormal) - local Sparks = EffectData() - Sparks:SetOrigin(Origin) - Sparks:SetNormal(HitNormal) - Sparks:SetMagnitude(Scale) - Sparks:SetScale(Scale) - Sparks:SetRadius(Scale) - util.Effect("Sparks", Sparks) + local EffectTable = { + Origin = Origin, + Normal = HitNormal, + Magnitude = Scale, + Scale = Scale, + Radius = Scale, + } + + Effects.CreateEffect("Sparks", EffectTable) if not IsValid(Emitter) then return end diff --git a/lua/effects/acf_smoke.lua b/lua/effects/acf_smoke.lua index e5e90376a..90351fb95 100644 --- a/lua/effects/acf_smoke.lua +++ b/lua/effects/acf_smoke.lua @@ -1,5 +1,6 @@ local TraceData = { start = true, endpos = true, mask = true } local TraceLine = util.TraceLine +local Effects = ACF.Utilities.Effects local GetIndex = ACF.GetAmmoDecalIndex local GetDecal = ACF.GetRicochetDecal local White = Color(255, 255, 255) @@ -37,12 +38,13 @@ function EFFECT:Init(Data) util.DecalEx(GetDecal(Type), Impact.Entity, Impact.HitPos, Impact.HitNormal, White, Size, Size) end - local Effect = EffectData() - Effect:SetOrigin(Origin) - Effect:SetNormal(Normal) - Effect:SetRadius(Caliber) + local EffectTable = { + Origin = Origin, + Normal = Normal, + Radius = Caliber, + } - util.Effect("acf_impact", Effect) + Effects.CreateEffect("acf_impact", EffectTable) end if not IsValid(Emitter) then return end diff --git a/lua/entities/acf_gun/init.lua b/lua/entities/acf_gun/init.lua index 386564ec7..a3726dd5e 100644 --- a/lua/entities/acf_gun/init.lua +++ b/lua/entities/acf_gun/init.lua @@ -471,6 +471,7 @@ do -- Metamethods -------------------------------- end ----------------------------------------- do -- Shooting ------------------------------ + local Effects = Utilities.Effects local TraceRes = {} -- Output for traces local TraceData = { start = true, endpos = true, filter = true, mask = MASK_SOLID, output = TraceRes } @@ -595,21 +596,23 @@ do -- Metamethods -------------------------------- function ENT:MuzzleEffect() if not ACF.GunsCanSmoke then return end - local Effect = EffectData() - Effect:SetEntity(self) - Effect:SetScale(self.BulletData.PropMass) - Effect:SetMagnitude(self.ReloadTime) + local EffectTable = { + Entity = self, + Scale = self.BulletData.PropMass, + Magnitude = self.ReloadTime, + } - util.Effect("ACF_Muzzle_Flash", Effect, true, true) + Effects.CreateEffect("ACF_Muzzle_Flash", EffectTable, true, true) end function ENT:ReloadEffect(Time) - local Effect = EffectData() - Effect:SetEntity(self) - Effect:SetScale(0) - Effect:SetMagnitude(Time) + local EffectTable = { + Entity = self, + Scale = 0, + Magnitude = Time, + } - util.Effect("ACF_Muzzle_Flash", Effect, true, true) + Effects.CreateEffect("ACF_Muzzle_Flash", EffectTable, true, true) end function ENT:Recoil() diff --git a/lua/weapons/acf_torch/shared.lua b/lua/weapons/acf_torch/shared.lua index 903ada2ff..74d899526 100644 --- a/lua/weapons/acf_torch/shared.lua +++ b/lua/weapons/acf_torch/shared.lua @@ -4,6 +4,7 @@ AddCSLuaFile("shared.lua") local ACF = ACF local Clock = ACF.Utilities.Clock local Sounds = ACF.Utilities.Sounds +local Effects = ACF.Utilities.Effects local Network = ACF.Networking local Damage = ACF.Damage local Objects = Damage.Objects @@ -244,11 +245,13 @@ function SWEP:PrimaryAttack() Entity:SetHealth(Health) local AngPos = Owner:GetAttachment(4) - local Effect = EffectData() - Effect:SetOrigin(AngPos.Pos + Trace.Normal * 10) - Effect:SetNormal(Trace.Normal) - Effect:SetEntity(self) - util.Effect("thruster_ring", Effect, true, true) + local EffectTable = { + Origin = AngPos.Pos + Trace.Normal * 10, + Normal = Trace.Normal, + Entity = self, + } + + Effects.CreateEffect("thruster_ring", EffectTable, true, true) -- Sound ratelimiting local Time = CurTime() @@ -324,11 +327,13 @@ function SWEP:SecondaryAttack() damageInfo:SetDamagePosition(Trace.HitPos) Entity:TakeDamageInfo(damageInfo) - local effect = EffectData() - effect:SetOrigin(Trace.HitPos) - effect:SetNormal(Trace.Normal) - effect:SetEntity(self) - util.Effect("BloodImpact", effect, true, true) + local EffectTable = { + Origin = Trace.HitPos, + Normal = Trace.Normal, + Entity = self, + } + + Effects.CreateEffect("BloodImpact", EffectTable, true, true) else local DmgResult = self.DamageResult local DmgInfo = self.DamageInfo @@ -347,14 +352,15 @@ function SWEP:SecondaryAttack() if HitRes.Kill then ACF.APKill(Entity, Trace.Normal, 1, DmgInfo) else - local Effect = EffectData() - Effect:SetMagnitude(1) - Effect:SetRadius(1) - Effect:SetScale(1) - Effect:SetStart(HitPos) - Effect:SetOrigin(HitPos) - - util.Effect("Sparks", Effect, true, true) + local EffectTable = { + Magnitude = 1, + Radius = 1, + Scale = 1, + Start = HitPos, + Origin = HitPos, + } + + Effects.CreateEffect("Sparks", EffectTable, true, true) -- Sound ratelimiting local Time = CurTime()