| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- using Content.Server.Atmos.Components;
- using Content.Server.Decals;
- using Content.Shared.Atmos;
- using Content.Shared.Atmos.Components;
- using Content.Shared.Atmos.Reactions;
- using Content.Shared.Database;
- using Robust.Shared.Audio;
- using Robust.Shared.Map;
- using Robust.Shared.Map.Components;
- using Robust.Shared.Random;
- namespace Content.Server.Atmos.EntitySystems
- {
- public sealed partial class AtmosphereSystem
- {
- [Dependency] private readonly DecalSystem _decalSystem = default!;
- [Dependency] private readonly IRobustRandom _random = default!;
- private const int HotspotSoundCooldownCycles = 200;
- private int _hotspotSoundCooldown = 0;
- [ViewVariables(VVAccess.ReadWrite)]
- public string? HotspotSound { get; private set; } = "/Audio/Effects/fire.ogg";
- private void ProcessHotspot(
- Entity<GridAtmosphereComponent, GasTileOverlayComponent, MapGridComponent, TransformComponent> ent,
- TileAtmosphere tile)
- {
- var gridAtmosphere = ent.Comp1;
- if (!tile.Hotspot.Valid)
- {
- gridAtmosphere.HotspotTiles.Remove(tile);
- return;
- }
- AddActiveTile(gridAtmosphere, tile);
- if (!tile.Hotspot.SkippedFirstProcess)
- {
- tile.Hotspot.SkippedFirstProcess = true;
- return;
- }
- if(tile.ExcitedGroup != null)
- ExcitedGroupResetCooldowns(tile.ExcitedGroup);
- if ((tile.Hotspot.Temperature < Atmospherics.FireMinimumTemperatureToExist) || (tile.Hotspot.Volume <= 1f)
- || tile.Air == null || tile.Air.GetMoles(Gas.Oxygen) < 0.5f || (tile.Air.GetMoles(Gas.Plasma) < 0.5f && tile.Air.GetMoles(Gas.Tritium) < 0.5f))
- {
- tile.Hotspot = new Hotspot();
- InvalidateVisuals(ent, tile);
- return;
- }
- PerformHotspotExposure(tile);
- if (tile.Hotspot.Bypassing)
- {
- tile.Hotspot.State = 3;
- var gridUid = ent.Owner;
- var tilePos = tile.GridIndices;
- // Get the existing decals on the tile
- var tileDecals = _decalSystem.GetDecalsInRange(gridUid, tilePos);
- // Count the burnt decals on the tile
- var tileBurntDecals = 0;
- foreach (var set in tileDecals)
- {
- if (Array.IndexOf(_burntDecals, set.Decal.Id) == -1)
- continue;
- tileBurntDecals++;
- if (tileBurntDecals > 4)
- break;
- }
- // Add a random burned decal to the tile only if there are less than 4 of them
- if (tileBurntDecals < 4)
- _decalSystem.TryAddDecal(_burntDecals[_random.Next(_burntDecals.Length)], new EntityCoordinates(gridUid, tilePos), out _, cleanable: true);
- if (tile.Air.Temperature > Atmospherics.FireMinimumTemperatureToSpread)
- {
- var radiatedTemperature = tile.Air.Temperature * Atmospherics.FireSpreadRadiosityScale;
- foreach (var otherTile in tile.AdjacentTiles)
- {
- // TODO ATMOS: This is sus. Suss this out.
- if (otherTile == null)
- continue;
- if(!otherTile.Hotspot.Valid)
- HotspotExpose(gridAtmosphere, otherTile, radiatedTemperature, Atmospherics.CellVolume/4);
- }
- }
- }
- else
- {
- tile.Hotspot.State = (byte) (tile.Hotspot.Volume > Atmospherics.CellVolume * 0.4f ? 2 : 1);
- }
- if (tile.Hotspot.Temperature > tile.MaxFireTemperatureSustained)
- tile.MaxFireTemperatureSustained = tile.Hotspot.Temperature;
- if (_hotspotSoundCooldown++ == 0 && !string.IsNullOrEmpty(HotspotSound))
- {
- var coordinates = _mapSystem.ToCenterCoordinates(tile.GridIndex, tile.GridIndices);
- // A few details on the audio parameters for fire.
- // The greater the fire state, the lesser the pitch variation.
- // The greater the fire state, the greater the volume.
- _audio.PlayPvs(HotspotSound, coordinates, AudioParams.Default.WithVariation(0.15f/tile.Hotspot.State).WithVolume(-5f + 5f * tile.Hotspot.State));
- }
- if (_hotspotSoundCooldown > HotspotSoundCooldownCycles)
- _hotspotSoundCooldown = 0;
- // TODO ATMOS Maybe destroy location here?
- }
- private void HotspotExpose(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile,
- float exposedTemperature, float exposedVolume, bool soh = false, EntityUid? sparkSourceUid = null)
- {
- if (tile.Air == null)
- return;
- var oxygen = tile.Air.GetMoles(Gas.Oxygen);
- if (oxygen < 0.5f)
- return;
- var plasma = tile.Air.GetMoles(Gas.Plasma);
- var tritium = tile.Air.GetMoles(Gas.Tritium);
- if (tile.Hotspot.Valid)
- {
- if (soh)
- {
- if (plasma > 0.5f || tritium > 0.5f)
- {
- if (tile.Hotspot.Temperature < exposedTemperature)
- tile.Hotspot.Temperature = exposedTemperature;
- if (tile.Hotspot.Volume < exposedVolume)
- tile.Hotspot.Volume = exposedVolume;
- }
- }
- return;
- }
- if ((exposedTemperature > Atmospherics.PlasmaMinimumBurnTemperature) && (plasma > 0.5f || tritium > 0.5f))
- {
- if (sparkSourceUid.HasValue)
- _adminLog.Add(LogType.Flammable, LogImpact.High, $"Heat/spark of {ToPrettyString(sparkSourceUid.Value)} caused atmos ignition of gas: {tile.Air.Temperature.ToString():temperature}K - {oxygen}mol Oxygen, {plasma}mol Plasma, {tritium}mol Tritium");
- tile.Hotspot = new Hotspot
- {
- Volume = exposedVolume * 25f,
- Temperature = exposedTemperature,
- SkippedFirstProcess = tile.CurrentCycle > gridAtmosphere.UpdateCounter,
- Valid = true,
- State = 1
- };
- AddActiveTile(gridAtmosphere, tile);
- gridAtmosphere.HotspotTiles.Add(tile);
- }
- }
- private void PerformHotspotExposure(TileAtmosphere tile)
- {
- if (tile.Air == null || !tile.Hotspot.Valid) return;
- tile.Hotspot.Bypassing = tile.Hotspot.SkippedFirstProcess && tile.Hotspot.Volume > tile.Air.Volume*0.95f;
- if (tile.Hotspot.Bypassing)
- {
- tile.Hotspot.Volume = tile.Air.ReactionResults[(byte)GasReaction.Fire] * Atmospherics.FireGrowthRate;
- tile.Hotspot.Temperature = tile.Air.Temperature;
- }
- else
- {
- var affected = tile.Air.RemoveVolume(tile.Hotspot.Volume);
- affected.Temperature = tile.Hotspot.Temperature;
- React(affected, tile);
- tile.Hotspot.Temperature = affected.Temperature;
- tile.Hotspot.Volume = affected.ReactionResults[(byte)GasReaction.Fire] * Atmospherics.FireGrowthRate;
- Merge(tile.Air, affected);
- }
- var fireEvent = new TileFireEvent(tile.Hotspot.Temperature, tile.Hotspot.Volume);
- _entSet.Clear();
- _lookup.GetLocalEntitiesIntersecting(tile.GridIndex, tile.GridIndices, _entSet, 0f);
- foreach (var entity in _entSet)
- {
- RaiseLocalEvent(entity, ref fireEvent);
- }
- }
- }
- }
|