187 lines
6.3 KiB
C#
187 lines
6.3 KiB
C#
using Sand.Core;
|
|
|
|
namespace Sand.ChunkPrototype;
|
|
|
|
public sealed partial class PrototypeSparseSandAdapter
|
|
{
|
|
private void TickCellAging(int x, int y, PrototypeParticle particle)
|
|
{
|
|
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
return;
|
|
}
|
|
|
|
page.SetCellAge(localX, localY, page.GetCellAge(localX, localY) + 1f);
|
|
if (page.GetIntegrity(localX, localY) < particle.Durability)
|
|
{
|
|
page.SetIntegrity(localX, localY, MathF.Min(particle.Durability, page.GetIntegrity(localX, localY) + MathF.Max(0.02f, particle.Hardness * 0.03f)));
|
|
}
|
|
}
|
|
|
|
private bool TickLifetime(int x, int y, ref PrototypeParticle particle)
|
|
{
|
|
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var lifetime = page.GetLifetime(localX, localY);
|
|
if (lifetime > 0f)
|
|
{
|
|
lifetime -= 1f;
|
|
page.SetLifetime(localX, localY, lifetime);
|
|
}
|
|
|
|
if (lifetime <= 0f && particle.DefaultLifetime > 0f)
|
|
{
|
|
if (particle.MotionType == PrototypeParticleType.Steam && particle.SolidifyTypeId != 0 && TryResolveProfile(particle.SolidifyTypeId, out var condensed))
|
|
{
|
|
var currentTemperature = GetTemperatureAt(x, y);
|
|
ReplaceParticle(x, y, condensed);
|
|
if (TryGetCellPage(x, y, out _, out var targetPage, out var targetLocalX, out var targetLocalY))
|
|
{
|
|
targetPage.SetTemperature(targetLocalX, targetLocalY, MathF.Max(condensed.InitialTemperature, MathF.Min(currentTemperature, 95f)));
|
|
}
|
|
|
|
particle = condensed;
|
|
return false;
|
|
}
|
|
|
|
RemoveParticle(x, y);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void AutoIgnite(int x, int y, PrototypeParticle particle)
|
|
{
|
|
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (page.GetBurning(localX, localY) == 0 &&
|
|
particle.BurnTemperature > 0f &&
|
|
GetTemperatureAt(x, y) >= particle.BurnTemperature &&
|
|
particle.Flamability > 0f)
|
|
{
|
|
page.SetBurning(localX, localY, 1);
|
|
page.SetBurnTime(localX, localY, MathF.Max(particle.BurnDuration, 1f));
|
|
}
|
|
}
|
|
|
|
private void ApplyRuntimeEmissionAndProduction(int x, int y, PrototypeParticle particle, ref int seed)
|
|
{
|
|
var isEffectEmitter =
|
|
particle.BehaviorKind is ParticleBehaviorKind.Fire or ParticleBehaviorKind.BurningWood or ParticleBehaviorKind.Ember or ParticleBehaviorKind.Plasma;
|
|
var emission = particle.HeatEmission;
|
|
if (particle.BehaviorKind == ParticleBehaviorKind.Fire && emission <= 0f)
|
|
{
|
|
emission = 24f;
|
|
}
|
|
else if (particle.BehaviorKind == ParticleBehaviorKind.Plasma && emission <= 0f)
|
|
{
|
|
emission = 80f;
|
|
}
|
|
else if (particle.BehaviorKind == ParticleBehaviorKind.Ember && emission <= 0f)
|
|
{
|
|
emission = 12f;
|
|
}
|
|
else if (particle.IsMolten && emission <= 0f)
|
|
{
|
|
emission = particle.TypeId != 0 ? 28f : 0f;
|
|
}
|
|
|
|
if (emission > 0f)
|
|
{
|
|
ApplyHeatEmission(x, y, emission);
|
|
}
|
|
|
|
if ((isEffectEmitter || IsBurningAt(x, y)) && particle.ProduceTypeId != 0 && NextChance(ref seed) <= 0.08f)
|
|
{
|
|
TrySpawnAtOffset(x, y, 0, -1, particle.ProduceTypeId);
|
|
}
|
|
|
|
if (particle.SmokeSpawnChance > 0f && isEffectEmitter && TryFindProfileById("smoke", out var smoke) && NextChance(ref seed) <= particle.SmokeSpawnChance)
|
|
{
|
|
TrySpawnAtOffset(x, y, 0, -1, smoke.TypeId);
|
|
}
|
|
|
|
if (particle.EmberSpawnChance > 0f && isEffectEmitter && TryFindProfileById("ember", out var ember) && NextChance(ref seed) <= particle.EmberSpawnChance)
|
|
{
|
|
TrySpawnAtOffset(x, y, 0, -1, ember.TypeId);
|
|
}
|
|
}
|
|
|
|
private bool TickBurning(int x, int y, ref PrototypeParticle particle)
|
|
{
|
|
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY) || page.GetBurning(localX, localY) == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
page.SetTemperature(localX, localY, page.GetTemperature(localX, localY) + 1.5f + (particle.HeatEmission * 0.02f));
|
|
page.SetBurnTime(localX, localY, page.GetBurnTime(localX, localY) - MathF.Max(0.05f, particle.BurnRate));
|
|
if (page.GetBurnTime(localX, localY) > 0f)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
RemoveParticle(x, y);
|
|
return true;
|
|
}
|
|
|
|
private bool TickSpecialBehavior(int x, int y, PrototypeParticle particle, ref int seed)
|
|
{
|
|
var temperature = GetTemperatureAt(x, y);
|
|
switch (particle.BehaviorKind)
|
|
{
|
|
case ParticleBehaviorKind.Fire:
|
|
if (temperature < 120f && NextChance(ref seed) <= 0.1f)
|
|
{
|
|
RemoveParticle(x, y);
|
|
return true;
|
|
}
|
|
break;
|
|
case ParticleBehaviorKind.Ember:
|
|
if (temperature < 60f && NextChance(ref seed) <= 0.1f)
|
|
{
|
|
RemoveParticle(x, y);
|
|
return true;
|
|
}
|
|
break;
|
|
case ParticleBehaviorKind.BurningWood:
|
|
if (particle.EmberSpawnChance > 0f && TryFindProfileById("ember", out var ember) && NextChance(ref seed) <= particle.EmberSpawnChance * 0.5f)
|
|
{
|
|
TrySpawnAtOffset(x, y, 0, -1, ember.TypeId);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private bool IsBurningAt(int x, int y)
|
|
{
|
|
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return page.GetBurning(localX, localY) != 0;
|
|
}
|
|
|
|
private bool TrySpawnAtOffset(int x, int y, int offsetX, int offsetY, ushort typeId)
|
|
{
|
|
var tx = x + offsetX;
|
|
var ty = y + offsetY;
|
|
if (!InBounds(tx, ty) || HasParticle(tx, ty) || !TryResolveProfile(typeId, out var particle))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return AddParticle(tx, ty, particle);
|
|
}
|
|
}
|