Skip to content

Commit

Permalink
Merge pull request #453 from StrawWagen/gib-LOD
Browse files Browse the repository at this point in the history
Cheaper gibs/debris when FPS is low.
  • Loading branch information
marchc1 authored Jan 18, 2025
2 parents b2e58bd + 0aa857c commit fca5ac8
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 17 deletions.
1 change: 1 addition & 0 deletions lua/acf/core/globals.lua
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ elseif CLIENT then
CreateClientConVar("acf_legalhints", 1, true, true, "If enabled, ACF will throw a warning hint whenever an entity gets disabled.", 0, 1)
CreateClientConVar("acf_legalshame", 0, true, true, "If enabled, you will get a message in console from the server if someone else has an ACF entity get disabled, but only when the server has that logging enabled.", 0, 1)
CreateClientConVar("acf_debris", 1, true, false, "Toggles ACF Debris.", 0, 1)
CreateClientConVar("acf_debris_autolod", 1, true, false, "Automatically disables some effects on debris if FPS is low.", 0, 1)
CreateClientConVar("acf_debris_collision", 0, true, false, "Toggles debris collisions with other entities.", 0, 1)
CreateClientConVar("acf_debris_gibmultiplier", 1, true, false, "The amount of gibs spawned when created by ACF debris.", 0, 1)
CreateClientConVar("acf_debris_giblifetime", 60, true, false, "Defines lifetime in seconds of each debris gib.", 1, 300)
Expand Down
98 changes: 81 additions & 17 deletions lua/acf/damage/debris_cl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,21 @@ local ACF = ACF

local Effects = ACF.Utilities.Effects
local AllowDebris = GetConVar("acf_debris")
local AutoLod = GetConVar("acf_debris_autolod")
local CollideAll = GetConVar("acf_debris_collision")
local DebrisLife = GetConVar("acf_debris_lifetime")
local GibMult = GetConVar("acf_debris_gibmultiplier")
local GibLife = GetConVar("acf_debris_giblifetime")
local GibModel = "models/gibs/metal_gib%s.mdl"

local math = math

local AutoLod_TerribleFps = 15
local AutoLod_ReallyBadFps = 25
local AutoLod_LowFps = 35
local AutoLod_OkayFps = 40
local AutoLod_GoodFps = 45

local function Particle(Entity, Effect)
return CreateParticleSystem(Entity, Effect, PATTACH_ABSORIGIN_FOLLOW)
end
Expand Down Expand Up @@ -56,33 +65,61 @@ local function Ignite(Entity, Lifetime, IsGib)
end
end

local function CreateDebris(Model, Position, Angles, Material, Color, Normal, Power, ShouldIgnite)
local function CreateDebris(Model, Position, Angles, Material, Color, Normal, Power, ShouldIgnite, AutoLOD)
-- TODO: This fixes a crashing bug, but the underlying issue that Model can sometimes be blank ("") isn't fixed yet
if not util.IsValidModel(Model) then return end

local Lifetime = DebrisLife:GetFloat() * math.Rand(0.5, 1)
local DoCollideAll = CollideAll:GetBool()
local DoParticles = true
local AllowIgnite = ShouldIgnite
local AllowSmoke = true

if AutoLOD then
local FPS = 1 / RealFrameTime()
if FPS < AutoLod_ReallyBadFps then
if FPS < math.random(0, AutoLod_TerribleFps) then return end -- their game is basically crashing, dont add to the problem
DoParticles = false
DoCollideAll = false
Lifetime = Lifetime * math.Rand(0.01, 0.1)
elseif FPS < AutoLod_LowFps then
AllowIgnite = AllowIgnite and math.random(0, 100) < 15
AllowSmoke = math.random(0, 100) < 25
DoCollideAll = false
Lifetime = Lifetime * math.Rand(0.1, 0.25)
elseif FPS < AutoLod_OkayFps then
AllowIgnite = AllowIgnite and math.random(0, 100) < 25
AllowSmoke = math.random(0, 100) < 50
DoCollideAll = CollideAll and math.random(0, 100) < 50
Lifetime = Lifetime * math.Rand(0.25, 0.5)
elseif FPS <= AutoLod_GoodFps then
Lifetime = Lifetime * 0.5
end
end

local Debris = ents.CreateClientProp(Model)

if not IsValid(Debris) then return end

local Lifetime = DebrisLife:GetFloat() * math.Rand(0.5, 1)

Debris:SetPos(Position)
Debris:SetAngles(Angles)
Debris:SetMaterial(Material)
Debris:SetColor(Color)

if not CollideAll:GetBool() then
Debris:SetCollisionGroup(COLLISION_GROUP_WORLD)
if not DoCollideAll then
Debris:SetCollisionGroup(COLLISION_GROUP_WORLD) -- disable collisions
end

Debris:Spawn()

Debris.EmberParticle = Particle(Debris, "embers_medium_01")
if DoParticles then
Debris.EmberParticle = Particle(Debris, "embers_medium_01")

if ShouldIgnite and math.Rand(0, 0.5) < ACF.DebrisIgniteChance then
Ignite(Debris, Lifetime)
else
Debris.SmokeParticle = Particle(Debris, "smoke_exhaust_01a")
if AllowIgnite and math.Rand(0, 0.5) < ACF.DebrisIgniteChance then
Ignite(Debris, Lifetime)
elseif AllowSmoke then
Debris.SmokeParticle = Particle(Debris, "smoke_exhaust_01a")
end
end

local PhysObj = Debris:GetPhysicsObject()
Expand All @@ -98,12 +135,31 @@ local function CreateDebris(Model, Position, Angles, Material, Color, Normal, Po
return Debris
end

local function CreateGib(Position, Angles, Material, Color, Normal, Power, Min, Max)
local function CreateGib(Position, Angles, Material, Color, Normal, Power, Min, Max, AutoLOD)
local DoParticles = true
local AllowIgnite = true
local Lifetime = GibLife:GetFloat() * math.Rand(0.5, 1)
if AutoLOD then
local FPS = 1 / RealFrameTime()
if FPS < AutoLod_ReallyBadFps then
if FPS < math.random(0, AutoLod_ReallyBadFps) then return end
DoParticles = false
Lifetime = Lifetime * math.Rand(0.01, 0.1)
elseif FPS < AutoLod_LowFps then
DoParticles = math.random(0, 100) < 50
AllowIgnite = math.random(0, 100) < 15
Lifetime = Lifetime * math.Rand(0.1, 0.25)
elseif FPS < AutoLod_OkayFps then
AllowIgnite = math.random(0, 100) < 50
Lifetime = Lifetime * math.Rand(0.25, 0.5)
elseif FPS <= AutoLod_GoodFps then
Lifetime = Lifetime * 0.5
end
end
local Gib = ents.CreateClientProp(GibModel:format(math.random(1, 5)))

if not IsValid(Gib) then return end

local Lifetime = GibLife:GetFloat() * math.Rand(0.5, 1)
local Offset = ACF.RandomVector(Min, Max)

Offset:Rotate(Angles)
Expand All @@ -115,10 +171,12 @@ local function CreateGib(Position, Angles, Material, Color, Normal, Power, Min,
Gib:SetColor(Color)
Gib:Spawn()

Gib.SmokeParticle = Particle(Gib, "smoke_gib_01")
if DoParticles then
Gib.SmokeParticle = Particle(Gib, "smoke_gib_01")

if math.random() < ACF.DebrisIgniteChance then
Ignite(Gib, Lifetime, true)
if AllowIgnite and math.random() < ACF.DebrisIgniteChance then
Ignite(Gib, Lifetime, true)
end
end

local PhysObj = Gib:GetPhysicsObject()
Expand All @@ -138,7 +196,9 @@ function ACF.CreateDebris(Model, Position, Angles, Material, Color, Normal, Powe
if not AllowDebris:GetBool() then return end
if not Model then return end

local Debris = CreateDebris(Model, Position, Angles, Material, Color, Normal, Power, CanGib, Ignite)
local AutoLOD = AutoLod:GetBool()

local Debris = CreateDebris(Model, Position, Angles, Material, Color, Normal, Power, CanGib, Ignite, AutoLOD)

if IsValid(Debris) then
local Multiplier = GibMult:GetFloat()
Expand All @@ -148,9 +208,13 @@ function ACF.CreateDebris(Model, Position, Angles, Material, Color, Normal, Powe

if CanGib and Multiplier > 0 then
local GibCount = math.Clamp(Radius * 0.1, 1, math.max(10 * Multiplier, 1))
if AutoLOD then
local FPS = 1 / RealFrameTime()
GibCount = math.Clamp(GibCount, 0, FPS * 0.5)
end

for _ = 1, GibCount do
if not CreateGib(Position, Angles, Material, Color, Normal, Power, Min, Max) then
if not CreateGib(Position, Angles, Material, Color, Normal, Power, Min, Max, AutoLOD) then
break
end
end
Expand Down
3 changes: 3 additions & 0 deletions lua/acf/menu/items_cl/settings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ do -- Clientside settings
local Debris = Base:AddCheckBox("#acf.menu.settings.debris.clientside")
Debris:SetConVar("acf_debris")

local AutoLod = Base:AddCheckBox("#acf.menu.settings.debris.autolod")
AutoLod:SetConVar("acf_debris_autolod")

local Collisions = Base:AddCheckBox("#acf.menu.settings.debris.collision")
Collisions:SetConVar("acf_debris_collision")

Expand Down
2 changes: 2 additions & 0 deletions resource/localization/en/acf_menu_settings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ acf.menu.settings.debris=Debris

acf.menu.settings.debris.clientside=Allow creation of clientside debris.

acf.menu.settings.debris.autolod=Cheaper debris when FPS is low.

acf.menu.settings.debris.collision=Allow debris to collide with entities.
acf.menu.settings.debris.collision_desc=Disabling this can prevent certain types of spam-induced lag and crashes.

Expand Down

0 comments on commit fca5ac8

Please sign in to comment.