175 lines
5.9 KiB
C#
175 lines
5.9 KiB
C#
using Sand.Core;
|
|
|
|
namespace Sand.ChunkPrototype;
|
|
|
|
public sealed partial class PrototypeSparseSandAdapter
|
|
{
|
|
private bool ApplyLocalReaction(int x, int y, PrototypeParticle particle, ref int seed)
|
|
{
|
|
Span<(int X, int Y)> neighbors = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)];
|
|
for (var i = 0; i < neighbors.Length; i++)
|
|
{
|
|
var (nx, ny) = neighbors[i];
|
|
if (!TryGetParticle(nx, ny, out var neighbor))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (particle.HasFlag(PrototypeParticleFlags.WaterLike) && neighbor.HydrateTargetTypeId != 0 && TryResolveProfile(neighbor.HydrateTargetTypeId, out var hydrated))
|
|
{
|
|
ReplaceParticle(nx, ny, hydrated);
|
|
RemoveParticle(x, y);
|
|
return true;
|
|
}
|
|
|
|
if (particle.HasFlag(PrototypeParticleFlags.FireLike) && neighbor.HasFlag(PrototypeParticleFlags.WaterLike))
|
|
{
|
|
RemoveParticle(x, y);
|
|
if (neighbor.EvaporateTypeId != 0 && TryResolveProfile(neighbor.EvaporateTypeId, out var steam))
|
|
{
|
|
ReplaceParticle(nx, ny, steam);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
if (particle.HasFlag(PrototypeParticleFlags.HotSource) && neighbor.HasFlag(PrototypeParticleFlags.WaterLike))
|
|
{
|
|
if (particle.SolidifyTypeId != 0 && TryResolveProfile(particle.SolidifyTypeId, out var solidifiedSelf))
|
|
{
|
|
ReplaceParticle(x, y, solidifiedSelf);
|
|
}
|
|
|
|
if (neighbor.EvaporateTypeId != 0 && TryResolveProfile(neighbor.EvaporateTypeId, out var vaporizedNeighbor))
|
|
{
|
|
ReplaceParticle(nx, ny, vaporizedNeighbor);
|
|
}
|
|
else
|
|
{
|
|
RemoveParticle(nx, ny);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
if (particle.HasFlag(PrototypeParticleFlags.Acidic) &&
|
|
!neighbor.IsStatic &&
|
|
!neighbor.HasFlag(PrototypeParticleFlags.Acidic) &&
|
|
NextChance(ref seed) <= 0.08f)
|
|
{
|
|
RemoveParticle(nx, ny);
|
|
if (NextChance(ref seed) <= 0.18f)
|
|
{
|
|
RemoveParticle(x, y);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void ApplyPhaseTransition(int x, int y, ref PrototypeParticle particle)
|
|
{
|
|
var localTemperature = GetTemperatureAt(x, y);
|
|
var localPressure = GetPressureLoad(x, y);
|
|
var fieldForce = GetFieldForceMagnitude(x, y);
|
|
if (fieldForce > 0f)
|
|
{
|
|
localPressure += fieldForce * 0.2f;
|
|
}
|
|
|
|
var cellAge = GetCellAgeAt(x, y);
|
|
if (particle.PhaseTransitionHysteresis > 0f && cellAge < particle.PhaseTransitionHysteresis)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (particle.EvaporateTypeId != 0 &&
|
|
localTemperature >= particle.EvaporateTemperature &&
|
|
TryResolveProfile(particle.EvaporateTypeId, out var evaporated))
|
|
{
|
|
ReplaceParticle(x, y, evaporated);
|
|
particle = evaporated;
|
|
return;
|
|
}
|
|
|
|
if (particle.MeltTypeId != 0 &&
|
|
localTemperature >= particle.MeltTemperature &&
|
|
TryResolveProfile(particle.MeltTypeId, out var melted))
|
|
{
|
|
ReplaceParticle(x, y, melted);
|
|
particle = melted;
|
|
return;
|
|
}
|
|
|
|
if (particle.FreezeTypeId != 0 &&
|
|
localTemperature <= particle.FreezeTemperature &&
|
|
TryResolveProfile(particle.FreezeTypeId, out var frozen))
|
|
{
|
|
ReplaceParticle(x, y, frozen);
|
|
particle = frozen;
|
|
return;
|
|
}
|
|
|
|
if (particle.SolidifyTypeId != 0 &&
|
|
(localTemperature <= particle.SolidifyTemperature ||
|
|
(particle.MotionType == PrototypeParticleType.Steam && localPressure >= MathF.Max(0.9f, particle.PressureThreshold * 0.35f))) &&
|
|
TryResolveProfile(particle.SolidifyTypeId, out var condensed))
|
|
{
|
|
ReplaceParticle(x, y, condensed);
|
|
if (TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
page.SetTemperature(localX, localY, MathF.Max(condensed.InitialTemperature, MathF.Min(localTemperature, 95f)));
|
|
}
|
|
|
|
particle = condensed;
|
|
}
|
|
}
|
|
|
|
private float GetCellAgeAt(int x, int y)
|
|
{
|
|
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
return 0f;
|
|
}
|
|
|
|
return page.GetCellAge(localX, localY);
|
|
}
|
|
|
|
private bool HasPotentialReactiveNeighbor(int x, int y, PrototypeParticle particle)
|
|
{
|
|
Span<(int X, int Y)> neighbors = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)];
|
|
for (var i = 0; i < neighbors.Length; i++)
|
|
{
|
|
var (nx, ny) = neighbors[i];
|
|
if (!TryGetParticle(nx, ny, out var neighbor))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (particle.HasFlag(PrototypeParticleFlags.WaterLike) && neighbor.HydrateTargetTypeId != 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (particle.HydrateTargetTypeId != 0 && neighbor.HasFlag(PrototypeParticleFlags.WaterLike))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if ((particle.HasFlag(PrototypeParticleFlags.FireLike) || particle.HasFlag(PrototypeParticleFlags.HotSource)) && neighbor.HasFlag(PrototypeParticleFlags.WaterLike))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (particle.HasFlag(PrototypeParticleFlags.Acidic) && !neighbor.IsStatic && !neighbor.HasFlag(PrototypeParticleFlags.Acidic))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|