Emissions/ConchplexBurstEmission.cs
using Sandbox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using static Sandbox.PhysicsContact;
namespace ConchplexEmitters;
/// <summary>
/// Defines parameters for how to emit a particle, and when to emit it
/// </summary>
public class ConchplexBurstEmission
{
/// <summary>
/// Delay - what delay time to start bursting
/// </summary>
[Property, Group("Emitter"), KeyProperty]
public float BurstDelay { get; set; } = 0f;
/// <summary>
/// Ammount - how many to emit
/// </summary>
[Property, Group("Emitter"), KeyProperty]
[Range(0f, 1000f), Step(0.01f)]
public float BurstAmmount { get; set; } = 10f;
/// <summary>
/// Duration - Timespan to evenly emit over
/// </summary>
[Property, Group("Emitter"), KeyProperty]
public float BurstDuration { get; set; } = 0f;
/// <summary>
/// Probability - how likely it is to trigger 0 - never, 1 - always
/// </summary>
[Property, Group("Emitter"), KeyProperty]
[Range(0f, 1f), Step(0.01f)]
public float Probability { get; set; } = 1f;
/// <summary>
/// Cycles - how many times to try burst during a loop, 0 = infinite
/// </summary>
[Property, Group("Emitter"), KeyProperty]
public int Cycles { get; set; } = 0;
[Hide] private float timeSinceBurst = 0f;
[Hide] private float carryOver = 0f;
[Hide] private int totalEmitted = 0;
[Hide] private bool burstPending;
[Hide] private bool probablityChecked;
[Hide] private bool probablityPassed;
[Hide] private float burstDelta;
[Hide] private int cyclesDone = 0;
// DISTANCE EMISSION
public bool TryEmit(ParticleEffect target, ConchplexEmitter emitter, float time)
{
if (!burstPending || !probablityPassed) return false;
if (time - BurstDelay < 0) return false;
if (cyclesDone >= Cycles && Cycles! < 0) return false;
if(!probablityChecked)
{
probablityChecked = true;
if (Game.Random.Float() > Probability)
{
probablityPassed = false;
burstPending = false;
return false;
}
}
var enmitted = false;
// Burst has started, start counting down the burst time
burstDelta = ( timeSinceBurst + (time - BurstDelay)) - timeSinceBurst;
timeSinceBurst += time - BurstDelay;
// figure out how many to emit
float emissionRate = (BurstDuration > 0) ? BurstAmmount / BurstDuration : 0;
float particlesThisStep = emissionRate * burstDelta + carryOver - totalEmitted;
carryOver = particlesThisStep - (int)particlesThisStep;
// Burst time has ended, force ammount to emit, to whatever ammount remains
if (time - BurstDelay >= BurstDuration || BurstDuration <= 0)
{
particlesThisStep = BurstAmmount - totalEmitted;
burstPending = false;
enmitted = true;
}
// emit particles specified this step
for (int i = 0; i < (int)particlesThisStep; i++)
{
if (target.IsFull) break;
totalEmitted++;
emitter.EmitParticle(target);
}
cyclesDone++;
return enmitted;
}
public bool TryEmit(ParticleEffect target, ConchplexEmitter[] emitter, float time)
{
if (!burstPending || !probablityPassed) return false;
if (time - BurstDelay < 0) return false;
if (cyclesDone >= Cycles && Cycles! < 0) return false;
if (!probablityChecked)
{
probablityChecked = true;
if (Game.Random.Float() > Probability)
{
probablityPassed = false;
burstPending = false;
return false;
}
}
var enmitted = false;
// Burst has started, start counting down the burst time
burstDelta = (timeSinceBurst + (time - BurstDelay)) - timeSinceBurst;
timeSinceBurst += time - BurstDelay;
// figure out how many to emit
float emissionRate = (BurstDuration > 0) ? BurstAmmount / BurstDuration : 0;
float particlesThisStep = emissionRate * burstDelta + carryOver - totalEmitted;
carryOver = particlesThisStep - (int)particlesThisStep;
// Burst time has ended, force ammount to emit, to whatever ammount remains
if (time - BurstDelay >= BurstDuration || BurstDuration <= 0)
{
particlesThisStep = BurstAmmount - totalEmitted;
burstPending = false;
enmitted = true;
}
// emit particles specified this step
for (int i = 0; i < (int)particlesThisStep; i++)
{
if (target.IsFull) break;
var randomEmitter = emitter[Game.Random.Int(0, emitter.Length - 1)];
totalEmitted++;
randomEmitter.EmitParticle(target);
}
cyclesDone++;
return enmitted;
}
public bool IsActive() { return burstPending; }
public void ResetEmission()
{
burstPending = true;
probablityChecked = false;
probablityPassed = true;
timeSinceBurst = 0f;
carryOver = 0f;
totalEmitted = 0;
}
}