public void TryAddPoint(int x, int y, int z, int axis, float currentPressure, bool isIncendiary, List <ProcessPoint> toProcess, SparseSpatialArray <bool> processed) { if (processed.Get(x, y, z)) { return; } int cellValue = m_subsystemTerrain.Terrain.GetCellValue(x, y, z); int num = Terrain.ExtractContents(cellValue); if (num != 0) { int num2 = (int)(MathUtils.Hash((uint)(x + 913 * y + 217546 * z)) % 100u); float num3 = MathUtils.Lerp(1f, 2f, (float)num2 / 100f); if (num2 % 8 == 0) { num3 *= 3f; } Block block = BlocksManager.Blocks[num]; float num4 = m_pressureByPoint.Get(x - 1, y, z) + m_pressureByPoint.Get(x + 1, y, z) + m_pressureByPoint.Get(x, y - 1, z) + m_pressureByPoint.Get(x, y + 1, z) + m_pressureByPoint.Get(x, y, z - 1) + m_pressureByPoint.Get(x, y, z + 1); float num5 = MathUtils.Max(block.ExplosionResilience * num3, 1f); float num6 = num4 / num5; if (num6 > 1f) { int newValue = Terrain.MakeBlockValue(0); m_subsystemTerrain.DestroyCell(0, x, y, z, newValue, noDrop: true, noParticleSystem: true); bool flag = false; float probability = (num6 > 5f) ? 0.95f : 0.75f; if (m_random.Bool(probability)) { flag = TryExplodeBlock(x, y, z, cellValue); } if (!flag) { CalculateImpulseAndDamage(new Vector3((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f), 60f, 2f * num4, out Vector3 impulse, out float _); bool flag2 = false; List <BlockDropValue> list = new List <BlockDropValue>(); block.GetDropValues(m_subsystemTerrain, cellValue, newValue, 0, list, out bool _); if (list.Count == 0) { list.Add(new BlockDropValue { Value = cellValue, Count = 1 }); flag2 = true; } foreach (BlockDropValue item in list) { int num7 = Terrain.ExtractContents(item.Value); if (!(BlocksManager.Blocks[num7] is FluidBlock)) { float num8 = (m_projectilesCount < 40) ? 1f : ((m_projectilesCount < 60) ? 0.5f : ((m_projectilesCount >= 80) ? 0.125f : 0.25f)); if (m_random.Float(0f, 1f) < num8) { Vector3 velocity = impulse + m_random.Vector3(0.05f * impulse.Length()); if (m_projectilesCount >= 1) { velocity *= m_random.Float(0.5f, 1f); velocity += m_random.Vector3(0.2f * velocity.Length()); } float num9 = flag2 ? 0f : MathUtils.Lerp(1f, 0f, (float)m_projectilesCount / 20f); Projectile projectile = m_subsystemProjectiles.AddProjectile(item.Value, new Vector3((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f), velocity, m_random.Vector3(0f, 20f), null); projectile.ProjectileStoppedAction = ((!(m_random.Float(0f, 1f) < num9)) ? ProjectileStoppedAction.Disappear : ProjectileStoppedAction.TurnIntoPickable); if (m_random.Float(0f, 1f) < 0.5f && m_projectilesCount < 35) { float num10 = (num4 > 60f) ? m_random.Float(3f, 7f) : m_random.Float(1f, 3f); if (isIncendiary) { num10 += 10f; } m_subsystemProjectiles.AddTrail(projectile, Vector3.Zero, new SmokeTrailParticleSystem(15, m_random.Float(0.75f, 1.5f), num10, isIncendiary ? new Color(255, 140, 192) : Color.White)); projectile.IsIncendiary = isIncendiary; } m_generatedProjectiles.Add(projectile, value: true); m_projectilesCount++; } } } } } else { m_surroundingPressureByPoint.Set(x, y, z, new SurroundingPressurePoint { Pressure = num4, IsIncendiary = isIncendiary }); if (block.IsCollidable) { return; } } } toProcess.Add(new ProcessPoint { X = x, Y = y, Z = z, Axis = axis }); processed.Set(x, y, z, value: true); }
public void SimulateExplosion(int x, int y, int z, float pressure, bool isIncendiary) { float num = MathUtils.Max(0.13f * MathUtils.Pow(pressure, 0.5f), 1f); m_subsystemTerrain.ChangeCell(x, y, z, Terrain.MakeBlockValue(0)); SparseSpatialArray <bool> processed = new SparseSpatialArray <bool>(x, y, z, outside: true); List <ProcessPoint> list = new List <ProcessPoint>(); List <ProcessPoint> list2 = new List <ProcessPoint>(); List <ProcessPoint> list3 = new List <ProcessPoint>(); TryAddPoint(x, y, z, -1, pressure, isIncendiary, list, processed); int num2 = 0; int num3 = 0; while (list.Count > 0 || list2.Count > 0) { num2 += list.Count; num3++; float num4 = 5f * (float)MathUtils.Max(num3 - 7, 0); float num5 = pressure / (MathUtils.Pow(num2, 0.66f) + num4); if (num5 >= num) { foreach (ProcessPoint item in list) { float num6 = m_pressureByPoint.Get(item.X, item.Y, item.Z); float num7 = num5 + num6; m_pressureByPoint.Set(item.X, item.Y, item.Z, num7); if (item.Axis == 0) { TryAddPoint(item.X - 1, item.Y, item.Z, 0, num7, isIncendiary, list3, processed); TryAddPoint(item.X + 1, item.Y, item.Z, 0, num7, isIncendiary, list3, processed); TryAddPoint(item.X, item.Y - 1, item.Z, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X, item.Y + 1, item.Z, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X, item.Y, item.Z - 1, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X, item.Y, item.Z + 1, -1, num7, isIncendiary, list2, processed); } else if (item.Axis == 1) { TryAddPoint(item.X - 1, item.Y, item.Z, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X + 1, item.Y, item.Z, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X, item.Y - 1, item.Z, 1, num7, isIncendiary, list3, processed); TryAddPoint(item.X, item.Y + 1, item.Z, 1, num7, isIncendiary, list3, processed); TryAddPoint(item.X, item.Y, item.Z - 1, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X, item.Y, item.Z + 1, -1, num7, isIncendiary, list2, processed); } else if (item.Axis == 2) { TryAddPoint(item.X - 1, item.Y, item.Z, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X + 1, item.Y, item.Z, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X, item.Y - 1, item.Z, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X, item.Y + 1, item.Z, -1, num7, isIncendiary, list2, processed); TryAddPoint(item.X, item.Y, item.Z - 1, 2, num7, isIncendiary, list3, processed); TryAddPoint(item.X, item.Y, item.Z + 1, 2, num7, isIncendiary, list3, processed); } else { TryAddPoint(item.X - 1, item.Y, item.Z, 0, num7, isIncendiary, list3, processed); TryAddPoint(item.X + 1, item.Y, item.Z, 0, num7, isIncendiary, list3, processed); TryAddPoint(item.X, item.Y - 1, item.Z, 1, num7, isIncendiary, list3, processed); TryAddPoint(item.X, item.Y + 1, item.Z, 1, num7, isIncendiary, list3, processed); TryAddPoint(item.X, item.Y, item.Z - 1, 2, num7, isIncendiary, list3, processed); TryAddPoint(item.X, item.Y, item.Z + 1, 2, num7, isIncendiary, list3, processed); } } } List <ProcessPoint> list4 = list; list4.Clear(); list = list2; list2 = list3; list3 = list4; } }