using Content.Shared.Administration.Logs; using Content.Shared.Damage.Components; using Content.Shared.Damage.Systems; using Content.Shared.Electrocution; using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.Repairable; using Content.Shared.Tools.Systems; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Prototypes; namespace Content.Shared._FarHorizons.Power.Generation.FissionGenerator; // Ported and modified from goonstation by Jhrushbe. // CC-BY-NC-SA-3.0 // https://github.com/goonstation/goonstation/blob/ff86b044/code/obj/nuclearreactor/turbine.dm public abstract class SharedTurbineSystem : EntitySystem { // [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; // Delta V - Never used [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] protected readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedToolSystem _toolSystem = default!; [Dependency] private readonly EntityManager _entityManager = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; // [Dependency] private readonly IPrototypeManager _proto = default!; // Delta V - Never used public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnExamined); SubscribeLocalEvent(RepairTurbine); SubscribeLocalEvent(OnRepairTurbineFinished); } private void OnExamined(Entity ent, ref ExaminedEvent args) { var comp = ent.Comp; if (!Comp(ent).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status. return; using (args.PushGroup(nameof(TurbineComponent))) { if(comp.CurrentStator == null) args.PushMarkup(Loc.GetString("gas-turbine-examine-stator-null")); if (comp.CurrentBlade == null) args.PushMarkup(Loc.GetString("gas-turbine-examine-blade-null")); else { switch (comp.RPM) { case float n when n is >= 0 and <= 1: args.PushMarkup(Loc.GetString("turbine-spinning-0")); // " The blades are not spinning." break; case float n when n is > 1 and <= 60: args.PushMarkup(Loc.GetString("turbine-spinning-1")); // " The blades are turning slowly." break; case float n when n > 60 && n <= comp.BestRPM * 0.5: args.PushMarkup(Loc.GetString("turbine-spinning-2")); // " The blades are spinning." break; case float n when n > comp.BestRPM * 0.5 && n <= comp.BestRPM * 1.2: args.PushMarkup(Loc.GetString("turbine-spinning-3")); // " The blades are spinning quickly." break; case float n when n > comp.BestRPM * 1.2 && n <= float.PositiveInfinity: args.PushMarkup(Loc.GetString("turbine-spinning-4")); // " The blades are spinning out of control!" break; default: break; } } if (comp.Ruined) { args.PushMarkup(Loc.GetString("turbine-ruined")); // " It's completely broken!" } else if (comp.BladeHealth <= 0.25 * comp.BladeHealthMax) { args.PushMarkup(Loc.GetString("turbine-damaged-3")); // " It's critically damaged!" } else if (comp.BladeHealth <= 0.5 * comp.BladeHealthMax) { args.PushMarkup(Loc.GetString("turbine-damaged-2")); // " The turbine looks badly damaged." } else if (comp.BladeHealth <= 0.75 * comp.BladeHealthMax) { args.PushMarkup(Loc.GetString("turbine-damaged-1")); // " The turbine looks a bit scuffed." } else { args.PushMarkup(Loc.GetString("turbine-damaged-0")); // " It appears to be in good condition." } } } protected void UpdateAppearance(EntityUid uid, TurbineComponent? comp = null, AppearanceComponent? appearance = null) { if (!Resolve(uid, ref comp, ref appearance, false)) return; _appearance.SetData(uid, TurbineVisuals.TurbineRuined, comp.Ruined); _appearance.SetData(uid, TurbineVisuals.DamageSpark, comp.IsSparking); _appearance.SetData(uid, TurbineVisuals.DamageSmoke, comp.IsSmoking); } protected void PlayAudio(SoundSpecifier? sound, EntityUid uid, out EntityUid? audioStream, AudioParams? audioParams = null) { if (sound == null || audioParams == null) { audioStream = null; return; } var loop = audioParams.Value.WithLoop(true); var stream = _audio.PlayPvs(sound, uid, loop); // Delta V - It was alwasy false... so it was always this audioStream = stream?.Entity is { } entity ? entity : null; } protected static bool AdjustStatorLoad(TurbineComponent turbine, float change) { var newSet = Math.Max(turbine.StatorLoad + change, 1000f); if (turbine.StatorLoad != newSet) { turbine.StatorLoad = newSet; return true; } return false; } #region Repairs private void RepairTurbine(EntityUid uid, TurbineComponent comp, ref InteractUsingEvent args) { if (args.Handled) return; if(_toolSystem.HasQuality(args.Used, comp.RepairTool)) { if (comp.CurrentBlade == null) { _popupSystem.PopupEntity(Loc.GetString("gas-turbine-repair-fail-blade"), args.User, args.User, PopupType.Medium); args.Handled = true; return; } if (comp.CurrentStator == null) { _popupSystem.PopupEntity(Loc.GetString("gas-turbine-repair-fail-stator"), args.User, args.User, PopupType.Medium); args.Handled = true; return; } if (comp.BladeHealth >= comp.BladeHealthMax && !comp.Ruined) return; args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, comp.RepairDelay, comp.RepairTool, new RepairDoAfterEvent(), comp.RepairFuelCost); } } //Gotta love server/client desync protected virtual void OnRepairTurbineFinished(EntityUid uid, TurbineComponent comp, ref RepairDoAfterEvent args) { if (comp.Ruined) { comp.Ruined = false; if (comp.BladeHealth <= 0) { comp.BladeHealth = 1; } UpdateHealthIndicators(uid, comp); } else if (comp.BladeHealth < comp.BladeHealthMax) { comp.BladeHealth++; UpdateHealthIndicators(uid, comp); } else if (comp.BladeHealth >= comp.BladeHealthMax) { // This should technically never occur, but just in case... } if (!_entityManager.TryGetComponent(uid, out var damageableComponent)) return; _damageableSystem.SetAllDamage((uid, damageableComponent), 0); } protected void UpdateHealthIndicators(EntityUid uid, TurbineComponent comp) { if (comp.BladeHealth <= 0.75 * comp.BladeHealthMax && !comp.IsSparking) { comp.IsSparking = true; _audio.PlayPvs(new SoundPathSpecifier("/Audio/Effects/PowerSink/electric.ogg"), uid, AudioParams.Default.WithPitchScale(0.75f)); _popupSystem.PopupEntity(Loc.GetString("turbine-spark", ("owner", uid)), uid, PopupType.MediumCaution); } else if (comp.BladeHealth > 0.75 * comp.BladeHealthMax && comp.IsSparking) { comp.IsSparking = false; _popupSystem.PopupEntity(Loc.GetString("turbine-spark-stop", ("owner", uid)), uid, PopupType.Medium); } if (comp.BladeHealth <= 0.5 * comp.BladeHealthMax && !comp.IsSmoking) { comp.IsSmoking = true; _popupSystem.PopupEntity(Loc.GetString("turbine-smoke", ("owner", uid)), uid, PopupType.MediumCaution); } else if (comp.BladeHealth > 0.5 * comp.BladeHealthMax && comp.IsSmoking) { comp.IsSmoking = false; _popupSystem.PopupEntity(Loc.GetString("turbine-smoke-stop", ("owner", uid)), uid, PopupType.Medium); } _entityManager.EnsureComponent(uid).Enabled = comp.IsSparking; UpdateAppearance(uid, comp); } #endregion }