| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- using Content.Server.Atmos.EntitySystems;
- using Content.Server.Body.Components;
- using Content.Server.Temperature.Components;
- using Content.Shared.Atmos;
- using Content.Shared.Atmos.Rotting;
- using Content.Shared.Damage;
- using Robust.Server.Containers;
- using Robust.Shared.Physics.Components;
- using Robust.Shared.Timing;
- using Content.Server.GameTicking;
- using Content.Server.GameTicking.Rules.Components;
- using Content.Shared.GameTicking.Components;
- namespace Content.Server.Atmos.Rotting;
- public sealed class RottingSystem : SharedRottingSystem
- {
- [Dependency] private readonly IGameTiming _timing = default!;
- [Dependency] private readonly AtmosphereSystem _atmosphere = default!;
- [Dependency] private readonly ContainerSystem _container = default!;
- [Dependency] private readonly DamageableSystem _damageable = default!;
- [Dependency] private readonly GameTicker _gameTicker = default!;
- public override void Initialize()
- {
- base.Initialize();
- SubscribeLocalEvent<RottingComponent, BeingGibbedEvent>(OnGibbed);
- SubscribeLocalEvent<TemperatureComponent, IsRottingEvent>(OnTempIsRotting);
- }
- private void OnGibbed(EntityUid uid, RottingComponent component, BeingGibbedEvent args)
- {
- if (!TryComp<PhysicsComponent>(uid, out var physics))
- return;
- if (!TryComp<PerishableComponent>(uid, out var perishable))
- return;
- var molsToDump = perishable.MolsPerSecondPerUnitMass * physics.FixturesMass * (float)component.TotalRotTime.TotalSeconds;
- var tileMix = _atmosphere.GetTileMixture(uid, excite: true);
- tileMix?.AdjustMoles(Gas.Ammonia, molsToDump);
- }
- private void OnTempIsRotting(EntityUid uid, TemperatureComponent component, ref IsRottingEvent args)
- {
- if (args.Handled)
- return;
- args.Handled = component.CurrentTemperature < Atmospherics.T0C + 0.85f;
- }
- /// <summary>
- /// Is anything speeding up the decay?
- /// e.g. buried in a grave
- /// TODO: hot temperatures increase rot?
- /// </summary>
- /// <returns></returns>
- private float GetRotRate(EntityUid uid)
- {
- if (_container.TryGetContainingContainer((uid, null, null), out var container) &&
- TryComp<ProRottingContainerComponent>(container.Owner, out var rotContainer))
- {
- return rotContainer.DecayModifier;
- }
- return 1f;
- }
- public override void Update(float frameTime)
- {
- base.Update(frameTime);
- var perishQuery = EntityQueryEnumerator<PerishableComponent>();
- while (perishQuery.MoveNext(out var uid, out var perishable))
- {
- if (_timing.CurTime < perishable.RotNextUpdate)
- continue;
- perishable.RotNextUpdate += perishable.PerishUpdateRate;
- var stage = PerishStage((uid, perishable), MaxStages);
- if (stage != perishable.Stage)
- {
- perishable.Stage = stage;
- Dirty(uid, perishable);
- }
- if (IsRotten(uid) || !IsRotProgressing(uid, perishable))
- continue;
- perishable.RotAccumulator += perishable.PerishUpdateRate * GetRotRate(uid);
- if (perishable.RotAccumulator >= perishable.RotAfter)
- {
- var rot = AddComp<RottingComponent>(uid);
- rot.NextRotUpdate = _timing.CurTime + rot.RotUpdateRate;
- }
- }
- var rotQuery = EntityQueryEnumerator<RottingComponent, PerishableComponent, TransformComponent>();
- while (rotQuery.MoveNext(out var uid, out var rotting, out var perishable, out var xform))
- {
- if (_timing.CurTime < rotting.NextRotUpdate) // This is where it starts to get noticable on larger animals, no need to run every second
- continue;
- rotting.NextRotUpdate += rotting.RotUpdateRate;
- if (!IsRotProgressing(uid, perishable))
- continue;
- rotting.TotalRotTime += rotting.RotUpdateRate * GetRotRate(uid);
- if (rotting.DealDamage)
- {
- var damage = rotting.Damage * rotting.RotUpdateRate.TotalSeconds;
- _damageable.TryChangeDamage(uid, damage, true, false);
- }
- if (TryComp<RotIntoComponent>(uid, out var rotInto))
- {
- var rotStageEnd = rotInto.Stage;
- //on tdm, faster rotting
- var query = EntityQueryEnumerator<TeamDeathMatchRuleComponent, GameRuleComponent>();
- while (query.MoveNext(out var nuid, out var tdm, out var gameRule))
- {
- if (_gameTicker.IsGameRuleActive(nuid, gameRule))
- {
- if (perishable.RotAccumulator.TotalSeconds >= 300)
- {
- Spawn(rotInto.Entity, xform.Coordinates);
- QueueDel(uid);
- return;
- }
- }
- }
- var stage = RotStage(uid, rotting, perishable);
- if (stage >= rotStageEnd)
- {
- Spawn(rotInto.Entity, xform.Coordinates);
- QueueDel(uid);
- continue;
- }
- }
- if (!TryComp<PhysicsComponent>(uid, out var physics))
- continue;
- // We need a way to get the mass of the mob alone without armor etc in the future
- // or just remove the mass mechanics altogether because they aren't good.
- var molRate = perishable.MolsPerSecondPerUnitMass * (float)rotting.RotUpdateRate.TotalSeconds;
- var tileMix = _atmosphere.GetTileMixture(uid, excite: true);
- tileMix?.AdjustMoles(Gas.Ammonia, molRate * physics.FixturesMass);
- }
- }
- }
|