Merge remote-tracking branch 'space-station-14/master' into 04-05-2024-upstream
# Conflicts: # Resources/Prototypes/Maps/Pools/default.yml # Resources/Prototypes/Maps/train.yml
This commit is contained in:
@@ -96,6 +96,16 @@ public sealed class AlertLevelSystem : EntitySystem
|
||||
RaiseLocalEvent(new AlertLevelPrototypeReloadedEvent());
|
||||
}
|
||||
|
||||
public string GetLevel(EntityUid station, AlertLevelComponent? alert = null)
|
||||
{
|
||||
if (!Resolve(station, ref alert))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return alert.CurrentLevel;
|
||||
}
|
||||
|
||||
public float GetAlertLevelDelay(EntityUid station, AlertLevelComponent? alert = null)
|
||||
{
|
||||
if (!Resolve(station, ref alert))
|
||||
|
||||
@@ -12,9 +12,10 @@ namespace Content.Server.Atmos.Components
|
||||
/// <summary>
|
||||
/// Tool is functional only in allowed slots
|
||||
/// </summary>
|
||||
[DataField("allowedSlots")]
|
||||
[DataField]
|
||||
public SlotFlags AllowedSlots = SlotFlags.MASK | SlotFlags.HEAD;
|
||||
public bool IsFunctional;
|
||||
|
||||
public EntityUid? ConnectedInternalsEntity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using Content.Shared.DoAfter;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Internals;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -23,17 +24,29 @@ public sealed class InternalsSystem : EntitySystem
|
||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
|
||||
public const SlotFlags InventorySlots = SlotFlags.POCKET | SlotFlags.BELT;
|
||||
private EntityQuery<InternalsComponent> _internalsQuery;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_internalsQuery = GetEntityQuery<InternalsComponent>();
|
||||
|
||||
SubscribeLocalEvent<InternalsComponent, InhaleLocationEvent>(OnInhaleLocation);
|
||||
SubscribeLocalEvent<InternalsComponent, ComponentStartup>(OnInternalsStartup);
|
||||
SubscribeLocalEvent<InternalsComponent, ComponentShutdown>(OnInternalsShutdown);
|
||||
SubscribeLocalEvent<InternalsComponent, GetVerbsEvent<InteractionVerb>>(OnGetInteractionVerbs);
|
||||
SubscribeLocalEvent<InternalsComponent, InternalsDoAfterEvent>(OnDoAfter);
|
||||
|
||||
SubscribeLocalEvent<StartingGearEquippedEvent>(OnStartingGear);
|
||||
}
|
||||
|
||||
private void OnStartingGear(ref StartingGearEquippedEvent ev)
|
||||
{
|
||||
if (!_internalsQuery.TryComp(ev.Entity, out var internals) || internals.BreathToolEntity == null)
|
||||
return;
|
||||
|
||||
ToggleInternals(ev.Entity, ev.Entity, force: false, internals);
|
||||
}
|
||||
|
||||
private void OnGetInteractionVerbs(
|
||||
@@ -217,7 +230,7 @@ public sealed class InternalsSystem : EntitySystem
|
||||
if (component.BreathToolEntity is null || !AreInternalsWorking(component))
|
||||
return 2;
|
||||
|
||||
// If pressure in the tank is below low pressure threshhold, flash warning on internals UI
|
||||
// If pressure in the tank is below low pressure threshold, flash warning on internals UI
|
||||
if (TryComp<GasTankComponent>(component.GasTankEntity, out var gasTank)
|
||||
&& gasTank.IsLowPressure)
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ public abstract partial class GameRuleSystem<T> : EntitySystem where T : ICompon
|
||||
SubscribeLocalEvent<T, GameRuleAddedEvent>(OnGameRuleAdded);
|
||||
SubscribeLocalEvent<T, GameRuleStartedEvent>(OnGameRuleStarted);
|
||||
SubscribeLocalEvent<T, GameRuleEndedEvent>(OnGameRuleEnded);
|
||||
SubscribeLocalEvent<T, RoundEndTextAppendEvent>(OnRoundEndTextAppend);
|
||||
SubscribeLocalEvent<RoundEndTextAppendEvent>(OnRoundEndTextAppend);
|
||||
}
|
||||
|
||||
private void OnStartAttempt(RoundStartAttemptEvent args)
|
||||
@@ -70,11 +70,16 @@ public abstract partial class GameRuleSystem<T> : EntitySystem where T : ICompon
|
||||
Ended(uid, component, ruleData, args);
|
||||
}
|
||||
|
||||
private void OnRoundEndTextAppend(Entity<T> ent, ref RoundEndTextAppendEvent args)
|
||||
private void OnRoundEndTextAppend(RoundEndTextAppendEvent ev)
|
||||
{
|
||||
if (!TryComp<GameRuleComponent>(ent, out var ruleData))
|
||||
return;
|
||||
AppendRoundEndText(ent, ent, ruleData, ref args);
|
||||
var query = AllEntityQuery<T>();
|
||||
while (query.MoveNext(out var uid, out var comp))
|
||||
{
|
||||
if (!TryComp<GameRuleComponent>(uid, out var ruleData))
|
||||
continue;
|
||||
|
||||
AppendRoundEndText(uid, comp, ruleData, ref ev);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Polymorph.Systems;
|
||||
using Content.Shared.Zombies;
|
||||
using Content.Server.Actions;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Geras;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
@@ -10,8 +10,9 @@ namespace Content.Server.Geras;
|
||||
/// <inheritdoc/>
|
||||
public sealed class GerasSystem : SharedGerasSystem
|
||||
{
|
||||
[Dependency] private readonly ActionsSystem _actionsSystem = default!;
|
||||
[Dependency] private readonly PolymorphSystem _polymorphSystem = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaDataSystem = default!;
|
||||
[Dependency] private readonly ActionsSystem _actionsSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -19,6 +20,12 @@ public sealed class GerasSystem : SharedGerasSystem
|
||||
{
|
||||
SubscribeLocalEvent<GerasComponent, MorphIntoGeras>(OnMorphIntoGeras);
|
||||
SubscribeLocalEvent<GerasComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<GerasComponent, EntityZombifiedEvent>(OnZombification);
|
||||
}
|
||||
|
||||
private void OnZombification(EntityUid uid, GerasComponent component, EntityZombifiedEvent args)
|
||||
{
|
||||
_actionsSystem.RemoveAction(uid, component.GerasActionEntity);
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, GerasComponent component, MapInitEvent args)
|
||||
@@ -29,6 +36,9 @@ public sealed class GerasSystem : SharedGerasSystem
|
||||
|
||||
private void OnMorphIntoGeras(EntityUid uid, GerasComponent component, MorphIntoGeras args)
|
||||
{
|
||||
if (HasComp<ZombieComponent>(uid))
|
||||
return; // i hate zomber.
|
||||
|
||||
var ent = _polymorphSystem.PolymorphEntity(uid, component.GerasPolymorphId);
|
||||
|
||||
if (!ent.HasValue)
|
||||
@@ -36,6 +46,7 @@ public sealed class GerasSystem : SharedGerasSystem
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("geras-popup-morph-message-others", ("entity", ent.Value)), ent.Value, Filter.PvsExcept(ent.Value), true);
|
||||
_popupSystem.PopupEntity(Loc.GetString("geras-popup-morph-message-user"), ent.Value, ent.Value);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,5 +32,11 @@ namespace Content.Server.Speech.Components
|
||||
{
|
||||
[DataField("accent", customTypeSerializer: typeof(PrototypeIdSerializer<ReplacementAccentPrototype>), required: true)]
|
||||
public string Accent = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to substitute words, not always, but with some chance
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float ReplacementChance = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ namespace Content.Server.Speech.EntitySystems
|
||||
|
||||
private void OnAccent(EntityUid uid, ReplacementAccentComponent component, AccentGetEvent args)
|
||||
{
|
||||
if (!_random.Prob(component.ReplacementChance))
|
||||
return;
|
||||
|
||||
args.Message = ApplyReplacements(args.Message, component.Accent);
|
||||
}
|
||||
|
||||
@@ -46,6 +49,12 @@ namespace Content.Server.Speech.EntitySystems
|
||||
if (prototype.WordReplacements == null)
|
||||
return message;
|
||||
|
||||
// Prohibition of repeated word replacements.
|
||||
// All replaced words placed in the final message are placed here as dashes (___) with the same length.
|
||||
// The regex search goes through this buffer message, from which the already replaced words are crossed out,
|
||||
// ensuring that the replaced words cannot be replaced again.
|
||||
var maskMessage = message;
|
||||
|
||||
foreach (var (first, replace) in prototype.WordReplacements)
|
||||
{
|
||||
var f = _loc.GetString(first);
|
||||
@@ -53,10 +62,10 @@ namespace Content.Server.Speech.EntitySystems
|
||||
// this is kind of slow but its not that bad
|
||||
// essentially: go over all matches, try to match capitalization where possible, then replace
|
||||
// rather than using regex.replace
|
||||
for (int i = Regex.Count(message, $@"(?<!\w){f}(?!\w)", RegexOptions.IgnoreCase); i > 0; i--)
|
||||
for (int i = Regex.Count(maskMessage, $@"(?<!\w){f}(?!\w)", RegexOptions.IgnoreCase); i > 0; i--)
|
||||
{
|
||||
// fetch the match again as the character indices may have changed
|
||||
Match match = Regex.Match(message, $@"(?<!\w){f}(?!\w)", RegexOptions.IgnoreCase);
|
||||
Match match = Regex.Match(maskMessage, $@"(?<!\w){f}(?!\w)", RegexOptions.IgnoreCase);
|
||||
var replacement = r;
|
||||
|
||||
// Intelligently replace capitalization
|
||||
@@ -80,6 +89,8 @@ namespace Content.Server.Speech.EntitySystems
|
||||
|
||||
// In-place replace the match with the transformed capitalization replacement
|
||||
message = message.Remove(match.Index, match.Length).Insert(match.Index, replacement);
|
||||
string mask = new string('_', match.Length);
|
||||
maskMessage = message.Remove(match.Index, match.Length).Insert(match.Index, mask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
Subs.CVar(_configurationManager, CCVars.ICRandomCharacters, e => _randomizeCharacters = e, true);
|
||||
|
||||
_spawnerCallbacks = new Dictionary<SpawnPriorityPreference, Action<PlayerSpawningEvent>>()
|
||||
@@ -181,7 +182,7 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
|
||||
if (prototype?.StartingGear != null)
|
||||
{
|
||||
var startingGear = _prototypeManager.Index<StartingGearPrototype>(prototype.StartingGear);
|
||||
EquipStartingGear(entity.Value, startingGear);
|
||||
EquipStartingGear(entity.Value, startingGear, raiseEvent: false);
|
||||
}
|
||||
|
||||
// Run loadouts after so stuff like storage loadouts can get
|
||||
@@ -217,11 +218,14 @@ public sealed class StationSpawningSystem : SharedStationSpawningSystem
|
||||
}
|
||||
|
||||
// Handle any extra data here.
|
||||
EquipStartingGear(entity.Value, startingGear);
|
||||
EquipStartingGear(entity.Value, startingGear, raiseEvent: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var gearEquippedEv = new StartingGearEquippedEvent(entity.Value);
|
||||
RaiseLocalEvent(entity.Value, ref gearEquippedEv, true);
|
||||
|
||||
if (profile != null)
|
||||
{
|
||||
if (prototype != null)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using Content.Server.StationEvents.Events;
|
||||
using Content.Server.AlertLevel;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.StationEvents.Components;
|
||||
|
||||
[RegisterComponent, Access(typeof(AlertLevelInterceptionRule))]
|
||||
public sealed partial class AlertLevelInterceptionRuleComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Alert level to set the station to when the event starts.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string AlertLevel = "blue";
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Content.Server.GameTicking.Components;
|
||||
using Content.Server.StationEvents.Components;
|
||||
using Content.Server.AlertLevel;
|
||||
|
||||
namespace Content.Server.StationEvents.Events;
|
||||
|
||||
public sealed class AlertLevelInterceptionRule : StationEventSystem<AlertLevelInterceptionRuleComponent>
|
||||
{
|
||||
[Dependency] private readonly AlertLevelSystem _alertLevelSystem = default!;
|
||||
|
||||
protected override void Started(EntityUid uid, AlertLevelInterceptionRuleComponent component, GameRuleComponent gameRule,
|
||||
GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, component, gameRule, args);
|
||||
|
||||
if (!TryGetRandomStation(out var chosenStation))
|
||||
return;
|
||||
if (_alertLevelSystem.GetLevel(chosenStation.Value) != "green")
|
||||
return;
|
||||
|
||||
_alertLevelSystem.SetLevel(chosenStation.Value, component.AlertLevel, true, true, true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user