New psionic ablility: Precognition (#2131)

* TESTING enable events for dev enviroment

* Add NextEventComponent

* Check for schedulers NextEventComponent

* Seperate gernateing event to its own method

* Add NextEventSystem and use in BasicStationEventSchedulerSystem

* TESTING: Override time and player restrictions

* Stash events in NextEventComponent (#1)

* Add NextEventComponent

* Check for schedulers NextEventComponent

* Seperate gernateing event to its own method

* Add NextEventSystem and use in BasicStationEventSchedulerSystem

* Format code

* Add nextEvent time perdiction

* Use RunTime instead of float minutes

* Bug fixes

* Add NextEvent to Ramping and Meteors

* Fix timing on BasticStationEvents

* initialize NextEventComponent when created

* Event scheduler caching (#2)

* Check for schedulers NextEventComponent

* Seperate gernateing event to its own method

* Add NextEventSystem and use in BasicStationEventSchedulerSystem

* Format code

* Add nextEvent time perdiction

* Use RunTime instead of float minutes

* Bug fixes

* Add NextEvent to Ramping and Meteors

* Fix timing on BasticStationEvents

* initialize NextEventComponent when created

---------

Signed-off-by: SolStar <44028047+ewokswagger@users.noreply.github.com>

* Revert "Event scheduler caching (#2)"

This reverts commit bf9cd26ed4.

* Revert "Merge branch 'seer' into stash-next-event"

This reverts commit 656ca26173, reversing
changes made to 36f45be10e.

* Revert "Caching next exent"

This reverts commit 9f1bee4131, reversing
changes made to 82678d9c18.

* Reapply "Event scheduler caching (#2)"

This reverts commit 82678d9c18.

* More merge conflict nonsence

* oops

* oops 2

* Oops 3

* Precognition Psionic ability (#3)

* Precognition ability added

* Precog get next event

* Get soonest event and display

* update prototypes with precog results

* Add random

* Use Timespan for UseDelay

* Damage breaks doafter

* typo

* fix localization

* fix do after

* Add effects durring do after

* Revert "TESTING enable events for dev enviroment"

This reverts commit 03453133bd.

* Revert testing changes

* add deltav comments

* Cleaning up!

* Move NextEvent to server space

* Fix NextEventId init value

* Reverted upstream file to block scoped namespace

* Add precognitnon result messages

* reverting testing changes for real

* Add admin alert for upcoming events

* Add sound effect

* make alert more subtule

* extended max window size

* fix message mixup

* yaml fixes

* more yaml fixes

* Delta Changes

* totaly a yaml error trust

* remove unsessesary weights

---------

Signed-off-by: SolStar <44028047+ewokswagger@users.noreply.github.com>
This commit is contained in:
SolStar 2024-12-18 22:55:15 -05:00 committed by GitHub
parent 6e72bdebb6
commit d5716a8d41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 637 additions and 16 deletions

View File

@ -0,0 +1,232 @@
using Content.Server.Chat.Managers;
using Content.Server.DoAfter;
using Content.Server.DeltaV.StationEvents.NextEvent;
using Content.Server.GameTicking;
using Content.Server.Mind;
using Content.Shared.Abilities.Psionics;
using Content.Shared.Actions.Events;
using Content.Shared.Actions;
using Content.Shared.DoAfter;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Popups;
using Content.Shared.Psionics.Events;
using Content.Shared.StatusEffect;
using Content.Shared.Stunnable;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Player;
namespace Content.Server.Abilities.Psionics;
public sealed class PrecognitionPowerSystem : EntitySystem
{
[Dependency] private readonly DoAfterSystem _doAfterSystem = 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 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 IRobustRandom _random = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PrecognitionPowerComponent, MapInitEvent>(OnMapInit);
SubscribeLocalEvent<PrecognitionPowerComponent, ComponentShutdown>(OnShutdown);
SubscribeLocalEvent<PrecognitionPowerComponent, PrecognitionPowerActionEvent>(OnPowerUsed);
SubscribeLocalEvent<PrecognitionPowerComponent, PrecognitionDoAfterEvent>(OnDoAfter);
}
private void OnMapInit(Entity<PrecognitionPowerComponent> 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<PsionicComponent>(ent, out var psionic) && psionic.PsionicAbility == null)
{
psionic.PsionicAbility = ent.Comp.PrecognitionActionEntity;
psionic.ActivePowers.Add(ent.Comp);
}
}
private void OnShutdown(EntityUid uid, PrecognitionPowerComponent component, ComponentShutdown args)
{
_actions.RemoveAction(uid, component.PrecognitionActionEntity);
if (TryComp<PsionicComponent>(uid, out var psionic))
psionic.ActivePowers.Remove(component);
}
private void OnPowerUsed(EntityUid uid, PrecognitionPowerComponent component, PrecognitionPowerActionEvent args)
{
var ev = new PrecognitionDoAfterEvent(_gameTiming.CurTime);
var doAfterArgs = new DoAfterArgs(EntityManager, uid, component.UseDelay, ev, uid)
{
BreakOnDamage = true
};
// A custom shader for seeing visions would be nice but this will do for now.
_statusEffects.TryAddStatusEffect<TemporaryBlindnessComponent>(uid, "TemporaryBlindness", component.UseDelay, true);
_statusEffects.TryAddStatusEffect<SlowedDownComponent>(uid, "SlowedDown", component.UseDelay, true);
_doAfterSystem.TryStartDoAfter(doAfterArgs, out var doAfterId);
component.DoAfter = doAfterId;
var player = _audio.PlayGlobal(component.VisionSound, Filter.Entities(uid), true);
if (player != null)
component.SoundStream = player.Value.Entity;
_psionics.LogPowerUsed(uid, "Precognition");
args.Handled = true;
}
/// <summary>
/// Upon completion will send a message to the user corrosponding to the next station event to occour.
/// </summary>
/// <param name="uid"></param>
/// <param name="component"></param>
/// <param name="args"></param>
private void OnDoAfter(EntityUid uid, PrecognitionPowerComponent component, PrecognitionDoAfterEvent args)
{
if (args.Handled)
return;
if (args.Cancelled)
{
// Need to clean up the applied effects in case of cancel and alert the player.
component.SoundStream = _audio.Stop(component.SoundStream);
_statusEffects.TryRemoveStatusEffect(uid, "TemporaryBlindness");
_statusEffects.TryRemoveStatusEffect(uid, "SlowedDown");
_popups.PopupEntity(
Loc.GetString("psionic-power-precognition-failure-by-damage"),
uid,
uid,
PopupType.SmallCaution);
if (_actions.TryGetActionData(component.PrecognitionActionEntity, out var actionData))
// If canceled give a short delay before being able to try again
actionData.Cooldown =
(_gameTicker.RoundDuration(),
_gameTicker.RoundDuration() + TimeSpan.FromSeconds(15));
return;
}
// 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);
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.
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);
component.DoAfter = null;
}
/// <summary>
/// Gets the precognition result message corosponding to the passed event id.
/// </summary>
/// <returns>message string corosponding to the event id passed</returns>
private string GetResultMessage(EntProtoId? eventId, PrecognitionPowerComponent component)
{
foreach (var (eventProto, precognitionResult) in component.AllResults)
{
if (eventProto.ID == eventId && precognitionResult != null)
return precognitionResult.Message;
}
Log.Error($"Prototype {eventId} does not have an associated precognitionResult!");
return string.Empty;
}
/// <summary>
/// </summary>
/// <returns>The localized string of a weighted randomly chosen precognition result</returns>
public string? GetRandomResult()
{
var precognitionResults = GetAllPrecognitionResults();
var sumOfWeights = 0;
foreach (var precognitionResult in precognitionResults.Values)
sumOfWeights += (int)precognitionResult.Weight;
sumOfWeights = _random.Next(sumOfWeights);
foreach (var precognitionResult in precognitionResults.Values)
{
sumOfWeights -= (int)precognitionResult.Weight;
if (sumOfWeights <= 0)
return precognitionResult.Message;
}
Log.Error("Result was not found after weighted pick process!");
return null;
}
/// <summary>
/// Gets the soonest nextEvent to occur within the window.
/// </summary>
/// <param name="minDetectWindow"></param> The earliest reletive time that will be return a nextEvent
/// <param name="maxDetectWindow"></param> The latest reletive latest time that will be return a nextEvent
/// <returns>Component for the next event to occour if one exists in the window.</returns>
private NextEventComponent? FindEarliestNextEvent(TimeSpan minDetectWindow, TimeSpan maxDetectWindow)
{
TimeSpan? earliestNextEventTime = null;
NextEventComponent? earliestNextEvent = null;
var query = EntityQueryEnumerator<NextEventComponent>();
while (query.MoveNext(out var nextEventComponent))
{
// Update if the event is the most recent event that isnt too close or too far from happening to be of use
if (nextEventComponent.NextEventTime > _gameTicker.RoundDuration() + minDetectWindow
&& nextEventComponent.NextEventTime < _gameTicker.RoundDuration() + maxDetectWindow
&& earliestNextEvent == null
|| nextEventComponent.NextEventTime < earliestNextEventTime)
earliestNextEvent ??= nextEventComponent;
}
return earliestNextEvent;
}
public Dictionary<EntityPrototype, PrecognitionResultComponent> GetAllPrecognitionResults()
{
var allEvents = new Dictionary<EntityPrototype, PrecognitionResultComponent>();
foreach (var prototype in _prototype.EnumeratePrototypes<EntityPrototype>())
{
if (prototype.Abstract)
continue;
if (!prototype.TryGetComponent<PrecognitionResultComponent>(out var precognitionResult, _factory))
continue;
allEvents.Add(prototype, precognitionResult);
}
return allEvents;
}
}

View File

@ -0,0 +1,19 @@
using Robust.Shared.Prototypes;
namespace Content.Server.DeltaV.StationEvents.NextEvent;
[RegisterComponent, Access(typeof(NextEventSystem))]
public sealed partial class NextEventComponent : Component
{
/// <summary>
/// Id of the next event that will be run by EventManagerSystem.
/// </summary>
[DataField]
public EntProtoId? NextEventId;
/// <summary>
/// Round time of the scheduler's next station event.
/// </summary>
[DataField]
public TimeSpan NextEventTime;
}

View File

@ -0,0 +1,18 @@
using Content.Server.DeltaV.StationEvents.NextEvent;
using Robust.Shared.Prototypes;
namespace Content.Server.DeltaV.StationEvents.NextEvent;
public sealed class NextEventSystem : EntitySystem
{
/// <summary>
/// Updates the NextEventComponent with the provided id and time and returns the previously stored id.
/// </summary>
public EntProtoId? UpdateNextEvent(NextEventComponent component, EntProtoId newEventId, TimeSpan newEventTime)
{
EntProtoId? oldEventId = component.NextEventId; // Store components current NextEventId for return
component.NextEventId = newEventId;
component.NextEventTime = newEventTime;
return oldEventId;
}
}

View File

@ -1,5 +1,7 @@
using System.Linq;
using Content.Server.Administration;
using Content.Server.Chat.Managers; // DeltaV
using Content.Server.DeltaV.StationEvents.NextEvent; // DeltaV
using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
using Content.Server.StationEvents.Components;
@ -9,6 +11,7 @@ using Content.Shared.GameTicking.Components;
using JetBrains.Annotations;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing; // DeltaV
using Robust.Shared.Toolshed;
using Robust.Shared.Utility;
@ -21,14 +24,27 @@ namespace Content.Server.StationEvents
[UsedImplicitly]
public sealed class BasicStationEventSchedulerSystem : GameRuleSystem<BasicStationEventSchedulerComponent>
{
[Dependency] private readonly IChatManager _chatManager = default!; // DeltaV
[Dependency] private readonly IGameTiming _timing = default!; // DeltaV
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly EventManagerSystem _event = default!;
[Dependency] private readonly NextEventSystem _next = default!; // DeltaV
protected override void Started(EntityUid uid, BasicStationEventSchedulerComponent component, GameRuleComponent gameRule,
GameRuleStartedEvent args)
{
// A little starting variance so schedulers dont all proc at once.
component.TimeUntilNextEvent = RobustRandom.NextFloat(component.MinimumTimeUntilFirstEvent, component.MinimumTimeUntilFirstEvent + 120);
// DeltaV - end init NextEventComp
if (TryComp<NextEventComponent>(uid, out var nextEventComponent)
&& _event.TryGenerateRandomEvent(component.ScheduledGameRules, out string? firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent))
&& firstEvent != null)
{
_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
}
protected override void Ended(EntityUid uid, BasicStationEventSchedulerComponent component, GameRuleComponent gameRule,
@ -57,6 +73,23 @@ namespace Content.Server.StationEvents
continue;
}
// DeltaV events using NextEventComponent
if (TryComp<NextEventComponent>(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))
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);
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
_event.RunRandomEvent(eventScheduler.ScheduledGameRules);
ResetTimer(eventScheduler);
}

View File

@ -11,7 +11,8 @@ using Robust.Shared.Random;
using Content.Shared.EntityTable.EntitySelectors;
using Content.Shared.EntityTable;
using Content.Server.Psionics.Glimmer; // DeltaV
using Content.Shared.Psionics.Glimmer; // DeltaV
using Content.Shared.Psionics.Glimmer;
using System.Diagnostics.CodeAnalysis; // DeltaV
namespace Content.Server.StationEvents;
@ -59,37 +60,67 @@ public sealed class EventManagerSystem : EntitySystem
/// </summary>
public void RunRandomEvent(EntityTableSelector limitedEventsTable)
{
if (!TryBuildLimitedEvents(limitedEventsTable, out var limitedEvents))
if (TryGenerateRandomEvent(limitedEventsTable, out string? 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
/// <summary>
/// Returns a random event from the list of events given that can be run at a given time.
/// </summary>
/// <param name="limitedEventsTable">The list of events that can be chosen.</param>
/// <param name="randomLimitedEvent">Generated event</param>
/// <param name="eventRunTime">The time to use for checking time restrictions. Uses current time if null.</param>
/// <returns></returns>
public bool TryGenerateRandomEvent(EntityTableSelector limitedEventsTable, [NotNullWhen(true)] out string? randomLimitedEvent, TimeSpan? eventRunTime)
{
randomLimitedEvent = null;
if (!TryBuildLimitedEvents(limitedEventsTable, out var limitedEvents, eventRunTime))
{
Log.Warning("Provided event table could not build dict!");
return;
return false;
}
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.
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
if (randomLimitedEvent == null)
{
Log.Warning("The selected random event is null!");
return;
return false;
}
if (!_prototype.TryIndex(randomLimitedEvent, out _))
{
Log.Warning("A requested event is not available!");
return;
return false;
}
GameTicker.AddGameRule(randomLimitedEvent);
return true;
}
// DeltaV - end separate event generation method
// DeltaV - overloaded for backwards compatiblity
public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary<EntityPrototype, StationEventComponent> limitedEvents)
{
return TryBuildLimitedEvents(limitedEventsTable, out limitedEvents, null);
}
// DeltaV - end overloaded for backwards compatiblity
/// <summary>
/// Returns true if the provided EntityTableSelector gives at least one prototype with a StationEvent comp.
/// </summary>
public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary<EntityPrototype, StationEventComponent> limitedEvents)
public bool TryBuildLimitedEvents(EntityTableSelector limitedEventsTable, out Dictionary<EntityPrototype, StationEventComponent> limitedEvents, TimeSpan? eventRunTime) // DeltaV - Add a time overide
{
limitedEvents = new Dictionary<EntityPrototype, StationEventComponent>();
var availableEvents = AvailableEvents(); // handles the player counts and individual event restrictions
// DeltaV - Overide time for stashing events
var availableEvents = AvailableEvents(eventRunTime); // handles the player counts and individual event restrictions
if (availableEvents.Count == 0)
{
Log.Warning("No events were available to run!");
@ -175,6 +206,16 @@ public sealed class EventManagerSystem : EntitySystem
return null;
}
// DeltaV - overloaded for backwards compatiblity
public Dictionary<EntityPrototype, StationEventComponent> AvailableEvents(
bool ignoreEarliestStart = false,
int? playerCountOverride = null,
TimeSpan? currentTimeOverride = null)
{
return AvailableEvents(null, ignoreEarliestStart, playerCountOverride, currentTimeOverride);
}
// DeltaV - end overloaded for backwards compatiblity
/// <summary>
/// Gets the events that have met their player count, time-until start, etc.
/// </summary>
@ -182,6 +223,7 @@ public sealed class EventManagerSystem : EntitySystem
/// <param name="currentTimeOverride">Override for round time, if using this to simulate events rather than in an actual round.</param>
/// <returns></returns>
public Dictionary<EntityPrototype, StationEventComponent> AvailableEvents(
TimeSpan? eventRunTime,
bool ignoreEarliestStart = false,
int? playerCountOverride = null,
TimeSpan? currentTimeOverride = null)
@ -189,9 +231,12 @@ public sealed class EventManagerSystem : EntitySystem
var playerCount = playerCountOverride ?? _playerManager.PlayerCount;
// playerCount does a lock so we'll just keep the variable here
var currentTime = currentTimeOverride ?? (!ignoreEarliestStart
? GameTicker.RoundDuration()
: TimeSpan.Zero);
var currentTime = currentTimeOverride ?? (
(!ignoreEarliestStart
? eventRunTime // DeltaV - Use eventRunTime instead of RoundDuration if provided
?? GameTicker.RoundDuration()
: TimeSpan.Zero)
);
var result = new Dictionary<EntityPrototype, StationEventComponent>();

View File

@ -1,16 +1,22 @@
using Content.Server.Chat.Managers; // DeltaV
using Content.Server.DeltaV.StationEvents.NextEvent; // DeltaV
using Content.Server.GameTicking;
using Content.Server.GameTicking.Rules;
using Content.Server.StationEvents.Components;
using Content.Shared.GameTicking.Components;
using Robust.Shared.Random;
using Robust.Shared.Timing; // DeltaV
namespace Content.Server.StationEvents;
public sealed class RampingStationEventSchedulerSystem : GameRuleSystem<RampingStationEventSchedulerComponent>
{
[Dependency] private readonly IChatManager _chatManager = default!; // DeltaV
[Dependency] private readonly IGameTiming _timing = default!; // DeltaV
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly EventManagerSystem _event = default!;
[Dependency] private readonly GameTicker _gameTicker = default!;
[Dependency] private readonly NextEventSystem _next = default!; // DeltaV
/// <summary>
/// Returns the ChaosModifier which increases as round time increases to a point.
@ -36,6 +42,16 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem<RampingS
component.StartingChaos = component.MaxChaos / 10;
PickNextEventTime(uid, component);
// DeltaV - end init NextEventComp
if (TryComp<NextEventComponent>(uid, out var nextEventComponent)
&& _event.TryGenerateRandomEvent(component.ScheduledGameRules, out string? firstEvent, TimeSpan.FromSeconds(component.TimeUntilNextEvent))
&& firstEvent != null)
{
_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
}
public override void Update(float frameTime)
@ -57,6 +73,23 @@ public sealed class RampingStationEventSchedulerSystem : GameRuleSystem<RampingS
continue;
}
// DeltaV events using NextEventComponent
if (TryComp<NextEventComponent>(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)
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
PickNextEventTime(uid, scheduler);
_event.RunRandomEvent(scheduler.ScheduledGameRules);
}

View File

@ -0,0 +1,33 @@
using Content.Shared.DoAfter;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
namespace Content.Shared.Abilities.Psionics;
[RegisterComponent]
public sealed partial class PrecognitionPowerComponent : Component
{
[DataField]
public float RandomResultChance = 0.2F;
[DataField]
public Dictionary<EntityPrototype, PrecognitionResultComponent> AllResults;
[DataField]
public SoundSpecifier VisionSound = new SoundPathSpecifier("/Audio/DeltaV/Effects/clang2.ogg");
[DataField]
public EntityUid? SoundStream;
[DataField]
public DoAfterId? DoAfter;
[DataField]
public TimeSpan UseDelay = TimeSpan.FromSeconds(8.35); // The length of the sound effect
[DataField]
public EntProtoId PrecognitionActionId = "ActionPrecognition";
[DataField]
public EntityUid? PrecognitionActionEntity;
}

View File

@ -0,0 +1,11 @@
namespace Content.Shared.Abilities.Psionics;
[RegisterComponent]
public sealed partial class PrecognitionResultComponent : Component
{
[DataField]
public string Message = default!;
[DataField]
public float Weight = 1;
}

View File

@ -0,0 +1,3 @@
namespace Content.Shared.Actions.Events;
public sealed partial class PrecognitionPowerActionEvent : InstantActionEvent;

View File

@ -21,6 +21,26 @@ namespace Content.Shared.Psionics.Events
public override DoAfterEvent Clone() => this;
}
// DeltaV Precognition
[Serializable, NetSerializable]
public sealed partial class PrecognitionDoAfterEvent : SimpleDoAfterEvent
{
[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
{

View File

@ -0,0 +1,46 @@
psionic-power-precognition-failure-by-damage = Your concentration was broken! You fail to decipher anything of use.
psionic-power-precognition-no-event-result-message = You see a vision of an undisturbed lake.
psionic-power-precognition-xeno-vents-result-message = You see a vision, peering around a corner you see a strange, squelching beast tear at the insides of one of your coworkers as they let out a bloodcurdling scream.
psionic-power-precognition-mothroach-spawn-result-message = You see a hungering mass of newborns, chittering and screeching as they sink their mandibles into the station's knitwork.
psionic-power-precognition-listening-post-result-message = you hear a cacophony of foreign voices speaking over radio static; you wake with a creeping sense of paranoia.
psionic-power-precognition-paradox-anomaly-result-message = You see your coworker splitting in two. Where there was one, there are now two. You are unsure which of the beings is truly your coworker.
psionic-power-precognition-fugitive-result-message = You see hounds around every corner all hunting for someone who does not belong.
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-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.
psionic-power-precognition-bureaucratic-error-result-message = You see a vision of yourself trapped in a room, trying to solve a puzzle with both missing and duplicate pieces.
psionic-power-precognition-clerical-error-result-message = You see faces you once knew being obscured in a fog of static, identities lost.
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-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-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.
psionic-power-precognition-lone-ops-spawn-result-message = You see a vision of a beast with a blood-red carapace, laughing as it eats through the station, bite by bite.
psionic-power-precognition-sleeper-agents-result-message = You see a vision of life through the eyes of a non-descript coworker, a soft but dangerous buzzing accompanies you at the base of their skull. It sounds like radio static.
psionic-power-precognition-mass-hallucinations-result-message = You attempt to see a vision of the future, but all you see is a phantasmagoria of chaotic shapes.
psionic-power-precognition-ion-storm-result-message = You see a vision of the rigid being destroyed and reshaped into something new and wrong.
psionic-power-precognition-meteor-swarm-result-message = You see a fiery vision of shooting stars falling from the sky, colorful trails shooting through the station you call home.
psionic-power-precognition-game-rule-urist-swarm-result-message = You see a fiery vision of... PEOPLE falling from the sky! colorful trails shooting through the station you call home.
psionic-power-precognition-immovable-rod-spawn-result-message = You see a fiery vision of a MASSIVE star falling from the sky! colorful trails shooting through the station you call home.
psionic-power-precognition-mouse-migration-result-message = You see a vision of living as a simplistic creature, scurrying underfoot of creatures beyond your comprehension.
psionic-power-precognition-king-rat-migration-result-message = You see a vision of living as a simplistic creature, scurrying underfoot of creatures beyond your comprehension.
psionic-power-precognition-cockroach-migration-result-message = You see a vision of living as a simplistic creature, scurrying underfoot of creatures beyond your comprehension.
psionic-power-precognition-snail-migration-result-message = You see a vision of living as a simplistic creature, scurrying underfoot of creatures beyond your comprehension.
psionic-power-precognition-random-sentience-result-message = Something bright and beautiful sparks to life within your third eye. Nothing brings wonder quite like new life.
psionic-power-precognition-unknown-shuttle-cargo-lost-result-message = You see a vision of a simple ship of old Terra, adrift of the sea, far away from home.
psionic-power-precognition-unknown-shuttle-traveling-cuisine-result-message = You see a vision of peace, a cozy meal sizzling on a warm stove. A delicious smells wafts through the air.
psionic-power-precognition-unknown-shuttle-disaster-evac-pod-result-message = You see a vision of death and blood, of a destruction so complete only few survive, drifting through the coldness of space.

View File

@ -0,0 +1 @@
station-event-system-run-event-delayed = Running event {$eventName} in {$seconds} seconds

View File

@ -1,4 +1,4 @@
- type: entity
- type: entity
id: ActionOpenRadioImplant
name: Open Radio Implant
description: Opens the bluespace key compartment of the radio implant embedded in your skull.
@ -34,3 +34,17 @@
sprite: Structures/Furniture/Tables/generic.rsi
state: full
event: !type:ToggleCrawlingStateEvent
- type: entity
id: ActionPrecognition
name: Precognition
description: See into the future to get a hint about the next random event.
components:
- type: InstantAction
icon:
sprite: DeltaV/Interface/Actions/actions_psionics.rsi
state: precognition
useDelay: 240
checkCanInteract: false
checkConsciousness: false
event: !type:PrecognitionPowerActionEvent

View File

@ -30,6 +30,8 @@
params:
volume: -4
duration: null #ending is handled by MeteorSwarmRule
- type: PrecognitionResult
message: psionic-power-precognition-meteor-swarm-result-message
- type: MeteorSwarmRule
- type: entity
@ -44,6 +46,8 @@
minimumPlayers: 20
weight: 1
duration: 60
- type: PrecognitionResult
message: psionic-power-precognition-xeno-vents-result-message
- type: VentCrittersRule
entries:
- id: MobXeno
@ -72,6 +76,8 @@
minimumPlayers: 15
weight: 4
duration: 60
- type: PrecognitionResult
message: psionic-power-precognition-mothroach-spawn-result-message
- type: VentCrittersRule
entries:
- id: MobMothroach
@ -87,6 +93,8 @@
minimumPlayers: 25
maxOccurrences: 1
duration: null
- type: PrecognitionResult
message: psionic-power-precognition-listening-post-result-message
- type: RuleGrids
- type: LoadFarGridRule
path: /Maps/Shuttles/DeltaV/listening_post.yml
@ -146,6 +154,8 @@
components:
- type: StationEvent
duration: null
- type: PrecognitionResult
message: psionic-power-precognition-paradox-anomaly-result-message
- type: ParadoxClonerRule
- type: AntagObjectives
objectives:
@ -169,6 +179,8 @@
- type: StationEvent
minimumPlayers: 40 # it's really easy to find fugitives on lowpop
duration: null
- type: PrecognitionResult
message: psionic-power-precognition-fugitive-result-message
- type: FugitiveRule
- type: AntagLoadProfileRule
- type: AntagObjectives

View File

@ -17,6 +17,7 @@
parent: BaseGameRule
id: GlimmerEventScheduler
components:
- type: NextEvent
- type: BasicStationEventScheduler
minMaxEventTiming:
min: 300

View File

@ -14,6 +14,8 @@
minimumPlayers: 20
maxOccurrences: 1
duration: null
- type: PrecognitionResult
message: psionic-power-precognition-syndicate-recruiter-result-message
- type: RuleGrids
- type: LoadMapRule
preloadedGrid: SyndieRecruiterShip
@ -56,6 +58,8 @@
minimumPlayers: 20
maxOccurrences: 1
duration: null
- type: PrecognitionResult
message: psionic-power-precognition-synthesis-specialist-result-message
- type: RuleGrids
- type: LoadMapRule
preloadedGrid: SyndieSynthesisShip

View File

@ -26,6 +26,8 @@
delay:
min: 10
max: 10
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-cargo-gifts-base-result-message
- type: StationEvent
startColor: "#18abf5"
startAudio:

View File

@ -83,6 +83,8 @@
path: /Audio/Announcements/announce.ogg
weight: 12 # DeltaV - was 8
duration: 35
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-anomoly-spawn-result-message
- type: AnomalySpawnRule
- type: entity
@ -99,6 +101,8 @@
path: /Audio/Announcements/announce.ogg
weight: 8
duration: 35
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-bluespace-artifact-result-message
- type: BluespaceArtifactRule
- type: entity
@ -110,6 +114,8 @@
reoccurrenceDelay: 5
earliestStart: 1
duration: 1
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-bluespace-locker-result-message
- type: BluespaceLockerRule
- type: entity
@ -120,6 +126,8 @@
weight: 10
duration: 1
minimumPlayers: 15
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-breaker-flip-result-message
- type: BreakerFlipRule
- type: entity
@ -133,6 +141,8 @@
minimumPlayers: 25
weight: 5
duration: 1
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-bureaucratic-error-result-message
- type: BureaucraticErrorRule
ignoredJobs:
- StationAi
@ -146,6 +156,8 @@
minimumPlayers: 15
weight: 5
duration: 1
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-clerical-error-result-message
- type: ClericalErrorRule
- type: entity
@ -156,6 +168,8 @@
weight: 8 # DeltaV - was 10
duration: 1
minimumPlayers: 10
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-closet-skeleton-result-message
- type: RandomEntityStorageSpawnRule
prototype: MobSkeletonCloset
@ -169,6 +183,8 @@
reoccurrenceDelay: 20
minimumPlayers: 45 # DeltaV - was 20
duration: null
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-dragon-spawn-result-message
- type: SpaceSpawnRule
spawnDistance: 0
- type: AntagSpawner
@ -198,6 +214,8 @@
earliestStart: 30
reoccurrenceDelay: 60 # DeltaV - was 20
minimumPlayers: 40 # DeltaV - was 30
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-ninja-spawn-result-message
- type: SpaceSpawnRule
- type: AntagLoadProfileRule
- type: AntagObjectives
@ -253,6 +271,8 @@
duration: 1
earliestStart: 45
minimumPlayers: 20
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-revenant-spawn-result-message
- type: RandomSpawnRule
prototype: MobRevenant
@ -277,6 +297,8 @@
path: /Audio/Announcements/gas_leak.ogg # DeltaV - custom announcer
endAnnouncement: station-event-gas-leak-end-announcement
weight: 10 # DeltaV - was 8
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-gas-leak-result-message
- type: GasLeakRule
- type: entity
@ -288,6 +310,8 @@
minimumPlayers: 10 # DeltaV - Was 15
weight: 5 # DeltaV - was 7
duration: 240
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-kudzu-growth-result-message
- type: KudzuGrowthRule
- type: entity
@ -304,6 +328,8 @@
volume: -4
duration: 60
maxDuration: 120
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-power-grid-check-result-message
- type: PowerGridCheckRule
- type: entity
@ -318,6 +344,8 @@
path: /Audio/Announcements/attention.ogg
duration: 120
maxDuration: 240
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-solar-flare-result-message
- type: SolarFlareRule
onlyJamHeadsets: true
affectedChannels:
@ -346,6 +374,8 @@
minimumPlayers: 15
weight: 7.5 # DeltaV - was 5
duration: 60
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-vent-clog-result-message
- type: VentClogRule
- type: entity
@ -360,6 +390,8 @@
minimumPlayers: 15
weight: 5
duration: 60
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-slimes-spawn-result-message
- type: VentCrittersRule
entries:
- id: MobAdultSlimesBlueAngry
@ -381,6 +413,8 @@
minimumPlayers: 15
weight: 5
duration: 60
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-snake-spawn-result-message
- type: VentCrittersRule
entries:
- id: MobPurpleSnake
@ -402,6 +436,8 @@
minimumPlayers: 15
weight: 5
duration: 60
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-spider-spawn-result-message
- type: VentCrittersRule
entries:
- id: MobGiantSpiderAngry
@ -419,6 +455,8 @@
minimumPlayers: 30 # DeltaV - was 20
weight: 1 # DeltaV - was 1.5
duration: 60
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-spider-clown-spawn-result-message
- type: VentCrittersRule
entries:
- id: MobClownSpider
@ -433,6 +471,8 @@
minimumPlayers: 40
weight: 1 # Zombies was happening basically every single survival round, so now it's super rare
duration: 1
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-zombie-outbreak-result-message
- type: ZombieRule
- type: AntagSelection
definitions:
@ -467,6 +507,8 @@
minimumPlayers: 30 # DeltaV - was 20
reoccurrenceDelay: 30
duration: 1
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-lone-ops-spawn-result-message
- type: RuleGrids
- type: LoadMapRule
mapPath: /Maps/Shuttles/ShuttleEvent/striker.yml
@ -507,6 +549,8 @@
path: /Audio/Announcements/attention.ogg # DeltaV - Use the generic announcement sound
duration: null # the rule has to last the whole round not 1 second
occursDuringRoundEnd: false
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-sleeper-agents-result-message
- type: AlertLevelInterceptionRule
- type: AntagSelection
definitions:
@ -529,6 +573,8 @@
weight: 10
duration: 150
maxDuration: 300
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-mass-hallucinations-result-message
- type: MassHallucinationsRule
minTimeBetweenIncidents: 30 # DeltaV - was 0.1
maxTimeBetweenIncidents: 300
@ -544,6 +590,8 @@
weight: 10
reoccurrenceDelay: 30 #DeltaV - Was 20 #20 mins feels too short, and can scramble borgs way too much
duration: 1
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-ion-storm-result-message
- type: IonStormRule
# DeltaV - Disable Mimic event. It causes a ton of heisentests, and does practially nothing in game

View File

@ -55,6 +55,7 @@
parent: BaseGameRule
id: MeteorSwarmScheduler
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 600 # 10 min
@ -68,6 +69,7 @@
parent: BaseGameRule
id: MeteorSwarmMildScheduler
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 600 # 10 min
@ -82,6 +84,7 @@
parent: BaseGameRule
id: KesslerSyndromeScheduler
components:
- type: NextEvent # DeltaV: Queue Event
- type: GameRule
- type: RampingStationEventScheduler
scheduledGameRules: !type:NestedSelector
@ -99,6 +102,8 @@
reoccurrenceDelay: 1
earliestStart: 12
minimumPlayers: 25
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-meteor-swarm-result-message
- type: MeteorSwarm
- type: entity
@ -184,6 +189,8 @@
components:
- type: StationEvent
weight: 0.05
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-game-rule-urist-swarm-result-message
- type: MeteorSwarm
announcement: station-event-meteor-urist-start-announcement
announcementSound: /Audio/Announcements/attention.ogg
@ -209,6 +216,8 @@
duration: 1
earliestStart: 30
minimumPlayers: 25
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-immovable-rod-spawn-result-message
- type: ImmovableRodRule
rodPrototypes:
- id: ImmovableRodKeepTilesStill

View File

@ -28,6 +28,8 @@
earliestStart: 15
weight: 6
duration: 50
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-mouse-migration-result-message
- type: VentCrittersRule
entries:
- id: MobMouse
@ -52,6 +54,8 @@
weight: 6
duration: 50
minimumPlayers: 30 # Hopefully this is enough for the Rat King's potential Army (it was not, raised from 15 -> 30)
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-king-rat-migration-result-message
- type: VentCrittersRule
entries:
- id: MobMouse
@ -76,6 +80,8 @@
path: /Audio/Announcements/attention.ogg
weight: 6
duration: 50
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-cockroach-migration-result-message
- type: VentCrittersRule
entries:
- id: MobCockroach
@ -93,6 +99,8 @@
path: /Audio/Announcements/attention.ogg
weight: 6
duration: 50
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-snail-migration-result-message
- type: VentCrittersRule
entries:
- id: MobSnail
@ -114,6 +122,8 @@
weight: 6
duration: 50
minimumPlayers: 30
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-snail-migration-result-message
- type: VentCrittersRule
entries:
- id: MobSnail

View File

@ -8,6 +8,8 @@
maxOccurrences: 1 # this event has diminishing returns on interesting-ness, so we cap it
startAudio:
path: /Audio/Announcements/attention.ogg
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-random-sentience-result-message
- type: RandomSentienceRule
minSentiences: 2
maxSentiences: 5
@ -22,4 +24,4 @@
id: RandomSentienceEventStrength
values:
prefix: random-sentience-event-strength-
count: 8
count: 8

View File

@ -313,6 +313,7 @@
id: BasicStationEventScheduler
parent: BaseGameRule
components:
- type: NextEvent # DeltaV: Queue Event for precognition
- type: BasicStationEventScheduler
minMaxEventTiming: # DeltaV
min: 300 # DeltaV - 5 mins, was 3
@ -324,6 +325,7 @@
id: RampingStationEventScheduler
parent: BaseGameRule
components:
- type: NextEvent # DeltaV: Queue Event for precognition
- type: RampingStationEventScheduler
averageChaos: 4.5 # DeltaV
averageEndTime: 180 # DeltaV
@ -334,6 +336,7 @@
id: SpaceTrafficControlEventScheduler # iff we make a selector for EntityTables that can respect StationEventComp restrictions, or somehow impliment them otherwise in said tables,
parent: BaseGameRule # we can remerge this with the other schedulers, but it will silently fail due to that limitation without a separate scheduler to balance atm.
components:
- type: NextEvent # DeltaV: Queue Event for precognition
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 2700 # 45 mins #shows up like half way through shift.
minMaxEventTiming:
@ -346,6 +349,7 @@
id: SpaceTrafficControlFriendlyEventScheduler
parent: BaseGameRule
components:
- type: NextEvent # DeltaV: Queue Event for precognition
- type: BasicStationEventScheduler
minimumTimeUntilFirstEvent: 1200 # 20 mins
minMaxEventTiming:

View File

@ -59,6 +59,8 @@
components:
- type: StationEvent
maxOccurrences: 2 # should be the same as [copies] in shuttle_incoming_event.yml
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-unknown-shuttle-cargo-lost-result-message
- type: LoadMapRule
preloadedGrid: ShuttleCargoLost
@ -69,6 +71,8 @@
- type: StationEvent
startAnnouncement: station-event-unknown-shuttle-incoming
maxOccurrences: 2 # should be the same as [copies] in shuttle_incoming_event.yml
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-unknown-shuttle-traveling-cuisine-result-message
- type: LoadMapRule
preloadedGrid: TravelingCuisine
@ -79,6 +83,8 @@
- type: StationEvent
startAnnouncement: station-event-unknown-shuttle-incoming
maxOccurrences: 3 # should be the same as [copies] in shuttle_incoming_event.yml
- type: PrecognitionResult # DeltaV - Precogniton
message: psionic-power-precognition-unknown-shuttle-disaster-evac-pod-result-message
- type: LoadMapRule
preloadedGrid: DisasterEvacPod

View File

@ -5,6 +5,7 @@
DispelPower: 1
TelegnosisPower: 1
PsionicRegenerationPower: 1
PrecognitionPower: 1 # DeltaV
MassSleepPower: 0.3
NoosphericZapPower: 0.3
# PsionicInvisibilityPower: 0.15

View File

@ -0,0 +1,14 @@
{
"version": 1,
"license": "CC-BY-SA-4.0",
"copyright": "Sprited by chamomileteatime on Discord for DeltaV",
"size": {
"x": 64,
"y": 64
},
"states": [
{
"name": "precognition"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB