diff --git a/Content.Server/StationEvents/Components/StationEventComponent.cs b/Content.Server/StationEvents/Components/StationEventComponent.cs index 8d879161a34..7ffbd355a35 100644 --- a/Content.Server/StationEvents/Components/StationEventComponent.cs +++ b/Content.Server/StationEvents/Components/StationEventComponent.cs @@ -73,7 +73,25 @@ public sealed partial class StationEventComponent : Component /// Frontier - How many players need to be present on station for the event to not run, to avoid running safe events with high-pop /// [DataField] - public int MaximumPlayers = 999; + public int MaximumPlayers = 9999; + + /// + /// Frontier - + /// + [DataField] + public int MinimumStations = 1; + + /// + /// Frontier - + /// + [DataField] + public int MaximumStations = 1; + + /// + /// Frontier - + /// + [DataField] + public int PlayersPerEvent = 10; /// /// How many times this even can occur in a single round diff --git a/Content.Server/StationEvents/EventManagerSystem.cs b/Content.Server/StationEvents/EventManagerSystem.cs index b7bdd898d74..0fce622e514 100644 --- a/Content.Server/StationEvents/EventManagerSystem.cs +++ b/Content.Server/StationEvents/EventManagerSystem.cs @@ -281,4 +281,11 @@ private bool CanRun(EntityPrototype prototype, StationEventComponent stationEven return true; } + + public void GetEventStations(StationEventComponent stationEvent) + { + var numStations = Math.Clamp(_playerManager.PlayerCount / stationEvent.PlayersPerEvent, stationEvent.MinimumStations, stationEvent.MaximumStations); + + + } } diff --git a/Content.Server/_NF/Power/Components/ElectricalOverloadComponent.cs b/Content.Server/_NF/Power/Components/ElectricalOverloadComponent.cs new file mode 100644 index 00000000000..23561d42ae4 --- /dev/null +++ b/Content.Server/_NF/Power/Components/ElectricalOverloadComponent.cs @@ -0,0 +1,29 @@ +namespace Content.Server._NF.Power.Components; + +[RegisterComponent] +public sealed partial class ElectricalOverloadComponent : Component +{ + [ViewVariables] + public DateTime EmpAt = DateTime.MaxValue; + + [ViewVariables] + public DateTime NextBuzz = DateTime.MaxValue; + + /// + /// Range of the EMP in tiles. + /// + [DataField] + public float EmpRange = 1f; + + /// + /// Power consumed from batteries by the EMP + /// + [DataField] + public float EmpConsumption = 100000f; + + /// + /// How long the EMP effects last for, in seconds + /// + [DataField] + public float EmpDuration = 15f; +} diff --git a/Content.Server/_NF/Power/EntitySystems/ElectricalOverloadSystem.cs b/Content.Server/_NF/Power/EntitySystems/ElectricalOverloadSystem.cs new file mode 100644 index 00000000000..af1da5c27c3 --- /dev/null +++ b/Content.Server/_NF/Power/EntitySystems/ElectricalOverloadSystem.cs @@ -0,0 +1,84 @@ +using Content.Server._NF.Power.Components; +using Content.Server._NF.Tools.Components; +using Content.Server.Chat.Systems; +using Content.Server.Emp; +using Content.Server.Power.Components; +using Robust.Shared.Random; + +namespace Content.Server._NF.Power.EntitySystems; + +public sealed class ElectricalOverloadSystem : EntitySystem +{ + [Dependency] private readonly EmpSystem _emp = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly ChatSystem _chatSystem = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnElectricalOverload); + } + + private void OnElectricalOverload(EntityUid uid, ElectricalOverloadComponent component, ElectricalOverloadEvent args) + { + if (args.Enabled) + { + // Toggled on, means EMP pulse! + component.EmpAt = DateTime.Now + TimeSpan.FromSeconds(_random.NextDouble(25, 35)); + component.NextBuzz = DateTime.Now + TimeSpan.FromSeconds(_random.NextDouble(3, 5)); + if (!HasComp(uid)) + { + EnsureComp(uid, out var disableToolUse); + disableToolUse.Anchoring = true; + disableToolUse.Cutting = true; + disableToolUse.Prying = true; + disableToolUse.Screwing = true; + disableToolUse.Welding = true; + + disableToolUse.TemporarilyDisabled = true; // Event + } + } + else + { + // Toggled off, means cancel EMP pulse. + component.EmpAt = DateTime.MaxValue; + component.NextBuzz = DateTime.MaxValue; + if (TryComp(uid, out var disableToolUse) && disableToolUse.TemporarilyDisabled) + { + RemComp(uid); + } + } + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var enumerator = EntityQueryEnumerator(); + while (enumerator.MoveNext(out var entity, out var component)) + { + if (component.EmpAt > DateTime.Now) + { + if (component.NextBuzz > DateTime.Now) + continue; + + component.NextBuzz = DateTime.Now + TimeSpan.FromSeconds(_random.NextDouble(7, 15)); + _chatSystem.TrySendInGameICMessage( + entity, + Loc.GetString("electrical-overload-system-buzz"), + InGameICChatType.Emote, + hideChat: true, + ignoreActionBlocker: true + ); + continue; + } + + var coords = _transform.GetMapCoordinates(entity); + _emp.EmpPulse(coords, component.EmpRange, component.EmpConsumption, component.EmpDuration); + // We add a bit of randomness to the next EMP pulse time + component.EmpAt = DateTime.Now + TimeSpan.FromSeconds(_random.NextDouble(3, 10)); + } + } +} diff --git a/Content.Server/_NF/StationEvents/Components/ElectricStormRuleComponent.cs b/Content.Server/_NF/StationEvents/Components/ElectricStormRuleComponent.cs new file mode 100644 index 00000000000..dba27dd9ca2 --- /dev/null +++ b/Content.Server/_NF/StationEvents/Components/ElectricStormRuleComponent.cs @@ -0,0 +1,41 @@ +using System.Threading; +using Content.Server.StationEvents.Events; + +namespace Content.Server.StationEvents.Components; + +/// +/// Solar Flare event specific configuration +/// +[RegisterComponent, Access(typeof(ElectricStormRule))] +public sealed partial class ElectricStormRuleComponent : Component +{ + /// + /// Chance light bulb breaks per second during event + /// + [DataField] + public float ComputerChance; + + /// + /// Chance door toggles per second during event + /// + [DataField] + public float MachineChance; + + /// + /// Minimum faxes to send + /// + [DataField] + public int PlayersPerTargets { get; private set; } = 5; + + /// + /// Minimum faxes to send + /// + [DataField] + public int MinTargets { get; private set; } = 1; + + /// + /// Maximum faxes to send + /// + [DataField] + public int MaxTargets { get; private set; } = 10; +} diff --git a/Content.Server/_NF/StationEvents/Components/RandomFaxRuleComponent.cs b/Content.Server/_NF/StationEvents/Components/RandomFaxRuleComponent.cs index 2cb084e6413..80f5d0a48e1 100644 --- a/Content.Server/_NF/StationEvents/Components/RandomFaxRuleComponent.cs +++ b/Content.Server/_NF/StationEvents/Components/RandomFaxRuleComponent.cs @@ -52,6 +52,12 @@ public sealed partial class RandomFaxRuleComponent : Component [DataField] public List? PerRecipientActions { get; private set; } + /// + /// + /// + [DataField] + public int PlayersPerFaxes { get; private set; } = 15; + /// /// Minimum faxes to send /// @@ -62,7 +68,7 @@ public sealed partial class RandomFaxRuleComponent : Component /// Maximum faxes to send /// [DataField] - public int MaxFaxes { get; private set; } = 1; + public int MaxFaxes { get; private set; } = 3; } // TODO: relocate these definitions. @@ -101,4 +107,4 @@ public sealed partial class EditableFaxPrintout public string? StampState; public List StampedBy = new(); public bool Locked; -} \ No newline at end of file +} diff --git a/Content.Server/_NF/StationEvents/Events/ElectricStormRule.cs b/Content.Server/_NF/StationEvents/Events/ElectricStormRule.cs new file mode 100644 index 00000000000..d8a30d8ca95 --- /dev/null +++ b/Content.Server/_NF/StationEvents/Events/ElectricStormRule.cs @@ -0,0 +1,68 @@ +using Content.Server.GameTicking.Rules.Components; +using Robust.Shared.Random; +using Content.Server.StationEvents.Components; +using Content.Shared.GameTicking.Components; +using Content.Server.Construction.Components; +using Content.Server.Power.EntitySystems; +using Content.Server.Power.Components; +using Content.Shared.Station.Components; +using Robust.Server.Player; +using Content.Server.Station.Components; +using Content.Server.Station.Systems; +using Content.Server._NF.Power.EntitySystems; +using Content.Server._NF.Power.Components; + +namespace Content.Server.StationEvents.Events; + +public sealed class ElectricStormRule : StationEventSystem +{ + private float _effectTimer = 0; + + public override void Initialize() + { + base.Initialize(); + } + + protected override void Started(EntityUid uid, ElectricStormRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args) + { + base.Started(uid, component, gameRule, args); + + RaiseLocalEvent(uid, new ElectricalOverloadEvent(true)); + } + + protected override void Ended(EntityUid uid, ElectricStormRuleComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args) + { + base.Ended(uid, component, gameRule, args); + + RemComp(uid); + } + + protected override void ActiveTick(EntityUid uid, ElectricStormRuleComponent component, GameRuleComponent gameRule, float frameTime) + { + base.ActiveTick(uid, component, gameRule, frameTime); + + _effectTimer -= frameTime; + if (_effectTimer < 0) + { + _effectTimer += 1; + var computerQuery = EntityQueryEnumerator(); + while (computerQuery.MoveNext(out var computerEnt, out var computer)) + { + if (RobustRandom.Prob(component.ComputerChance)) + { + EnsureComp(computerEnt); + } + } + var lightQuery = EntityQueryEnumerator(); + while (lightQuery.MoveNext(out var machineEnt, out var machine)) + { + if (RobustRandom.Prob(component.MachineChance)) + { + EnsureComp(machineEnt); + } + } + } + } + + public record struct ElectricalOverloadEvent(bool Enabled); +} diff --git a/Content.Server/_NF/StationEvents/Events/RandomFaxRule.cs b/Content.Server/_NF/StationEvents/Events/RandomFaxRule.cs index c3ebff3aa6a..4c4af3013e9 100644 --- a/Content.Server/_NF/StationEvents/Events/RandomFaxRule.cs +++ b/Content.Server/_NF/StationEvents/Events/RandomFaxRule.cs @@ -4,7 +4,7 @@ using Content.Shared.Fax.Components; using Content.Server.Fax; using Content.Server.Station.Systems; -using Robust.Shared.Random; +using Robust.Server.Player; namespace Content.Server.StationEvents.Events; @@ -13,7 +13,7 @@ public sealed class RandomFaxRule : StationEventSystem [Dependency] private readonly IEntityManager _entMan = default!; [Dependency] private readonly FaxSystem _faxSystem = default!; [Dependency] private readonly StationSystem _stationSystem = default!; - [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; private const int MaxRetries = 10; protected override void Added(EntityUid uid, RandomFaxRuleComponent component, GameRuleComponent gameRule, GameRuleAddedEvent args) @@ -41,7 +41,7 @@ protected override void Started(EntityUid uid, RandomFaxRuleComponent component, { base.Started(uid, component, gameRule, args); - var numFaxes = _random.Next(component.MinFaxes, component.MaxFaxes); + var numFaxes = Math.Clamp(_playerManager.PlayerCount / component.PlayersPerFaxes, component.MinFaxes, component.MaxFaxes); List stations = new(); int retries = 0; diff --git a/Content.Server/_NF/Tools/Component/DisableToolUseComponent.cs b/Content.Server/_NF/Tools/Component/DisableToolUseComponent.cs index c9dd9b4cc5c..9b3313b2eba 100644 --- a/Content.Server/_NF/Tools/Component/DisableToolUseComponent.cs +++ b/Content.Server/_NF/Tools/Component/DisableToolUseComponent.cs @@ -1,7 +1,3 @@ -using Content.Shared.Tools; -using Robust.Shared.Prototypes; -using Robust.Shared.Utility; - namespace Content.Server._NF.Tools.Components { [RegisterComponent] @@ -30,5 +26,8 @@ public sealed partial class DisableToolUseComponent : Component public bool Rolling; [DataField, ViewVariables(VVAccess.ReadWrite)] public bool Digging; + + [DataField, ViewVariables(VVAccess.ReadWrite)] // Used by events + public bool TemporarilyDisabled; } } diff --git a/Resources/Locale/en-US/_Umbra/power/overload.ftl b/Resources/Locale/en-US/_Umbra/power/overload.ftl new file mode 100644 index 00000000000..4b25f018e16 --- /dev/null +++ b/Resources/Locale/en-US/_Umbra/power/overload.ftl @@ -0,0 +1 @@ +electrical-overload-system-buzz = buzzes