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); } }