126 lines
4.1 KiB
C#
126 lines
4.1 KiB
C#
using Sand.Core;
|
|
|
|
namespace Sand.ChunkPrototype;
|
|
|
|
public sealed partial class PrototypeSparseSandAdapter
|
|
{
|
|
private bool ApplyPressureResponse(int x, int y, PrototypeParticle particle)
|
|
{
|
|
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var localPressure = GetLocalPressure(x, y);
|
|
var threshold = particle.PressureThreshold;
|
|
if (threshold <= 0f)
|
|
{
|
|
threshold = particle.IsStatic
|
|
? 2.5f + particle.PressureResistance + particle.PressureTolerance
|
|
: 1.4f + (particle.PressureResistance * 0.35f) + particle.PressureTolerance;
|
|
}
|
|
|
|
if (localPressure < threshold)
|
|
{
|
|
var reducedDuration = MathF.Max(0f, page.GetPressureDuration(localX, localY) - 1f);
|
|
page.SetPressureDuration(localX, localY, reducedDuration);
|
|
var maxIntegrity = particle.Durability;
|
|
if (page.GetIntegrity(localX, localY) < maxIntegrity)
|
|
{
|
|
page.SetIntegrity(localX, localY, MathF.Min(maxIntegrity, page.GetIntegrity(localX, localY) + MathF.Max(0.2f, particle.Hardness * 0.1f)));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
var pressureDuration = page.GetPressureDuration(localX, localY) + 1f;
|
|
page.SetPressureDuration(localX, localY, pressureDuration);
|
|
var overload = MathF.Max(0f, localPressure - threshold);
|
|
var damageScale = 1f / MathF.Max(0.35f, 0.4f + particle.Hardness + (particle.PressureResistance * 0.1f));
|
|
page.SetIntegrity(localX, localY, page.GetIntegrity(localX, localY) - MathF.Max(0.15f, 0.45f + overload) * damageScale);
|
|
var requiredDuration = particle.PressureThresholdDuration > 0 ? particle.PressureThresholdDuration : (short)2;
|
|
if (pressureDuration < requiredDuration)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (particle.BrokenTypeId != 0 && TryResolveProfile(particle.BrokenTypeId, out var broken))
|
|
{
|
|
ReplaceParticle(x, y, broken);
|
|
return true;
|
|
}
|
|
|
|
if (particle.Flamability > 0f && GetTemperatureAt(x, y) >= MathF.Max(60f, particle.BurnTemperature * 0.5f))
|
|
{
|
|
page.SetBurning(localX, localY, 1);
|
|
page.SetBurnTime(localX, localY, MathF.Max(1f, particle.BurnDuration));
|
|
return false;
|
|
}
|
|
|
|
if (page.GetIntegrity(localX, localY) <= 0f)
|
|
{
|
|
if (!particle.IsStatic && particle.Kind == ParticleKind.Solid)
|
|
{
|
|
RemoveParticle(x, y);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private float GetLocalPressure(int x, int y) => MathF.Abs(SamplePressure(x, y));
|
|
|
|
private float GetPressureLoad(int x, int y)
|
|
{
|
|
var local = GetLocalPressure(x, y);
|
|
var neighborLoad =
|
|
(MathF.Abs(SamplePressure(x - 1, y)) +
|
|
MathF.Abs(SamplePressure(x + 1, y)) +
|
|
MathF.Abs(SamplePressure(x, y - 1)) +
|
|
MathF.Abs(SamplePressure(x, y + 1))) * 0.5f;
|
|
return Math.Max(local, neighborLoad);
|
|
}
|
|
|
|
private float GetFieldForceMagnitude(int x, int y)
|
|
{
|
|
var wind = GetWindAtCell(x, y);
|
|
var force = GetForceAtCell(x, y);
|
|
var totalX = wind.X + force.X;
|
|
var totalY = wind.Y + force.Y;
|
|
return MathF.Sqrt((totalX * totalX) + (totalY * totalY));
|
|
}
|
|
|
|
private float SamplePressure(int x, int y)
|
|
{
|
|
if (!TryGetFieldPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
return 0f;
|
|
}
|
|
|
|
return page.GetCell(localX, localY).Pressure;
|
|
}
|
|
|
|
private float GetPressureDurationAt(int x, int y)
|
|
{
|
|
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
return 0f;
|
|
}
|
|
|
|
return page.GetPressureDuration(localX, localY);
|
|
}
|
|
|
|
private float GetIntegrityAt(int x, int y)
|
|
{
|
|
if (!TryGetCellPage(x, y, out _, out var page, out var localX, out var localY))
|
|
{
|
|
return 0f;
|
|
}
|
|
|
|
return page.GetIntegrity(localX, localY);
|
|
}
|
|
}
|