diff --git a/Content.Server/DeltaV/Abilities/Psionics/PrecognitionPowerSystem.cs b/Content.Server/DeltaV/Abilities/Psionics/PrecognitionPowerSystem.cs
index 23fe9d7e3eb..60d574192e1 100644
--- a/Content.Server/DeltaV/Abilities/Psionics/PrecognitionPowerSystem.cs
+++ b/Content.Server/DeltaV/Abilities/Psionics/PrecognitionPowerSystem.cs
@@ -6,6 +6,7 @@
using Content.Shared.Abilities.Psionics;
using Content.Shared.Actions.Events;
using Content.Shared.Actions;
+using Content.Shared.Chat;
using Content.Shared.DoAfter;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Popups;
@@ -22,32 +23,38 @@ namespace Content.Server.Abilities.Psionics;
public sealed class PrecognitionPowerSystem : EntitySystem
{
- [Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly DoAfterSystem _doAfter = default!;
[Dependency] private readonly GameTicker _gameTicker = default!;
[Dependency] private readonly MindSystem _mind = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
- [Dependency] private readonly SharedPopupSystem _popups = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedPsionicAbilitiesSystem _psionics = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
[Dependency] private readonly IChatManager _chat = default!;
[Dependency] private readonly IComponentFactory _factory = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
- [Dependency] private readonly IPrototypeManager _prototype = default!;
+ [Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly IRobustRandom _random = default!;
+ ///
+ /// A map between game rule prototypes and their results to give.
+ ///
+ public Dictionary Results = new();
+
public override void Initialize()
{
base.Initialize();
+
SubscribeLocalEvent(OnMapInit);
SubscribeLocalEvent(OnShutdown);
SubscribeLocalEvent(OnPowerUsed);
SubscribeLocalEvent(OnDoAfter);
+ SubscribeLocalEvent(OnPrototypesReloaded);
}
private void OnMapInit(Entity ent, ref MapInitEvent args)
{
- ent.Comp.AllResults = GetAllPrecognitionResults();
_actions.AddAction(ent, ref ent.Comp.PrecognitionActionEntity, ent.Comp.PrecognitionActionId);
_actions.StartUseDelay(ent.Comp.PrecognitionActionEntity);
if (TryComp(ent, out var psionic) && psionic.PsionicAbility == null)
@@ -66,7 +73,7 @@ private void OnShutdown(EntityUid uid, PrecognitionPowerComponent component, Com
private void OnPowerUsed(EntityUid uid, PrecognitionPowerComponent component, PrecognitionPowerActionEvent args)
{
- var ev = new PrecognitionDoAfterEvent(_gameTiming.CurTime);
+ var ev = new PrecognitionDoAfterEvent();
var doAfterArgs = new DoAfterArgs(EntityManager, uid, component.UseDelay, ev, uid)
{
BreakOnDamage = true
@@ -76,7 +83,7 @@ private void OnPowerUsed(EntityUid uid, PrecognitionPowerComponent component, Pr
_statusEffects.TryAddStatusEffect(uid, "TemporaryBlindness", component.UseDelay, true);
_statusEffects.TryAddStatusEffect(uid, "SlowedDown", component.UseDelay, true);
- _doAfterSystem.TryStartDoAfter(doAfterArgs, out var doAfterId);
+ _doAfter.TryStartDoAfter(doAfterArgs, out var doAfterId);
component.DoAfter = doAfterId;
var player = _audio.PlayGlobal(component.VisionSound, Filter.Entities(uid), true);
@@ -104,7 +111,7 @@ private void OnDoAfter(EntityUid uid, PrecognitionPowerComponent component, Prec
_statusEffects.TryRemoveStatusEffect(uid, "TemporaryBlindness");
_statusEffects.TryRemoveStatusEffect(uid, "SlowedDown");
- _popups.PopupEntity(
+ _popup.PopupEntity(
Loc.GetString("psionic-power-precognition-failure-by-damage"),
uid,
uid,
@@ -121,33 +128,31 @@ private void OnDoAfter(EntityUid uid, PrecognitionPowerComponent component, Prec
// Determines the window that will be looked at for events, avoiding events that are too close or too far to be useful.
var minDetectWindow = TimeSpan.FromSeconds(30);
var maxDetectWindow = TimeSpan.FromMinutes(10);
- string? message = null;
if (!_mind.TryGetMind(uid, out _, out var mindComponent) || mindComponent.Session == null)
return;
- var nextEvent = (FindEarliestNextEvent(minDetectWindow, maxDetectWindow));
- if (nextEvent == null) // A special message given if there is no event within the time window.
- message = "psionic-power-precognition-no-event-result-message";
-
- if (nextEvent != null && nextEvent.NextEventId != null)
- message = GetResultMessage(nextEvent.NextEventId, component);
+ var nextEvent = FindEarliestNextEvent(minDetectWindow, maxDetectWindow);
+ LocId? message = nextEvent?.NextEventId is {} nextEventId
+ ? GetResultMessage(nextEventId)
+ // A special message given if there is no event within the time window.
+ : "psionic-power-precognition-no-event-result-message";
if (_random.Prob(component.RandomResultChance)) // This will replace the proper result message with a random one occasionaly to simulate some unreliablity.
message = GetRandomResult();
- if (string.IsNullOrEmpty(message)) // If there is no message to send don't bother trying to send it.
+ if (message is not {} locId) // If there is no message to send don't bother trying to send it.
return;
// Send a message describing the vision they see
- message = Loc.GetString(message);
- _chat.ChatMessageToOne(Shared.Chat.ChatChannel.Server,
- message,
- Loc.GetString("chat-manager-server-wrap-message", ("message", message)),
- uid,
- false,
- mindComponent.Session.Channel,
- Color.PaleVioletRed);
+ var msg = Loc.GetString(locId);
+ _chat.ChatMessageToOne(ChatChannel.Server,
+ msg,
+ Loc.GetString("chat-manager-server-wrap-message", ("message", message)),
+ uid,
+ false,
+ mindComponent.Session.Channel,
+ Color.PaleVioletRed);
component.DoAfter = null;
}
@@ -156,37 +161,37 @@ private void OnDoAfter(EntityUid uid, PrecognitionPowerComponent component, Prec
/// Gets the precognition result message corosponding to the passed event id.
///
/// message string corosponding to the event id passed
- private string GetResultMessage(EntProtoId? eventId, PrecognitionPowerComponent component)
+ private LocId GetResultMessage(EntProtoId eventId)
{
- foreach (var (eventProto, precognitionResult) in component.AllResults)
+ if (!Results.TryGetValue(eventId, out var result))
{
- if (eventProto.ID == eventId && precognitionResult != null)
- return precognitionResult.Message;
+ Log.Error($"Prototype {eventId} does not have an associated precognitionResult!");
+ return string.Empty;
}
- Log.Error($"Prototype {eventId} does not have an associated precognitionResult!");
- return string.Empty;
+
+ return result.Message;
}
///
///
- /// The localized string of a weighted randomly chosen precognition result
- public string? GetRandomResult()
+ /// The locale message id of a weighted randomly chosen precognition result
+ public LocId? GetRandomResult()
{
- var precognitionResults = GetAllPrecognitionResults();
- var sumOfWeights = 0;
- foreach (var precognitionResult in precognitionResults.Values)
- sumOfWeights += (int)precognitionResult.Weight;
+ // funny weighted random
+ var sumOfWeights = 0f;
+ foreach (var precognitionResult in Results.Values)
+ sumOfWeights += precognitionResult.Weight;
- sumOfWeights = _random.Next(sumOfWeights);
- foreach (var precognitionResult in precognitionResults.Values)
+ sumOfWeights = (float) _random.Next((double) sumOfWeights);
+ foreach (var precognitionResult in Results.Values)
{
- sumOfWeights -= (int)precognitionResult.Weight;
+ sumOfWeights -= precognitionResult.Weight;
- if (sumOfWeights <= 0)
+ if (sumOfWeights <= 0f)
return precognitionResult.Message;
}
- Log.Error("Result was not found after weighted pick process!");
+ Log.Error("Precognition result was not found after weighted pick process!");
return null;
}
@@ -208,15 +213,25 @@ private string GetResultMessage(EntProtoId? eventId, PrecognitionPowerComponent
&& nextEventComponent.NextEventTime < _gameTicker.RoundDuration() + maxDetectWindow
&& earliestNextEvent == null
|| nextEventComponent.NextEventTime < earliestNextEventTime)
+ {
earliestNextEvent ??= nextEventComponent;
+ }
}
return earliestNextEvent;
}
- public Dictionary GetAllPrecognitionResults()
+ private void OnPrototypesReloaded(PrototypesReloadedEventArgs args)
{
- var allEvents = new Dictionary();
- foreach (var prototype in _prototype.EnumeratePrototypes())
+ if (!args.WasModified())
+ return;
+
+ CachePrecognitionResults();
+ }
+
+ private void CachePrecognitionResults()
+ {
+ Results.Clear();
+ foreach (var prototype in _proto.EnumeratePrototypes())
{
if (prototype.Abstract)
continue;
@@ -224,9 +239,7 @@ public Dictionary GetAllPrecogniti
if (!prototype.TryGetComponent(out var precognitionResult, _factory))
continue;
- allEvents.Add(prototype, precognitionResult);
+ Results.Add(prototype.ID, precognitionResult);
}
-
- return allEvents;
}
}
diff --git a/Content.Server/DeltaV/StationEvents/NextEvent/NextEventComponent.cs b/Content.Server/DeltaV/StationEvents/NextEvent/NextEventComponent.cs
index 78fa5a2f067..944a440eab1 100644
--- a/Content.Server/DeltaV/StationEvents/NextEvent/NextEventComponent.cs
+++ b/Content.Server/DeltaV/StationEvents/NextEvent/NextEventComponent.cs
@@ -1,8 +1,10 @@
using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.DeltaV.StationEvents.NextEvent;
[RegisterComponent, Access(typeof(NextEventSystem))]
+[AutoGenerateComponentPause]
public sealed partial class NextEventComponent : Component
{
///
@@ -14,6 +16,6 @@ public sealed partial class NextEventComponent : Component
///
/// Round time of the scheduler's next station event.
///
- [DataField]
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan NextEventTime;
}
diff --git a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs
index 882d841b24f..f70ce468ab4 100644
--- a/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs
+++ b/Content.Server/StationEvents/BasicStationEventSchedulerSystem.cs
@@ -36,15 +36,14 @@ protected override void Started(EntityUid uid, BasicStationEventSchedulerCompone
// A little starting variance so schedulers dont all proc at once.
component.TimeUntilNextEvent = RobustRandom.NextFloat(component.MinimumTimeUntilFirstEvent, component.MinimumTimeUntilFirstEvent + 120);
- // DeltaV - end init NextEventComp
+ // Begin DeltaV Additions: init NextEventComp
if (TryComp(uid, out var nextEventComponent)
- && _event.TryGenerateRandomEvent(component.ScheduledGameRules, out string? firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent))
- && firstEvent != null)
+ && _event.TryGenerateRandomEvent(component.ScheduledGameRules, TimeSpan.FromSeconds(component.TimeUntilNextEvent)) is {} firstEvent)
{
_chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", firstEvent), ("seconds", (int)component.TimeUntilNextEvent)));
_next.UpdateNextEvent(nextEventComponent, firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent));
}
- // DeltaV - end init NextEventComp
+ // End DeltaV Additions
}
protected override void Ended(EntityUid uid, BasicStationEventSchedulerComponent component, GameRuleComponent gameRule,
@@ -73,22 +72,24 @@ public override void Update(float frameTime)
continue;
}
- // DeltaV events using NextEventComponent
+ // Begin DeltaV Additions: events using NextEventComponent
if (TryComp(uid, out var nextEventComponent)) // If there is a nextEventComponent use the stashed event instead of running it directly.
{
ResetTimer(eventScheduler); // Time needs to be reset ahead of time since we need to chose events based on the next time it will run.
var nextEventTime = _timing.CurTime + TimeSpan.FromSeconds(eventScheduler.TimeUntilNextEvent);
- if (!_event.TryGenerateRandomEvent(eventScheduler.ScheduledGameRules, out string? generatedEvent, nextEventTime))
+ if (_event.TryGenerateRandomEvent(eventScheduler.ScheduledGameRules, nextEventTime) is not {} generatedEvent)
continue;
+
_chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", generatedEvent), ("seconds", (int)eventScheduler.TimeUntilNextEvent)));
// Cycle the stashed event with the new generated event and time.
- string? storedEvent = _next.UpdateNextEvent(nextEventComponent, generatedEvent, nextEventTime);
+ var storedEvent = _next.UpdateNextEvent(nextEventComponent, generatedEvent, nextEventTime);
if (string.IsNullOrEmpty(storedEvent)) //If there was no stored event don't try to run it.
continue;
+
GameTicker.AddGameRule(storedEvent);
continue;
}
- // DeltaV end events using NextEventComponent
+ // End DeltaV Additions: events using NextEventComponent
_event.RunRandomEvent(eventScheduler.ScheduledGameRules);
ResetTimer(eventScheduler);
diff --git a/Content.Server/StationEvents/EventManagerSystem.cs b/Content.Server/StationEvents/EventManagerSystem.cs
index eadacdbbadf..b865b9a34c9 100644
--- a/Content.Server/StationEvents/EventManagerSystem.cs
+++ b/Content.Server/StationEvents/EventManagerSystem.cs
@@ -11,8 +11,7 @@
using Content.Shared.EntityTable.EntitySelectors;
using Content.Shared.EntityTable;
using Content.Server.Psionics.Glimmer; // DeltaV
-using Content.Shared.Psionics.Glimmer;
-using System.Diagnostics.CodeAnalysis; // DeltaV
+using Content.Shared.Psionics.Glimmer; // DeltaV
namespace Content.Server.StationEvents;
@@ -60,67 +59,51 @@ public void RunRandomEvent()
///
public void RunRandomEvent(EntityTableSelector limitedEventsTable)
{
- if (TryGenerateRandomEvent(limitedEventsTable, out string? randomLimitedEvent)) // DeltaV - seperated into own method
+ if (TryGenerateRandomEvent(limitedEventsTable) is {} randomLimitedEvent) // DeltaV - seperated into own method
GameTicker.AddGameRule(randomLimitedEvent);
}
- // DeltaV - overloaded for backwards compatiblity
- public bool TryGenerateRandomEvent(EntityTableSelector limitedEventsTable, [NotNullWhen(true)] out string? randomLimitedEvent)
- {
- return TryGenerateRandomEvent(limitedEventsTable, out randomLimitedEvent, null);
- }
- // DeltaV - end overloaded for backwards compatiblity
-
- // DeltaV - separate event generation method
///
- /// Returns a random event from the list of events given that can be run at a given time.
+ /// DeltaV: Returns a random event from the list of events given that can be run at a given time.
///
/// The list of events that can be chosen.
- /// Generated event
/// The time to use for checking time restrictions. Uses current time if null.
- ///
- public bool TryGenerateRandomEvent(EntityTableSelector limitedEventsTable, [NotNullWhen(true)] out string? randomLimitedEvent, TimeSpan? eventRunTime)
+ /// The generated event id
+ ///
+ /// This is taken out of RunRandomEvent.
+ ///
+ public EntProtoId? TryGenerateRandomEvent(EntityTableSelector limitedEventsTable, TimeSpan? eventRunTime = null)
{
- randomLimitedEvent = null;
if (!TryBuildLimitedEvents(limitedEventsTable, out var limitedEvents, eventRunTime))
{
Log.Warning("Provided event table could not build dict!");
- return false;
+ return null;
}
- randomLimitedEvent = FindEvent(limitedEvents); // this picks the event, It might be better to use the GetSpawns to do it, but that will be a major rebalancing fuck.
- // DeltaV - randomLimitedEvent declared by enclosing method
+ var randomLimitedEvent = FindEvent(limitedEvents); // this picks the event, It might be better to use the GetSpawns to do it, but that will be a major rebalancing fuck.
if (randomLimitedEvent == null)
{
Log.Warning("The selected random event is null!");
- return false;
+ return null;
}
- if (!_prototype.TryIndex(randomLimitedEvent, out _))
+ if (!_prototype.HasIndex(randomLimitedEvent))
{
Log.Warning("A requested event is not available!");
- return false;
+ return null;
}
- return true;
+ return randomLimitedEvent;
}
- // DeltaV - end separate event generation method
-
- // DeltaV - overloaded for backwards compatiblity
- public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary limitedEvents)
- {
- return TryBuildLimitedEvents(limitedEventsTable, out limitedEvents, null);
- }
- // DeltaV - end overloaded for backwards compatiblity
///
/// Returns true if the provided EntityTableSelector gives at least one prototype with a StationEvent comp.
///
- public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary limitedEvents, TimeSpan? eventRunTime) // DeltaV - Add a time overide
+ public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary limitedEvents, TimeSpan? eventRunTime = null) // DeltaV - Add a time overide
{
limitedEvents = new Dictionary();
// DeltaV - Overide time for stashing events
- var availableEvents = AvailableEvents(eventRunTime); // handles the player counts and individual event restrictions
+ var availableEvents = AvailableEvents(eventRunTime: eventRunTime); // handles the player counts and individual event restrictions
if (availableEvents.Count == 0)
{
Log.Warning("No events were available to run!");
@@ -206,16 +189,6 @@ public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Di
return null;
}
- // DeltaV - overloaded for backwards compatiblity
- public Dictionary AvailableEvents(
- bool ignoreEarliestStart = false,
- int? playerCountOverride = null,
- TimeSpan? currentTimeOverride = null)
- {
- return AvailableEvents(null, ignoreEarliestStart, playerCountOverride, currentTimeOverride);
- }
- // DeltaV - end overloaded for backwards compatiblity
-
///
/// Gets the events that have met their player count, time-until start, etc.
///
@@ -223,20 +196,17 @@ public Dictionary AvailableEvents(
/// Override for round time, if using this to simulate events rather than in an actual round.
///
public Dictionary AvailableEvents(
- TimeSpan? eventRunTime,
bool ignoreEarliestStart = false,
int? playerCountOverride = null,
- TimeSpan? currentTimeOverride = null)
- {
+ TimeSpan? currentTimeOverride = null,
+ TimeSpan? eventRunTime = null) // DeltaV
+ {
var playerCount = playerCountOverride ?? _playerManager.PlayerCount;
// playerCount does a lock so we'll just keep the variable here
- var currentTime = currentTimeOverride ?? (
- (!ignoreEarliestStart
- ? eventRunTime // DeltaV - Use eventRunTime instead of RoundDuration if provided
- ?? GameTicker.RoundDuration()
- : TimeSpan.Zero)
- );
+ var currentTime = currentTimeOverride ?? (!ignoreEarliestStart
+ ? eventRunTime ?? GameTicker.RoundDuration() // DeltaV - Use eventRunTime instead of RoundDuration if provided
+ : TimeSpan.Zero);
var result = new Dictionary();
diff --git a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs
index 67c8f9fb5d4..9585b3b824a 100644
--- a/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs
+++ b/Content.Server/StationEvents/RampingStationEventSchedulerSystem.cs
@@ -43,15 +43,14 @@ protected override void Started(EntityUid uid, RampingStationEventSchedulerCompo
PickNextEventTime(uid, component);
- // DeltaV - end init NextEventComp
+ // Begin DeltaV Additions: init NextEventComp
if (TryComp(uid, out var nextEventComponent)
- && _event.TryGenerateRandomEvent(component.ScheduledGameRules, out string? firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent))
- && firstEvent != null)
+ && _event.TryGenerateRandomEvent(component.ScheduledGameRules, TimeSpan.FromSeconds(component.TimeUntilNextEvent)) is {} firstEvent)
{
_chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", firstEvent), ("seconds", (int)component.TimeUntilNextEvent)));
_next.UpdateNextEvent(nextEventComponent, firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent));
}
- // DeltaV - end init NextEventComp
+ // End DeltaV Additions: init NextEventComp
}
public override void Update(float frameTime)
@@ -73,22 +72,24 @@ public override void Update(float frameTime)
continue;
}
- // DeltaV events using NextEventComponent
+ // Begin DeltaV Additions: events using NextEventComponent
if (TryComp(uid, out var nextEventComponent)) // If there is a nextEventComponent use the stashed event instead of running it directly.
{
PickNextEventTime(uid, scheduler);
var nextEventTime = _timing.CurTime + TimeSpan.FromSeconds(scheduler.TimeUntilNextEvent);
- if (!_event.TryGenerateRandomEvent(scheduler.ScheduledGameRules, out string? generatedEvent, nextEventTime) || generatedEvent == null)
+ if (_event.TryGenerateRandomEvent(scheduler.ScheduledGameRules, nextEventTime) is not {} generatedEvent)
continue;
+
_chatManager.SendAdminAlert(Loc.GetString("station-event-system-run-event-delayed", ("eventName", generatedEvent), ("seconds", (int)scheduler.TimeUntilNextEvent)));
// Cycle the stashed event with the new generated event and time.
string? storedEvent = _next.UpdateNextEvent(nextEventComponent, generatedEvent, nextEventTime);
if (string.IsNullOrEmpty(storedEvent)) //If there was no stored event don't try to run it.
continue;
+
GameTicker.AddGameRule(storedEvent);
continue;
}
- // DeltaV end events using NextEventComponent
+ // End DeltaV Additions: events using NextEventComponent
PickNextEventTime(uid, scheduler);
_event.RunRandomEvent(scheduler.ScheduledGameRules);
diff --git a/Content.Shared/DeltaV/Abilities/Psionics/PrecognitionPowerComponent.cs b/Content.Shared/DeltaV/Abilities/Psionics/PrecognitionPowerComponent.cs
index 26ecf48f7aa..6f5f36086c6 100644
--- a/Content.Shared/DeltaV/Abilities/Psionics/PrecognitionPowerComponent.cs
+++ b/Content.Shared/DeltaV/Abilities/Psionics/PrecognitionPowerComponent.cs
@@ -1,17 +1,15 @@
using Content.Shared.DoAfter;
using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared.Abilities.Psionics;
-[RegisterComponent]
+[RegisterComponent, NetworkedComponent]
public sealed partial class PrecognitionPowerComponent : Component
{
[DataField]
- public float RandomResultChance = 0.2F;
-
- [DataField]
- public Dictionary AllResults;
+ public float RandomResultChance = 0.2f;
[DataField]
public SoundSpecifier VisionSound = new SoundPathSpecifier("/Audio/DeltaV/Effects/clang2.ogg");
diff --git a/Content.Shared/DeltaV/Abilities/Psionics/PrecognitionResultComponent.cs b/Content.Shared/DeltaV/Abilities/Psionics/PrecognitionResultComponent.cs
index 34a8979f4fa..059ada567ff 100644
--- a/Content.Shared/DeltaV/Abilities/Psionics/PrecognitionResultComponent.cs
+++ b/Content.Shared/DeltaV/Abilities/Psionics/PrecognitionResultComponent.cs
@@ -1,10 +1,13 @@
namespace Content.Shared.Abilities.Psionics;
+///
+/// Component added to game rules that lets it be shown with the precognition psionic power.
+///
[RegisterComponent]
public sealed partial class PrecognitionResultComponent : Component
{
- [DataField]
- public string Message = default!;
+ [DataField(required: true)]
+ public LocId Message;
[DataField]
public float Weight = 1;
diff --git a/Content.Shared/DeltaV/Psionics/Events.cs b/Content.Shared/DeltaV/Psionics/Events.cs
new file mode 100644
index 00000000000..ce5b680a118
--- /dev/null
+++ b/Content.Shared/DeltaV/Psionics/Events.cs
@@ -0,0 +1,10 @@
+using Content.Shared.DoAfter;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Psionics.Events;
+
+[Serializable, NetSerializable]
+public sealed partial class PrecognitionDoAfterEvent : SimpleDoAfterEvent;
+
+[Serializable, NetSerializable]
+public sealed partial class GlimmerWispDrainDoAfterEvent : SimpleDoAfterEvent;
diff --git a/Content.Shared/Nyanotrasen/Psionics/Events.cs b/Content.Shared/Nyanotrasen/Psionics/Events.cs
index 3837e3d0ee9..c54dc48de8d 100644
--- a/Content.Shared/Nyanotrasen/Psionics/Events.cs
+++ b/Content.Shared/Nyanotrasen/Psionics/Events.cs
@@ -1,48 +1,21 @@
-using Robust.Shared.Serialization;
using Content.Shared.DoAfter;
+using Robust.Shared.Serialization;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
-namespace Content.Shared.Psionics.Events
-{
- [Serializable, NetSerializable]
- public sealed partial class PsionicRegenerationDoAfterEvent : DoAfterEvent
- {
- [DataField("startedAt", required: true)]
- public TimeSpan StartedAt;
-
- private PsionicRegenerationDoAfterEvent()
- {
- }
-
- public PsionicRegenerationDoAfterEvent(TimeSpan startedAt)
- {
- StartedAt = startedAt;
- }
+namespace Content.Shared.Psionics.Events;
- public override DoAfterEvent Clone() => this;
- }
+[Serializable, NetSerializable]
+public sealed partial class PsionicRegenerationDoAfterEvent : SimpleDoAfterEvent
+{
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan StartedAt;
- // DeltaV Precognition
- [Serializable, NetSerializable]
- public sealed partial class PrecognitionDoAfterEvent : SimpleDoAfterEvent
+ private PsionicRegenerationDoAfterEvent()
{
- [DataField("startedAt", required: true)]
- public TimeSpan StartedAt;
-
- private PrecognitionDoAfterEvent()
- {
- }
-
- public PrecognitionDoAfterEvent(TimeSpan startedAt)
- {
- StartedAt = startedAt;
- }
-
- public override DoAfterEvent Clone() => this;
}
- // DeltaV End Precognition
- [Serializable, NetSerializable]
- public sealed partial class GlimmerWispDrainDoAfterEvent : SimpleDoAfterEvent
+ public PsionicRegenerationDoAfterEvent(TimeSpan startedAt)
{
+ StartedAt = startedAt;
}
}
diff --git a/Resources/Locale/en-US/deltav/abilities/psionic.ftl b/Resources/Locale/en-US/deltav/abilities/psionic.ftl
index 677c0b19def..8d6ab750383 100644
--- a/Resources/Locale/en-US/deltav/abilities/psionic.ftl
+++ b/Resources/Locale/en-US/deltav/abilities/psionic.ftl
@@ -9,7 +9,7 @@ psionic-power-precognition-fugitive-result-message = You see hounds around every
psionic-power-precognition-syndicate-recruiter-result-message = You see someone cutting ties on a chain-link fence and reforging its now disparate parts under a new oath of blood.
psionic-power-precognition-synthesis-specialist-result-message = You smell a dangerous mixture of chemicals in the air; the distant sound of a small plasma engine roars to life.
psionic-power-precognition-cargo-gifts-base-result-message = You see a vision of yourself, gathered for a time-old tradition of receiving gifts. You didn't ask for these, but you must pretend to appreciate nonetheless.
-psionic-power-precognition-anomoly-spawn-result-message = You attempt to look forward, but the future is distorted by a blast of noöspheric energies converging on a single point.
+psionic-power-precognition-anomaly-spawn-result-message = You attempt to look forward, but the future is distorted by a blast of noöspheric energies converging on a single point.
psionic-power-precognition-bluespace-artifact-result-message = You attempt to look forward but are blinded by noöspheric energies coalescing into an object beyond comprehension.
psionic-power-precognition-bluespace-locker-result-message = You attempt to look forward, but the noösphere seems distorted by a constantly shifting bluespace energy.
psionic-power-precognition-breaker-flip-result-message = You see torches snuff around you and keepers rekindling the lost flames.
@@ -18,14 +18,14 @@ psionic-power-precognition-clerical-error-result-message = You see faces you onc
psionic-power-precognition-closet-skeleton-result-message = You hear a crackling laugh echo and clinking bones in the dusty recesses of the station.
psionic-power-precognition-dragon-spawn-result-message = Reality around you bulges and breaks as a great beast cries for war. The smell of salty sea and blood fills the air.
psionic-power-precognition-ninja-spawn-result-message = You see a vision of shadows brought to life, hounds of war howling their cries as they chase it through dark corners of the station.
-psionic-power-precognition-revenant-spawn-result-message = The shadows around you grow threefold taller and threefold darker. Something lurks within them, a predator stalking you in the darkness.
+psionic-power-precognition-revenant-spawn-result-message = The shadows around you grow threefold taller and threefold darker. Something lurks within them, a predator stalking you in the darkness.
psionic-power-precognition-gas-leak-result-message = For but a moment, it feels as if you cannot breathe. With a blink, everything returns to normal.
psionic-power-precognition-kudzu-growth-result-message = Leaves and vines pierce through the dusty tiles of the station, crawling about your ankles, trying to drag you down with them.
psionic-power-precognition-power-grid-check-result-message = You see torches snuff around you only to spontaneously ignite moments later.
psionic-power-precognition-solar-flare-result-message = The stars look beautiful tonight, shrinking and growing and shooting great bolts like fireworks into the sky.
psionic-power-precognition-vent-clog-result-message = You smell something horrific on the artificial breeze of the station, for a moment your eyes fill with fog. When you blink it away, the smell is gone.
psionic-power-precognition-slimes-spawn-result-message = Something lurks deep within the darkest corners of the station, crying for blood. Soft squelches and bubbling howls accompany the call.
-psionic-power-precognition-snake-spawn-result-message = Something lurks deep within the darkest corners of the station, crying for blood. The sounds of hissing growls accompany the call.
+psionic-power-precognition-snake-spawn-result-message = Something lurks deep within the darkest corners of the station, crying for blood. The sounds of hissing growls accompany the call.
psionic-power-precognition-spider-spawn-result-message = Something lurks deep within the darkest corners of the station, crying for blood. A symphony of clicks and chitters accompanies the call.
psionic-power-precognition-spider-clown-spawn-result-message = Something lurks deep within the darkest corners of the station, crying for blood. An unholy mass of honks accompanies the call.
psionic-power-precognition-zombie-outbreak-result-message = Your coworker lies on the cold ground before you; skull ripped open, eyes blank. You think you see the body twitch.
diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml
index b22bc621c80..1d6bebb6963 100644
--- a/Resources/Prototypes/GameRules/events.yml
+++ b/Resources/Prototypes/GameRules/events.yml
@@ -84,7 +84,7 @@
weight: 12 # DeltaV - was 8
duration: 35
- type: PrecognitionResult # DeltaV - Precogniton
- message: psionic-power-precognition-anomoly-spawn-result-message
+ message: psionic-power-precognition-anomaly-spawn-result-message
- type: AnomalySpawnRule
- type: entity