Merge remote-tracking branch 'upstream/master' into upstream-sync

# Conflicts:
#	Content.Server/Connection/ConnectionManager.cs
#	Content.Shared/Humanoid/SharedHumanoidAppearanceSystem.cs
#	Resources/Prototypes/Accents/word_replacements.yml
#	Resources/Prototypes/Datasets/ion_storm.yml
#	Resources/Prototypes/Entities/Clothing/Masks/specific.yml
#	Resources/Prototypes/StatusEffects/health.yml
#	Resources/Prototypes/StatusEffects/job.yml
#	Resources/Prototypes/StatusEffects/security.yml
#	Resources/Textures/Decals/bricktile.rsi/white_box.png
This commit is contained in:
Morb0
2024-04-12 02:17:14 +03:00
271 changed files with 8046 additions and 7840 deletions

View File

@@ -9,20 +9,20 @@ namespace Content.Client.Access;
public sealed class AccessOverlay : Overlay
{
private const string TextFontPath = "/Fonts/NotoSans/NotoSans-Regular.ttf";
private const int TextFontSize = 12;
private readonly IEntityManager _entityManager;
private readonly EntityLookupSystem _lookup;
private readonly SharedTransformSystem _xform;
private readonly SharedTransformSystem _transformSystem;
private readonly Font _font;
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
public AccessOverlay(IEntityManager entManager, IResourceCache cache, EntityLookupSystem lookup, SharedTransformSystem xform)
public AccessOverlay(IEntityManager entityManager, IResourceCache resourceCache, SharedTransformSystem transformSystem)
{
_entityManager = entManager;
_lookup = lookup;
_xform = xform;
_font = cache.GetFont("/Fonts/NotoSans/NotoSans-Regular.ttf", 12);
_entityManager = entityManager;
_transformSystem = transformSystem;
_font = resourceCache.GetFont(TextFontPath, TextFontSize);
}
protected override void Draw(in OverlayDrawArgs args)
@@ -30,52 +30,65 @@ public sealed class AccessOverlay : Overlay
if (args.ViewportControl == null)
return;
var readerQuery = _entityManager.GetEntityQuery<AccessReaderComponent>();
var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
foreach (var ent in _lookup.GetEntitiesIntersecting(args.MapId, args.WorldAABB,
LookupFlags.Static | LookupFlags.Approximate))
var textBuffer = new StringBuilder();
var query = _entityManager.EntityQueryEnumerator<AccessReaderComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var accessReader, out var transform))
{
if (!readerQuery.TryGetComponent(ent, out var reader) ||
!xformQuery.TryGetComponent(ent, out var xform))
textBuffer.Clear();
var entityName = _entityManager.ToPrettyString(uid);
textBuffer.AppendLine(entityName.Prototype);
textBuffer.Append("UID: ");
textBuffer.Append(entityName.Uid.Id);
textBuffer.Append(", NUID: ");
textBuffer.Append(entityName.Nuid.Id);
textBuffer.AppendLine();
if (!accessReader.Enabled)
{
textBuffer.AppendLine("-Disabled");
continue;
}
var text = new StringBuilder();
var index = 0;
var a = $"{_entityManager.ToPrettyString(ent)}";
text.Append(a);
foreach (var list in reader.AccessLists)
if (accessReader.AccessLists.Count > 0)
{
a = $"Tag {index}";
text.AppendLine(a);
foreach (var entry in list)
var groupNumber = 0;
foreach (var accessList in accessReader.AccessLists)
{
a = $"- {entry}";
text.AppendLine(a);
groupNumber++;
foreach (var entry in accessList)
{
textBuffer.Append("+Set ");
textBuffer.Append(groupNumber);
textBuffer.Append(": ");
textBuffer.Append(entry.Id);
textBuffer.AppendLine();
}
}
index++;
}
string textStr;
if (text.Length >= 2)
{
textStr = text.ToString();
textStr = textStr[..^2];
}
else
{
textStr = "";
textBuffer.AppendLine("+Unrestricted");
}
var screenPos = args.ViewportControl.WorldToScreen(_xform.GetWorldPosition(xform));
foreach (var key in accessReader.AccessKeys)
{
textBuffer.Append("+Key ");
textBuffer.Append(key.OriginStation);
textBuffer.Append(": ");
textBuffer.Append(key.Id);
textBuffer.AppendLine();
}
args.ScreenHandle.DrawString(_font, screenPos, textStr, Color.Gold);
foreach (var tag in accessReader.DenyTags)
{
textBuffer.Append("-Tag ");
textBuffer.AppendLine(tag.Id);
}
var accessInfoText = textBuffer.ToString();
var screenPos = args.ViewportControl.WorldToScreen(_transformSystem.GetWorldPosition(transform));
args.ScreenHandle.DrawString(_font, screenPos, accessInfoText, Color.Gold);
}
}
}

View File

@@ -7,8 +7,16 @@ namespace Content.Client.Access.Commands;
public sealed class ShowAccessReadersCommand : IConsoleCommand
{
public string Command => "showaccessreaders";
public string Description => "Shows all access readers in the viewport";
public string Help => $"{Command}";
public string Description => "Toggles showing access reader permissions on the map";
public string Help => """
Overlay Info:
-Disabled | The access reader is disabled
+Unrestricted | The access reader has no restrictions
+Set [Index]: [Tag Name]| A tag in an access set (accessor needs all tags in the set to be allowed by the set)
+Key [StationUid]: [StationRecordKeyId] | A StationRecordKey that is allowed
-Tag [Tag Name] | A tag that is not allowed (takes priority over other allows)
""";
public void Execute(IConsoleShell shell, string argStr, string[] args)
{
var collection = IoCManager.Instance;
@@ -26,10 +34,9 @@ public sealed class ShowAccessReadersCommand : IConsoleCommand
var entManager = collection.Resolve<IEntityManager>();
var cache = collection.Resolve<IResourceCache>();
var lookup = entManager.System<EntityLookupSystem>();
var xform = entManager.System<SharedTransformSystem>();
overlay.AddOverlay(new AccessOverlay(entManager, cache, lookup, xform));
overlay.AddOverlay(new AccessOverlay(entManager, cache, xform));
shell.WriteLine($"Set access reader debug overlay to true");
}
}

View File

@@ -27,6 +27,11 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
SendMessage(new BountyPrintLabelMessage(id));
};
_menu.OnSkipButtonPressed += id =>
{
SendMessage(new BountySkipMessage(id));
};
_menu.OpenCentered();
}
@@ -37,7 +42,7 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
if (message is not CargoBountyConsoleState state)
return;
_menu?.UpdateEntries(state.Bounties);
_menu?.UpdateEntries(state.Bounties, state.UntilNextSkip);
}
protected override void Dispose(bool disposing)

View File

@@ -13,7 +13,18 @@
</BoxContainer>
<Control MinWidth="10"/>
<BoxContainer Orientation="Vertical" MinWidth="120">
<Button Name="PrintButton" Text="{Loc 'bounty-console-label-button-text'}" HorizontalExpand="False" HorizontalAlignment="Right"/>
<BoxContainer Orientation="Horizontal" MinWidth="120">
<Button Name="PrintButton"
Text="{Loc 'bounty-console-label-button-text'}"
HorizontalExpand="False"
HorizontalAlignment="Right"
StyleClasses="OpenRight"/>
<Button Name="SkipButton"
Text="{Loc 'bounty-console-skip-button-text'}"
HorizontalExpand="False"
HorizontalAlignment="Right"
StyleClasses="OpenLeft"/>
</BoxContainer>
<RichTextLabel Name="IdLabel" HorizontalAlignment="Right" Margin="0 0 5 0"/>
</BoxContainer>
</BoxContainer>

View File

@@ -1,11 +1,13 @@
using Content.Client.Message;
using Content.Shared.Cargo;
using Content.Shared.Cargo.Prototypes;
using Content.Shared.Random;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using Serilog;
namespace Content.Client.Cargo.UI;
@@ -14,15 +16,19 @@ public sealed partial class BountyEntry : BoxContainer
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
public Action? OnButtonPressed;
public Action? OnLabelButtonPressed;
public Action? OnSkipButtonPressed;
public TimeSpan EndTime;
public TimeSpan UntilNextSkip;
public BountyEntry(CargoBountyData bounty)
public BountyEntry(CargoBountyData bounty, TimeSpan untilNextSkip)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
UntilNextSkip = untilNextSkip;
if (!_prototype.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var bountyPrototype))
return;
@@ -38,6 +44,27 @@ public sealed partial class BountyEntry : BoxContainer
DescriptionLabel.SetMarkup(Loc.GetString("bounty-console-description-label", ("description", Loc.GetString(bountyPrototype.Description))));
IdLabel.SetMarkup(Loc.GetString("bounty-console-id-label", ("id", bounty.Id)));
PrintButton.OnPressed += _ => OnButtonPressed?.Invoke();
PrintButton.OnPressed += _ => OnLabelButtonPressed?.Invoke();
SkipButton.OnPressed += _ => OnSkipButtonPressed?.Invoke();
}
private void UpdateSkipButton(float deltaSeconds)
{
UntilNextSkip -= TimeSpan.FromSeconds(deltaSeconds);
if (UntilNextSkip > TimeSpan.Zero)
{
SkipButton.Label.Text = UntilNextSkip.ToString("mm\\:ss");
SkipButton.Disabled = true;
return;
}
SkipButton.Label.Text = Loc.GetString("bounty-console-skip-button-text");
SkipButton.Disabled = false;
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
UpdateSkipButton(args.DeltaSeconds);
}
}

View File

@@ -10,19 +10,21 @@ namespace Content.Client.Cargo.UI;
public sealed partial class CargoBountyMenu : FancyWindow
{
public Action<string>? OnLabelButtonPressed;
public Action<string>? OnSkipButtonPressed;
public CargoBountyMenu()
{
RobustXamlLoader.Load(this);
}
public void UpdateEntries(List<CargoBountyData> bounties)
public void UpdateEntries(List<CargoBountyData> bounties, TimeSpan untilNextSkip)
{
BountyEntriesContainer.Children.Clear();
foreach (var b in bounties)
{
var entry = new BountyEntry(b);
entry.OnButtonPressed += () => OnLabelButtonPressed?.Invoke(b.Id);
var entry = new BountyEntry(b, untilNextSkip);
entry.OnLabelButtonPressed += () => OnLabelButtonPressed?.Invoke(b.Id);
entry.OnSkipButtonPressed += () => OnSkipButtonPressed?.Invoke(b.Id);
BountyEntriesContainer.AddChild(entry);
}

View File

@@ -104,41 +104,12 @@ public sealed partial class LatheMenu : DefaultWindow
RecipeList.Children.Clear();
foreach (var prototype in sortedRecipesToShow)
{
StringBuilder sb = new();
var first = true;
foreach (var (id, amount) in prototype.RequiredMaterials)
{
if (!_prototypeManager.TryIndex<MaterialPrototype>(id, out var proto))
continue;
if (first)
first = false;
else
sb.Append('\n');
var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, component.MaterialUseMultiplier);
var sheetVolume = _materialStorage.GetSheetVolume(proto);
var unit = Loc.GetString(proto.Unit);
// rounded in locale not here
var sheets = adjustedAmount / (float) sheetVolume;
var amountText = Loc.GetString("lathe-menu-material-amount", ("amount", sheets), ("unit", unit));
var name = Loc.GetString(proto.Name);
sb.Append(Loc.GetString("lathe-menu-tooltip-display", ("material", name), ("amount", amountText)));
}
if (!string.IsNullOrWhiteSpace(prototype.Description))
{
sb.Append('\n');
sb.Append(Loc.GetString("lathe-menu-description-display", ("description", prototype.Description)));
}
var icon = prototype.Icon == null
? _spriteSystem.GetPrototypeIcon(prototype.Result).Default
: _spriteSystem.Frame0(prototype.Icon);
var canProduce = _lathe.CanProduce(_owner, prototype, quantity);
var control = new RecipeControl(prototype, sb.ToString(), canProduce, icon);
var control = new RecipeControl(prototype, () => GenerateTooltipText(prototype), canProduce, icon);
control.OnButtonPressed += s =>
{
if (!int.TryParse(AmountLineEdit.Text, out var amount) || amount <= 0)
@@ -149,6 +120,51 @@ public sealed partial class LatheMenu : DefaultWindow
}
}
private string GenerateTooltipText(LatheRecipePrototype prototype)
{
StringBuilder sb = new();
foreach (var (id, amount) in prototype.RequiredMaterials)
{
if (!_prototypeManager.TryIndex<MaterialPrototype>(id, out var proto))
continue;
var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, _entityManager.GetComponent<LatheComponent>(_owner).MaterialUseMultiplier);
var sheetVolume = _materialStorage.GetSheetVolume(proto);
var unit = Loc.GetString(proto.Unit);
var sheets = adjustedAmount / (float) sheetVolume;
var availableAmount = _materialStorage.GetMaterialAmount(_owner, id);
var missingAmount = Math.Max(0, adjustedAmount - availableAmount);
var missingSheets = missingAmount / (float) sheetVolume;
var name = Loc.GetString(proto.Name);
string tooltipText;
if (missingSheets > 0)
{
tooltipText = Loc.GetString("lathe-menu-material-amount-missing", ("amount", sheets), ("missingAmount", missingSheets), ("unit", unit), ("material", name));
}
else
{
var amountText = Loc.GetString("lathe-menu-material-amount", ("amount", sheets), ("unit", unit));
tooltipText = Loc.GetString("lathe-menu-tooltip-display", ("material", name), ("amount", amountText));
}
sb.AppendLine(tooltipText);
}
if (!string.IsNullOrWhiteSpace(prototype.Description))
sb.AppendLine(Loc.GetString("lathe-menu-description-display", ("description", prototype.Description)));
// Remove last newline
if (sb.Length > 0)
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
public void UpdateCategories()
{
var currentCategories = new List<ProtoId<LatheCategoryPrototype>>();

View File

@@ -11,17 +11,16 @@ namespace Content.Client.Lathe.UI;
public sealed partial class RecipeControl : Control
{
public Action<string>? OnButtonPressed;
public Func<string> TooltipTextSupplier;
public string TooltipText;
public RecipeControl(LatheRecipePrototype recipe, string tooltip, bool canProduce, Texture? texture = null)
public RecipeControl(LatheRecipePrototype recipe, Func<string> tooltipTextSupplier, bool canProduce, Texture? texture = null)
{
RobustXamlLoader.Load(this);
RecipeName.Text = recipe.Name;
RecipeTexture.Texture = texture;
Button.Disabled = !canProduce;
TooltipText = tooltip;
TooltipTextSupplier = tooltipTextSupplier;
Button.TooltipSupplier = SupplyTooltip;
Button.OnPressed += (_) =>
@@ -32,6 +31,6 @@ public sealed partial class RecipeControl : Control
private Control? SupplyTooltip(Control sender)
{
return new RecipeTooltip(TooltipText);
return new RecipeTooltip(TooltipTextSupplier());
}
}

View File

@@ -210,9 +210,9 @@ public sealed partial class CrewMonitoringWindow : FancyWindow
specifier = new SpriteSpecifier.Rsi(new ResPath("Interface/Alerts/human_crew_monitoring.rsi"), "dead");
}
else if (sensor.TotalDamage != null)
else if (sensor.DamagePercentage != null)
{
var index = MathF.Round(4f * (sensor.TotalDamage.Value / 100f));
var index = MathF.Round(4f * sensor.DamagePercentage.Value);
if (index >= 5)
specifier = new SpriteSpecifier.Rsi(new ResPath("Interface/Alerts/human_crew_monitoring.rsi"), "critical");

View File

@@ -49,6 +49,7 @@
<Label Text="{Loc 'ui-options-general-speech'}"
FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="ShowOocPatronColor" Text="{Loc 'ui-options-show-ooc-patron-color'}" />
<CheckBox Name="ShowLoocAboveHeadCheckBox" Text="{Loc 'ui-options-show-looc-on-head'}" />
<CheckBox Name="FancySpeechBubblesCheckBox" Text="{Loc 'ui-options-fancy-speech'}" />
<CheckBox Name="FancyNameBackgroundsCheckBox" Text="{Loc 'ui-options-fancy-name-background'}" />

View File

@@ -3,11 +3,14 @@ using Content.Client.UserInterface.Screens;
using Content.Shared.CCVar;
using Content.Shared.HUD;
using Robust.Client.AutoGenerated;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Range = Robust.Client.UserInterface.Controls.Range;
@@ -16,6 +19,7 @@ namespace Content.Client.Options.UI.Tabs
[GenerateTypedNameReferences]
public sealed partial class MiscTab : Control
{
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
@@ -55,8 +59,11 @@ namespace Content.Client.Options.UI.Tabs
UpdateApplyButton();
};
ShowOocPatronColor.Visible = _playerManager.LocalSession?.Channel.UserData.PatronTier is { } patron;
HudThemeOption.OnItemSelected += OnHudThemeChanged;
DiscordRich.OnToggled += OnCheckBoxToggled;
ShowOocPatronColor.OnToggled += OnCheckBoxToggled;
ShowLoocAboveHeadCheckBox.OnToggled += OnCheckBoxToggled;
ShowHeldItemCheckBox.OnToggled += OnCheckBoxToggled;
ShowCombatModeIndicatorsCheckBox.OnToggled += OnCheckBoxToggled;
@@ -73,6 +80,7 @@ namespace Content.Client.Options.UI.Tabs
HudThemeOption.SelectId(_hudThemeIdToIndex.GetValueOrDefault(_cfg.GetCVar(CVars.InterfaceTheme), 0));
DiscordRich.Pressed = _cfg.GetCVar(CVars.DiscordEnabled);
ShowOocPatronColor.Pressed = _cfg.GetCVar(CCVars.ShowOocPatronColor);
ShowLoocAboveHeadCheckBox.Pressed = _cfg.GetCVar(CCVars.LoocAboveHeadShow);
ShowHeldItemCheckBox.Pressed = _cfg.GetCVar(CCVars.HudHeldItemShow);
ShowCombatModeIndicatorsCheckBox.Pressed = _cfg.GetCVar(CCVars.CombatModeIndicatorsPointShow);
@@ -130,6 +138,7 @@ namespace Content.Client.Options.UI.Tabs
_cfg.SetCVar(CCVars.HudHeldItemShow, ShowHeldItemCheckBox.Pressed);
_cfg.SetCVar(CCVars.CombatModeIndicatorsPointShow, ShowCombatModeIndicatorsCheckBox.Pressed);
_cfg.SetCVar(CCVars.OpaqueStorageWindow, OpaqueStorageWindowCheckBox.Pressed);
_cfg.SetCVar(CCVars.ShowOocPatronColor, ShowOocPatronColor.Pressed);
_cfg.SetCVar(CCVars.LoocAboveHeadShow, ShowLoocAboveHeadCheckBox.Pressed);
_cfg.SetCVar(CCVars.ChatEnableFancyBubbles, FancySpeechBubblesCheckBox.Pressed);
_cfg.SetCVar(CCVars.ChatFancyNameBackground, FancyNameBackgroundsCheckBox.Pressed);
@@ -158,6 +167,7 @@ namespace Content.Client.Options.UI.Tabs
var isShowHeldItemSame = ShowHeldItemCheckBox.Pressed == _cfg.GetCVar(CCVars.HudHeldItemShow);
var isCombatModeIndicatorsSame = ShowCombatModeIndicatorsCheckBox.Pressed == _cfg.GetCVar(CCVars.CombatModeIndicatorsPointShow);
var isOpaqueStorageWindow = OpaqueStorageWindowCheckBox.Pressed == _cfg.GetCVar(CCVars.OpaqueStorageWindow);
var isOocPatronColorShowSame = ShowOocPatronColor.Pressed == _cfg.GetCVar(CCVars.ShowOocPatronColor);
var isLoocShowSame = ShowLoocAboveHeadCheckBox.Pressed == _cfg.GetCVar(CCVars.LoocAboveHeadShow);
var isFancyChatSame = FancySpeechBubblesCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatEnableFancyBubbles);
var isFancyBackgroundSame = FancyNameBackgroundsCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatFancyNameBackground);
@@ -175,6 +185,7 @@ namespace Content.Client.Options.UI.Tabs
isShowHeldItemSame &&
isCombatModeIndicatorsSame &&
isOpaqueStorageWindow &&
isOocPatronColorShowSame &&
isLoocShowSame &&
isFancyChatSame &&
isFancyBackgroundSame &&

View File

@@ -19,7 +19,6 @@ namespace Content.Client.Overlays;
/// </summary>
public sealed class EntityHealthBarOverlay : Overlay
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
private readonly IEntityManager _entManager;
private readonly SharedTransformSystem _transform;
private readonly MobStateSystem _mobStateSystem;
@@ -27,17 +26,14 @@ public sealed class EntityHealthBarOverlay : Overlay
private readonly ProgressColorSystem _progressColor;
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
public HashSet<string> DamageContainers = new();
private readonly ShaderInstance _shader;
public EntityHealthBarOverlay(IEntityManager entManager)
{
IoCManager.InjectDependencies(this);
_entManager = entManager;
_transform = _entManager.System<SharedTransformSystem>();
_mobStateSystem = _entManager.System<MobStateSystem>();
_mobThresholdSystem = _entManager.System<MobThresholdSystem>();
_progressColor = _entManager.System<ProgressColorSystem>();
_shader = _prototype.Index<ShaderPrototype>("unshaded").Instance();
}
protected override void Draw(in OverlayDrawArgs args)
@@ -50,8 +46,6 @@ public sealed class EntityHealthBarOverlay : Overlay
var scaleMatrix = Matrix3.CreateScale(new Vector2(scale, scale));
var rotationMatrix = Matrix3.CreateRotation(-rotation);
handle.UseShader(_shader);
var query = _entManager.AllEntityQueryEnumerator<MobThresholdsComponent, MobStateComponent, DamageableComponent, SpriteComponent>();
while (query.MoveNext(out var uid,
out var mobThresholdsComponent,
@@ -122,7 +116,6 @@ public sealed class EntityHealthBarOverlay : Overlay
handle.DrawRect(pixelDarken, Black.WithAlpha(128));
}
handle.UseShader(null);
handle.SetTransform(Matrix3.Identity);
}

View File

@@ -1,8 +1,10 @@
using Content.Client.UserInterface.Controls;
using Content.Shared.Popups;
using Content.Shared.RCD;
using Content.Shared.RCD.Components;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
@@ -16,17 +18,24 @@ public sealed partial class RCDMenu : RadialMenu
{
[Dependency] private readonly EntityManager _entManager = default!;
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
private readonly SpriteSystem _spriteSystem;
private readonly SharedPopupSystem _popup;
public event Action<ProtoId<RCDPrototype>>? SendRCDSystemMessageAction;
private EntityUid _owner;
public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui)
{
IoCManager.InjectDependencies(this);
RobustXamlLoader.Load(this);
_spriteSystem = _entManager.System<SpriteSystem>();
_popup = _entManager.System<SharedPopupSystem>();
_owner = owner;
// Find the main radial container
var main = FindControl<RadialContainer>("Main");
@@ -51,14 +60,21 @@ public sealed partial class RCDMenu : RadialMenu
if (parent == null)
continue;
var name = Loc.GetString(proto.SetName);
name = char.ToUpper(name[0]) + name.Remove(0, 1);
var tooltip = Loc.GetString(proto.SetName);
if ((proto.Mode == RcdMode.ConstructTile || proto.Mode == RcdMode.ConstructObject) &&
proto.Prototype != null && _protoManager.TryIndex(proto.Prototype, out var entProto))
{
tooltip = Loc.GetString(entProto.Name);
}
tooltip = char.ToUpper(tooltip[0]) + tooltip.Remove(0, 1);
var button = new RCDMenuButton()
{
StyleClasses = { "RadialMenuButton" },
SetSize = new Vector2(64f, 64f),
ToolTip = name,
ToolTip = tooltip,
ProtoId = protoId,
};
@@ -120,6 +136,27 @@ public sealed partial class RCDMenu : RadialMenu
castChild.OnButtonUp += _ =>
{
SendRCDSystemMessageAction?.Invoke(castChild.ProtoId);
if (_playerManager.LocalSession?.AttachedEntity != null &&
_protoManager.TryIndex(castChild.ProtoId, out var proto))
{
var msg = Loc.GetString("rcd-component-change-mode", ("mode", Loc.GetString(proto.SetName)));
if (proto.Mode == RcdMode.ConstructTile || proto.Mode == RcdMode.ConstructObject)
{
var name = Loc.GetString(proto.SetName);
if (proto.Prototype != null &&
_protoManager.TryIndex(proto.Prototype, out var entProto))
name = entProto.Name;
msg = Loc.GetString("rcd-component-change-build-mode", ("name", name));
}
// Popup message
_popup.PopupClient(msg, _owner, _playerManager.LocalSession.AttachedEntity);
}
Close();
};
}

View File

@@ -3,9 +3,9 @@ using Content.Shared.StatusIcon.Components;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Enums;
using System.Numerics;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
using System.Numerics;
namespace Content.Client.StatusIcon;
@@ -18,7 +18,7 @@ public sealed class StatusIconOverlay : Overlay
private readonly SpriteSystem _sprite;
private readonly TransformSystem _transform;
private readonly StatusIconSystem _statusIcon;
private readonly ShaderInstance _shader;
private readonly ShaderInstance _unshadedShader;
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
@@ -29,7 +29,7 @@ public sealed class StatusIconOverlay : Overlay
_sprite = _entity.System<SpriteSystem>();
_transform = _entity.System<TransformSystem>();
_statusIcon = _entity.System<StatusIconSystem>();
_shader = _prototype.Index<ShaderPrototype>("unshaded").Instance();
_unshadedShader = _prototype.Index<ShaderPrototype>("unshaded").Instance();
}
protected override void Draw(in OverlayDrawArgs args)
@@ -42,8 +42,6 @@ public sealed class StatusIconOverlay : Overlay
var scaleMatrix = Matrix3.CreateScale(new Vector2(1, 1));
var rotationMatrix = Matrix3.CreateRotation(-eyeRot);
handle.UseShader(_shader);
var query = _entity.AllEntityQueryEnumerator<StatusIconComponent, SpriteComponent, TransformComponent, MetaDataComponent>();
while (query.MoveNext(out var uid, out var comp, out var sprite, out var xform, out var meta))
{
@@ -111,11 +109,16 @@ public sealed class StatusIconOverlay : Overlay
}
if (proto.IsShaded)
handle.UseShader(null);
else
handle.UseShader(_unshadedShader);
var position = new Vector2(xOffset, yOffset);
handle.DrawTexture(texture, position);
}
}
handle.UseShader(null);
handle.UseShader(null);
}
}
}

View File

@@ -56,7 +56,7 @@ public sealed class CraftingTests : InteractionTest
// Player's hands should be full of the remaining rods, except those dropped during the failed crafting attempt.
// Spear and left over stacks should be on the floor.
await AssertEntityLookup((Rod, 2), (Cable, 8), (ShardGlass, 2), (Spear, 1));
await AssertEntityLookup((Rod, 2), (Cable, 7), (ShardGlass, 2), (Spear, 1));
}
// The following is wrapped in an if DEBUG. This is because of cursed state handling bugs. Tests don't (de)serialize
@@ -100,7 +100,7 @@ public sealed class CraftingTests : InteractionTest
Assert.That(sys.IsEntityInContainer(rods), Is.False);
Assert.That(sys.IsEntityInContainer(wires), Is.False);
Assert.That(rodStack, Has.Count.EqualTo(8));
Assert.That(wireStack, Has.Count.EqualTo(8));
Assert.That(wireStack, Has.Count.EqualTo(7));
await FindEntity(Spear, shouldSucceed: false);
});

View File

@@ -1,11 +1,16 @@
using System.Globalization;
using System.Linq;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking;
using Content.Server.Hands.Systems;
using Content.Server.Inventory;
using Content.Server.Popups;
using Content.Server.Chat.Systems;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Server.StationRecords;
using Content.Server.StationRecords.Systems;
using Content.Shared.StationRecords;
using Content.Shared.UserInterface;
using Content.Shared.Access.Systems;
using Content.Shared.Bed.Cryostorage;
@@ -32,6 +37,7 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
[Dependency] private readonly ChatSystem _chatSystem = default!;
[Dependency] private readonly ClimbSystem _climb = default!;
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly GameTicker _gameTicker = default!;
@@ -40,6 +46,7 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly StationJobsSystem _stationJobs = default!;
[Dependency] private readonly StationRecordsSystem _stationRecords = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
@@ -163,26 +170,30 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
{
var comp = ent.Comp;
var cryostorageEnt = ent.Comp.Cryostorage;
var station = _station.GetOwningStation(ent);
var name = Name(ent.Owner);
if (!TryComp<CryostorageComponent>(cryostorageEnt, out var cryostorageComponent))
return;
// if we have a session, we use that to add back in all the job slots the player had.
if (userId != null)
{
foreach (var station in _station.GetStationsSet())
foreach (var uniqueStation in _station.GetStationsSet())
{
if (!TryComp<StationJobsComponent>(station, out var stationJobs))
if (!TryComp<StationJobsComponent>(uniqueStation, out var stationJobs))
continue;
if (!_stationJobs.TryGetPlayerJobs(station, userId.Value, out var jobs, stationJobs))
if (!_stationJobs.TryGetPlayerJobs(uniqueStation, userId.Value, out var jobs, stationJobs))
continue;
foreach (var job in jobs)
{
_stationJobs.TryAdjustJobSlot(station, job, 1, clamp: true);
_stationJobs.TryAdjustJobSlot(uniqueStation, job, 1, clamp: true);
}
_stationJobs.TryRemovePlayerJobs(station, userId.Value, stationJobs);
_stationJobs.TryRemovePlayerJobs(uniqueStation, userId.Value, stationJobs);
}
}
@@ -203,12 +214,33 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
_gameTicker.OnGhostAttempt(mind.Value, false);
}
}
comp.AllowReEnteringBody = false;
_transform.SetParent(ent, PausedMap.Value);
cryostorageComponent.StoredPlayers.Add(ent);
Dirty(ent, comp);
UpdateCryostorageUIState((cryostorageEnt.Value, cryostorageComponent));
AdminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(ent):player} was entered into cryostorage inside of {ToPrettyString(cryostorageEnt.Value)}");
if (!TryComp<StationRecordsComponent>(station, out var stationRecords))
return;
var key = new StationRecordKey(_stationRecords.GetRecordByName(station.Value, name) ?? default(uint), station.Value);
var jobName = "Unknown";
if (_stationRecords.TryGetRecord<GeneralStationRecord>(key, out var entry, stationRecords))
jobName = entry.JobTitle;
_stationRecords.RemoveRecord(key, stationRecords);
_chatSystem.DispatchStationAnnouncement(station.Value,
Loc.GetString(
"earlyleave-cryo-announcement",
("character", name),
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName))
), Loc.GetString("earlyleave-cryo-sender"),
playDefaultSound: false
);
}
private void HandleCryostorageReconnection(Entity<CryostorageContainedComponent> entity)

View File

@@ -159,7 +159,6 @@ public sealed class PlantHolderSystem : EntitySystem
if (!_botany.TryGetSeed(seeds, out var seed))
return;
float? seedHealth = seeds.HealthOverride;
var name = Loc.GetString(seed.Name);
var noun = Loc.GetString(seed.Noun);
_popup.PopupCursor(Loc.GetString("plant-holder-component-plant-success-message",
@@ -169,9 +168,9 @@ public sealed class PlantHolderSystem : EntitySystem
component.Seed = seed;
component.Dead = false;
component.Age = 1;
if (seedHealth is float realSeedHealth)
if (seeds.HealthOverride != null)
{
component.Health = realSeedHealth;
component.Health = seeds.HealthOverride.Value;
}
else
{
@@ -288,8 +287,18 @@ public sealed class PlantHolderSystem : EntitySystem
}
component.Health -= (_random.Next(3, 5) * 10);
float? healthOverride;
if (component.Harvest)
{
healthOverride = null;
}
else
{
healthOverride = component.Health;
}
component.Seed.Unique = false;
var seed = _botany.SpawnSeedPacket(component.Seed, Transform(args.User).Coordinates, args.User, component.Health);
var seed = _botany.SpawnSeedPacket(component.Seed, Transform(args.User).Coordinates, args.User, healthOverride);
_randomHelper.RandomOffset(seed, 0.25f);
var displayName = Loc.GetString(component.Seed.DisplayName);
_popup.PopupCursor(Loc.GetString("plant-holder-component-take-sample-message",

View File

@@ -1,4 +1,5 @@
using Content.Shared.Cargo;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.Cargo.Components;
@@ -32,4 +33,16 @@ public sealed partial class StationCargoBountyDatabaseComponent : Component
/// </summary>
[DataField]
public HashSet<string> CheckedBounties = new();
/// <summary>
/// The time at which players will be able to skip the next bounty.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan NextSkipTime = TimeSpan.Zero;
/// <summary>
/// The time between skipping bounties.
/// </summary>
[DataField]
public TimeSpan SkipDelay = TimeSpan.FromMinutes(15);
}

View File

@@ -4,7 +4,7 @@ using Content.Server.Cargo.Components;
using Content.Server.Labels;
using Content.Server.NameIdentifier;
using Content.Server.Paper;
using Content.Server.Station.Systems;
using Content.Shared.Access.Components;
using Content.Shared.Cargo;
using Content.Shared.Cargo.Components;
using Content.Shared.Cargo.Prototypes;
@@ -35,6 +35,7 @@ public sealed partial class CargoSystem
{
SubscribeLocalEvent<CargoBountyConsoleComponent, BoundUIOpenedEvent>(OnBountyConsoleOpened);
SubscribeLocalEvent<CargoBountyConsoleComponent, BountyPrintLabelMessage>(OnPrintLabelMessage);
SubscribeLocalEvent<CargoBountyConsoleComponent, BountySkipMessage>(OnSkipBountyMessage);
SubscribeLocalEvent<CargoBountyLabelComponent, PriceCalculationEvent>(OnGetBountyPrice);
SubscribeLocalEvent<EntitySoldEvent>(OnSold);
SubscribeLocalEvent<StationCargoBountyDatabaseComponent, MapInitEvent>(OnMapInit);
@@ -50,7 +51,8 @@ public sealed partial class CargoSystem
!TryComp<StationCargoBountyDatabaseComponent>(station, out var bountyDb))
return;
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(bountyDb.Bounties));
var untilNextSkip = bountyDb.NextSkipTime - _timing.CurTime;
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(bountyDb.Bounties, untilNextSkip));
}
private void OnPrintLabelMessage(EntityUid uid, CargoBountyConsoleComponent component, BountyPrintLabelMessage args)
@@ -70,6 +72,37 @@ public sealed partial class CargoSystem
_audio.PlayPvs(component.PrintSound, uid);
}
private void OnSkipBountyMessage(EntityUid uid, CargoBountyConsoleComponent component, BountySkipMessage args)
{
if (_station.GetOwningStation(uid) is not { } station || !TryComp<StationCargoBountyDatabaseComponent>(station, out var db))
return;
if (_timing.CurTime < db.NextSkipTime)
return;
if (!TryGetBountyFromId(station, args.BountyId, out var bounty))
return;
if (args.Session.AttachedEntity is not { Valid: true } mob)
return;
if (TryComp<AccessReaderComponent>(uid, out var accessReaderComponent) &&
!_accessReaderSystem.IsAllowed(mob, uid, accessReaderComponent))
{
_audio.PlayPvs(component.DenySound, uid);
return;
}
if (!TryRemoveBounty(station, bounty.Value))
return;
FillBountyDatabase(station);
db.NextSkipTime = _timing.CurTime + db.SkipDelay;
var untilNextSkip = db.NextSkipTime - _timing.CurTime;
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(db.Bounties, untilNextSkip));
_audio.PlayPvs(component.SkipSound, uid);
}
public void SetupBountyLabel(EntityUid uid, EntityUid stationId, CargoBountyData bounty, PaperComponent? paper = null, CargoBountyLabelComponent? label = null)
{
if (!Resolve(uid, ref paper, ref label) || !_protoMan.TryIndex<CargoBountyPrototype>(bounty.Bounty, out var prototype))
@@ -431,7 +464,8 @@ public sealed partial class CargoSystem
!TryComp<StationCargoBountyDatabaseComponent>(station, out var db))
continue;
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(db.Bounties), ui: ui);
var untilNextSkip = db.NextSkipTime - _timing.CurTime;
_uiSystem.TrySetUiState(uid, CargoConsoleUiKey.Bounty, new CargoBountyConsoleState(db.Bounties, untilNextSkip), ui: ui);
}
}

View File

@@ -247,8 +247,7 @@ namespace Content.Server.Chat.Managers
var prefs = _preferencesManager.GetPreferences(player.UserId);
colorOverride = prefs.AdminOOCColor;
}
if (player.Channel.UserData.PatronTier is { } patron &&
PatronOocColors.TryGetValue(patron, out var patronColor))
if ( _netConfigManager.GetClientCVar(player.Channel, CCVars.ShowOocPatronColor) && player.Channel.UserData.PatronTier is { } patron && PatronOocColors.TryGetValue(patron, out var patronColor))
{
wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Immutable;
using System.Runtime.InteropServices;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Content.Corvax.Interfaces.Server;
@@ -12,6 +13,7 @@ using Content.Shared.Players.PlayTimeTracking;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Network;
using Robust.Shared.Timing;
namespace Content.Server.Connection
@@ -20,6 +22,18 @@ namespace Content.Server.Connection
{
void Initialize();
Task<bool> HavePrivilegedJoin(NetUserId userId); // Corvax-Queue
/// <summary>
/// Temporarily allow a user to bypass regular connection requirements.
/// </summary>
/// <remarks>
/// The specified user will be allowed to bypass regular player cap,
/// whitelist and panic bunker restrictions for <paramref name="duration"/>.
/// Bans are not bypassed.
/// </remarks>
/// <param name="user">The user to give a temporary bypass.</param>
/// <param name="duration">How long the bypass should last for.</param>
void AddTemporaryConnectBypass(NetUserId user, TimeSpan duration);
}
/// <summary>
@@ -34,11 +48,18 @@ namespace Content.Server.Connection
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly ILocalizationManager _loc = default!;
[Dependency] private readonly ServerDbEntryManager _serverDbEntry = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly ILogManager _logManager = default!;
private IServerSponsorsManager? _sponsorsMgr; // Corvax-Sponsors
private IServerVPNGuardManager? _vpnGuardMgr; // Corvax-VPNGuard
private readonly Dictionary<NetUserId, TimeSpan> _temporaryBypasses = [];
private ISawmill _sawmill = default!;
public void Initialize()
{
_sawmill = _logManager.GetSawmill("connections");
IoCManager.Instance!.TryResolveType(out _sponsorsMgr); // Corvax-Sponsors
_netMgr.Connecting += NetMgrOnConnecting;
_netMgr.AssignUserIdCallback = AssignUserIdCallback;
@@ -46,6 +67,15 @@ namespace Content.Server.Connection
// _netMgr.HandleApprovalCallback = HandleApproval;
}
public void AddTemporaryConnectBypass(NetUserId user, TimeSpan duration)
{
ref var time = ref CollectionsMarshal.GetValueRefOrAddDefault(_temporaryBypasses, user, out _);
var newTime = _gameTiming.RealTime + duration;
// Make sure we only update the time if we wouldn't shrink it.
if (newTime > time)
time = newTime;
}
/*
private async Task<NetApproval> HandleApproval(NetApprovalEventArgs eventArgs)
{
@@ -115,6 +145,20 @@ namespace Content.Server.Connection
hwId = null;
}
var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false);
if (bans.Count > 0)
{
var firstBan = bans[0];
var message = firstBan.FormatBanMessage(_cfg, _loc);
return (ConnectionDenyReason.Ban, message, bans);
}
if (HasTemporaryBypass(userId))
{
_sawmill.Verbose("User {UserId} has temporary bypass, skipping further connection checks", userId);
return null;
}
var adminData = await _dbManager.GetAdminDataForAsync(e.UserId);
// Corvax-Start: Allow privileged players bypass bunker
@@ -192,14 +236,6 @@ namespace Content.Server.Connection
return (ConnectionDenyReason.Full, Loc.GetString("soft-player-cap-full"), null);
}
var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false);
if (bans.Count > 0)
{
var firstBan = bans[0];
var message = firstBan.FormatBanMessage(_cfg, _loc);
return (ConnectionDenyReason.Ban, message, bans);
}
if (_cfg.GetCVar(CCVars.WhitelistEnabled))
{
var min = _cfg.GetCVar(CCVars.WhitelistMinPlayers);
@@ -220,6 +256,11 @@ namespace Content.Server.Connection
return null;
}
private bool HasTemporaryBypass(NetUserId user)
{
return _temporaryBypasses.TryGetValue(user, out var time) && time > _gameTiming.RealTime;
}
private async Task<NetUserId?> AssignUserIdCallback(string name)
{
if (!_cfg.GetCVar(CCVars.GamePersistGuests))

View File

@@ -0,0 +1,60 @@
using Content.Server.Administration;
using Content.Shared.Administration;
using Robust.Shared.Console;
namespace Content.Server.Connection;
[AdminCommand(AdminFlags.Admin)]
public sealed class GrantConnectBypassCommand : LocalizedCommands
{
private static readonly TimeSpan DefaultDuration = TimeSpan.FromHours(1);
[Dependency] private readonly IPlayerLocator _playerLocator = default!;
[Dependency] private readonly IConnectionManager _connectionManager = default!;
public override string Command => "grant_connect_bypass";
public override async void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length is not (1 or 2))
{
shell.WriteError(Loc.GetString("cmd-grant_connect_bypass-invalid-args"));
return;
}
var argPlayer = args[0];
var info = await _playerLocator.LookupIdByNameOrIdAsync(argPlayer);
if (info == null)
{
shell.WriteError(Loc.GetString("cmd-grant_connect_bypass-unknown-user", ("user", argPlayer)));
return;
}
var duration = DefaultDuration;
if (args.Length > 1)
{
var argDuration = args[2];
if (!uint.TryParse(argDuration, out var minutes))
{
shell.WriteLine(Loc.GetString("cmd-grant_connect_bypass-invalid-duration", ("duration", argDuration)));
return;
}
duration = TimeSpan.FromMinutes(minutes);
}
_connectionManager.AddTemporaryConnectBypass(info.UserId, duration);
shell.WriteLine(Loc.GetString("cmd-grant_connect_bypass-success", ("user", argPlayer)));
}
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
{
if (args.Length == 1)
return CompletionResult.FromHint(Loc.GetString("cmd-grant_connect_bypass-arg-user"));
if (args.Length == 2)
return CompletionResult.FromHint(Loc.GetString("cmd-grant_connect_bypass-arg-duration"));
return CompletionResult.Empty;
}
}

View File

@@ -5,6 +5,11 @@ namespace Content.Server.Damage.Components;
[RegisterComponent, Access(typeof(DamagePopupSystem))]
public sealed partial class DamagePopupComponent : Component
{
/// <summary>
/// Bool that will be used to determine if the popup type can be changed with a left click.
/// </summary>
[DataField("allowTypeChange")] [ViewVariables(VVAccess.ReadWrite)]
public bool AllowTypeChange = false;
/// <summary>
/// Enum that will be used to determine the type of damage popup displayed.
/// </summary>

View File

@@ -1,7 +1,8 @@
using System.Linq;
using Content.Server.Damage.Components;
using Content.Server.Popups;
using Content.Shared.Damage;
using Robust.Shared.Player;
using Content.Shared.Interaction;
namespace Content.Server.Damage.Systems;
@@ -13,6 +14,7 @@ public sealed class DamagePopupSystem : EntitySystem
{
base.Initialize();
SubscribeLocalEvent<DamagePopupComponent, DamageChangedEvent>(OnDamageChange);
SubscribeLocalEvent<DamagePopupComponent, InteractHandEvent>(OnInteractHand);
}
private void OnDamageChange(EntityUid uid, DamagePopupComponent component, DamageChangedEvent args)
@@ -33,4 +35,20 @@ public sealed class DamagePopupSystem : EntitySystem
_popupSystem.PopupEntity(msg, uid);
}
}
private void OnInteractHand(EntityUid uid, DamagePopupComponent component, InteractHandEvent args)
{
if (component.AllowTypeChange)
{
if (component.Type == Enum.GetValues(typeof(DamagePopupType)).Cast<DamagePopupType>().Last())
{
component.Type = Enum.GetValues(typeof(DamagePopupType)).Cast<DamagePopupType>().First();
}
else
{
component.Type = (DamagePopupType) (int) component.Type + 1;
}
_popupSystem.PopupEntity("Target set to type: " + component.Type.ToString(), uid);
}
}
}

View File

@@ -299,7 +299,12 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
var canInsert = CanInsert(uid, component, args.Thrown);
var randDouble = _robustRandom.NextDouble();
if (!canInsert || randDouble > 0.75)
if (!canInsert)
{
return;
}
if (randDouble > 0.75)
{
_audioSystem.PlayPvs(component.MissSound, uid);

View File

@@ -143,6 +143,9 @@ public sealed partial class PuddleSystem
if (Openable.IsClosed(entity.Owner))
return;
if (!entity.Comp.SpillWhenThrown)
return;
if (args.User != null)
{
_adminLogger.Add(LogType.Landed,

View File

@@ -0,0 +1,29 @@
using Content.Shared.Whitelist;
namespace Content.Server.GameTicking.Rules.VariationPass.Components;
/// <summary>
/// Handles cutting a random wire on random devices around the station.
/// </summary>
[RegisterComponent]
public sealed partial class CutWireVariationPassComponent : Component
{
/// <summary>
/// Blacklist of hackable entities that should not be chosen to
/// have wires cut.
/// </summary>
[DataField]
public EntityWhitelist Blacklist = new();
/// <summary>
/// Chance for an individual wire to be cut.
/// </summary>
[DataField]
public float WireCutChance = 0.05f;
/// <summary>
/// Maximum number of wires that can be cut stationwide.
/// </summary>
[DataField]
public int MaxWiresCut = 10;
}

View File

@@ -0,0 +1,39 @@
using Content.Server.GameTicking.Rules.VariationPass.Components;
using Content.Server.Wires;
using Robust.Shared.Random;
namespace Content.Server.GameTicking.Rules.VariationPass;
/// <summary>
/// Handles cutting a random wire on random devices around the station.
/// This system identifies target devices and adds <see cref="CutWireOnMapInitComponent"/> to them.
/// The actual wire cutting is handled by <see cref="CutWireOnMapInitSystem"/>.
/// </summary>
public sealed class CutWireVariationPassSystem : VariationPassSystem<CutWireVariationPassComponent>
{
protected override void ApplyVariation(Entity<CutWireVariationPassComponent> ent, ref StationVariationPassEvent args)
{
var wiresCut = 0;
var query = AllEntityQuery<WiresComponent, TransformComponent>();
while (query.MoveNext(out var uid, out _, out var transform))
{
// Ignore if not part of the station
if (!IsMemberOfStation((uid, transform), ref args))
continue;
// Check against blacklist
if (ent.Comp.Blacklist.IsValid(uid))
continue;
if (Random.Prob(ent.Comp.WireCutChance))
{
EnsureComp<CutWireOnMapInitComponent>(uid);
wiresCut++;
// Limit max wires cut
if (wiresCut >= ent.Comp.MaxWiresCut)
break;
}
}
}
}

View File

@@ -249,7 +249,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
_playerManager.Sessions,
component.PatientZeroPrototypeId,
includeAllJobs: false,
customExcludeCondition: player => HasComp<ZombieImmuneComponent>(player) || HasComp<InitialInfectedExemptComponent>(player)
customExcludeCondition: player => HasComp<ZombieImmuneComponent>(player) || HasComp<InitialInfectedExemptComponent>(player)
);
//And get all players, excluding ZombieImmune and roles with CanBeAntag = False - to fill any leftover initial infected slots
@@ -259,7 +259,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
acceptableAntags: Shared.Antag.AntagAcceptability.All,
includeAllJobs: false ,
ignorePreferences: true,
customExcludeCondition: HasComp<ZombieImmuneComponent>
customExcludeCondition: HasComp<ZombieImmuneComponent>
);
//If there are no players to choose, abort
@@ -293,6 +293,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem<ZombieRuleComponent>
//Add the role to the mind silently (to avoid repeating job assignment)
_roles.MindAddRole(mind, new InitialInfectedRoleComponent { PrototypeId = component.PatientZeroPrototypeId }, silent: true);
EnsureComp<InitialInfectedComponent>(entity);
//Add the zombie components and grace period
var pending = EnsureComp<PendingZombieComponent>(entity);

View File

@@ -1,36 +1,23 @@
using Content.Shared.Examine;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.IdentityManagement;
using Content.Shared.Preferences;
using Content.Shared.Verbs;
using Robust.Shared.GameObjects.Components.Localization;
using Robust.Shared.Prototypes;
namespace Content.Server.Humanoid;
public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
{
[Dependency] private readonly MarkingManager _markingManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HumanoidAppearanceComponent, HumanoidMarkingModifierMarkingSetMessage>(OnMarkingsSet);
SubscribeLocalEvent<HumanoidAppearanceComponent, HumanoidMarkingModifierBaseLayersSetMessage>(OnBaseLayersSet);
SubscribeLocalEvent<HumanoidAppearanceComponent, GetVerbsEvent<Verb>>(OnVerbsRequest);
SubscribeLocalEvent<HumanoidAppearanceComponent, ExaminedEvent>(OnExamined);
}
private void OnExamined(EntityUid uid, HumanoidAppearanceComponent component, ExaminedEvent args)
{
var identity = Identity.Entity(uid, EntityManager);
var species = GetSpeciesRepresentation(component.Species).ToLower();
var age = GetAgeRepresentation(component.Species, component.Age);
args.PushText(Loc.GetString("humanoid-appearance-component-examine", ("user", identity), ("age", age), ("species", species)));
}
// this was done enough times that it only made sense to do it here
@@ -165,42 +152,4 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
Dirty(uid, humanoid);
}
/// <summary>
/// Takes ID of the species prototype, returns UI-friendly name of the species.
/// </summary>
public string GetSpeciesRepresentation(string speciesId)
{
if (_prototypeManager.TryIndex<SpeciesPrototype>(speciesId, out var species))
{
return Loc.GetString(species.Name);
}
else
{
return Loc.GetString("humanoid-appearance-component-unknown-species");
}
}
public string GetAgeRepresentation(string species, int age)
{
_prototypeManager.TryIndex<SpeciesPrototype>(species, out var speciesPrototype);
if (speciesPrototype == null)
{
Log.Error("Tried to get age representation of species that couldn't be indexed: " + species);
return Loc.GetString("identity-age-young");
}
if (age < speciesPrototype.YoungAge)
{
return Loc.GetString("identity-age-young");
}
if (age < speciesPrototype.OldAge)
{
return Loc.GetString("identity-age-middle-aged");
}
return Loc.GetString("identity-age-old");
}
}

View File

@@ -1,3 +1,4 @@
using Content.Shared.Damage;
using Robust.Shared.Audio;
namespace Content.Server.ImmovableRod;
@@ -36,4 +37,16 @@ public sealed partial class ImmovableRodComponent : Component
/// </summary>
[DataField("destroyTiles")]
public bool DestroyTiles = true;
/// <summary>
/// If true, this will gib & delete bodies
/// </summary>
[DataField]
public bool ShouldGib = true;
/// <summary>
/// Damage done, if not gibbing
/// </summary>
[DataField]
public DamageSpecifier? Damage;
}

View File

@@ -1,9 +1,10 @@
using Content.Server.Body.Systems;
using Content.Server.Polymorph.Components;
using Content.Server.Popups;
using Content.Shared.Body.Components;
using Content.Shared.Damage;
using Content.Shared.Examine;
using Content.Shared.Popups;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
@@ -22,6 +23,8 @@ public sealed class ImmovableRodSystem : EntitySystem
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
public override void Update(float frameTime)
{
@@ -64,11 +67,11 @@ public sealed class ImmovableRodSystem : EntitySystem
var vel = component.DirectionOverride.Degrees switch
{
0f => _random.NextVector2(component.MinSpeed, component.MaxSpeed),
_ => xform.WorldRotation.RotateVec(component.DirectionOverride.ToVec()) * _random.NextFloat(component.MinSpeed, component.MaxSpeed)
_ => _transform.GetWorldRotation(uid).RotateVec(component.DirectionOverride.ToVec()) * _random.NextFloat(component.MinSpeed, component.MaxSpeed)
};
_physics.ApplyLinearImpulse(uid, vel, body: phys);
xform.LocalRotation = (vel - xform.WorldPosition).ToWorldAngle() + MathHelper.PiOver2;
xform.LocalRotation = (vel - _transform.GetWorldPosition(uid)).ToWorldAngle() + MathHelper.PiOver2;
}
}
@@ -94,12 +97,28 @@ public sealed class ImmovableRodSystem : EntitySystem
return;
}
// gib em
// dont delete/hurt self if polymoprhed into a rod
if (TryComp<PolymorphedEntityComponent>(uid, out var polymorphed))
{
if (polymorphed.Parent == ent)
return;
}
// gib or damage em
if (TryComp<BodyComponent>(ent, out var body))
{
component.MobCount++;
_popup.PopupEntity(Loc.GetString("immovable-rod-penetrated-mob", ("rod", uid), ("mob", ent)), uid, PopupType.LargeCaution);
if (!component.ShouldGib)
{
if (component.Damage == null || !TryComp<DamageableComponent>(ent, out var damageable))
return;
_damageable.SetDamage(ent, damageable, component.Damage);
return;
}
_bodySystem.GibBody(ent, body: body);
return;
}

View File

@@ -49,6 +49,12 @@ public sealed class HealthAnalyzerSystem : EntitySystem
if (component.ScannedEntity is not {} patient)
continue;
if (Deleted(patient))
{
StopAnalyzingEntity((uid, component), patient);
continue;
}
component.NextUpdate = _timing.CurTime + component.UpdateInterval;
//Get distance between health analyzer and the scanned entity

View File

@@ -33,6 +33,7 @@ public sealed class SuitSensorSystem : EntitySystem
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly StationSystem _stationSystem = default!;
[Dependency] private readonly SingletonDeviceNetServerSystem _singletonServerSystem = default!;
[Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!;
public override void Initialize()
{
@@ -344,6 +345,11 @@ public sealed class SuitSensorSystem : EntitySystem
if (TryComp<DamageableComponent>(sensor.User.Value, out var damageable))
totalDamage = damageable.TotalDamage.Int();
// Get mob total damage crit threshold
int? totalDamageThreshold = null;
if (_mobThresholdSystem.TryGetThresholdForState(sensor.User.Value, Shared.Mobs.MobState.Critical, out var critThreshold))
totalDamageThreshold = critThreshold.Value.Int();
// finally, form suit sensor status
var status = new SuitSensorStatus(GetNetEntity(uid), userName, userJob, userJobIcon, userJobDepartments);
switch (sensor.Mode)
@@ -354,10 +360,12 @@ public sealed class SuitSensorSystem : EntitySystem
case SuitSensorMode.SensorVitals:
status.IsAlive = isAlive;
status.TotalDamage = totalDamage;
status.TotalDamageThreshold = totalDamageThreshold;
break;
case SuitSensorMode.SensorCords:
status.IsAlive = isAlive;
status.TotalDamage = totalDamage;
status.TotalDamageThreshold = totalDamageThreshold;
EntityCoordinates coordinates;
var xformQuery = GetEntityQuery<TransformComponent>();
@@ -402,6 +410,8 @@ public sealed class SuitSensorSystem : EntitySystem
if (status.TotalDamage != null)
payload.Add(SuitSensorConstants.NET_TOTAL_DAMAGE, status.TotalDamage);
if (status.TotalDamageThreshold != null)
payload.Add(SuitSensorConstants.NET_TOTAL_DAMAGE_THRESHOLD, status.TotalDamageThreshold);
if (status.Coordinates != null)
payload.Add(SuitSensorConstants.NET_COORDINATES, status.Coordinates);
@@ -429,12 +439,14 @@ public sealed class SuitSensorSystem : EntitySystem
// try get total damage and cords (optionals)
payload.TryGetValue(SuitSensorConstants.NET_TOTAL_DAMAGE, out int? totalDamage);
payload.TryGetValue(SuitSensorConstants.NET_TOTAL_DAMAGE_THRESHOLD, out int? totalDamageThreshold);
payload.TryGetValue(SuitSensorConstants.NET_COORDINATES, out NetCoordinates? coords);
var status = new SuitSensorStatus(suitSensorUid, name, job, jobIcon, jobDepartments)
{
IsAlive = isAlive.Value,
TotalDamage = totalDamage,
TotalDamageThreshold = totalDamageThreshold,
Coordinates = coords,
};
return status;

View File

@@ -66,11 +66,16 @@ public sealed class TegNodeGroup : BaseNodeGroup
public override void LoadNodes(List<Node> groupNodes)
{
DebugTools.Assert(groupNodes.Count <= 3, "The TEG has at most 3 parts");
DebugTools.Assert(_entityManager != null);
base.LoadNodes(groupNodes);
if (groupNodes.Count > 3)
{
// Somehow got more TEG parts. Probably shenanigans. Bail.
return;
}
Generator = groupNodes.OfType<TegNodeGenerator>().SingleOrDefault();
if (Generator != null)
{

View File

@@ -264,6 +264,11 @@ public sealed class ThrusterSystem : EntitySystem
return;
}
if (TryComp<ApcPowerReceiverComponent>(uid, out var apcPower))
{
apcPower.NeedsPower = true;
}
component.IsOn = true;
if (!EntityManager.TryGetComponent(xform.GridUid, out ShuttleComponent? shuttleComponent))
@@ -366,6 +371,11 @@ public sealed class ThrusterSystem : EntitySystem
if (!EntityManager.TryGetComponent(gridId, out ShuttleComponent? shuttleComponent))
return;
if (TryComp<ApcPowerReceiverComponent>(uid, out var apcPower))
{
apcPower.NeedsPower = false;
}
// Logger.DebugS("thruster", $"Disabled thruster {uid}");
switch (component.Type)

View File

@@ -1,40 +1,54 @@
using System.Threading;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Server.Spawners.Components
namespace Content.Server.Spawners.Components;
/// <summary>
/// Spawns entities at a set interval.
/// Can configure the set of entities, spawn timing, spawn chance,
/// and min/max number of entities to spawn.
/// </summary>
[RegisterComponent]
public sealed partial class TimedSpawnerComponent : Component, ISerializationHooks
{
[RegisterComponent]
public sealed partial class TimedSpawnerComponent : Component, ISerializationHooks
/// <summary>
/// List of entities that can be spawned by this component. One will be randomly
/// chosen for each entity spawned. When multiple entities are spawned at once,
/// each will be randomly chosen separately.
/// </summary>
[DataField]
public List<EntProtoId> Prototypes = [];
/// <summary>
/// Chance of an entity being spawned at the end of each interval.
/// </summary>
[DataField]
public float Chance = 1.0f;
/// <summary>
/// Length of the interval between spawn attempts.
/// </summary>
[DataField]
public int IntervalSeconds = 60;
/// <summary>
/// The minimum number of entities that can be spawned when an interval elapses.
/// </summary>
[DataField]
public int MinimumEntitiesSpawned = 1;
/// <summary>
/// The maximum number of entities that can be spawned when an interval elapses.
/// </summary>
[DataField]
public int MaximumEntitiesSpawned = 1;
public CancellationTokenSource? TokenSource;
void ISerializationHooks.AfterDeserialization()
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField("prototypes", customTypeSerializer:typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Prototypes { get; set; } = new();
[ViewVariables(VVAccess.ReadWrite)]
[DataField("chance")]
public float Chance { get; set; } = 1.0f;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("intervalSeconds")]
public int IntervalSeconds { get; set; } = 60;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("MinimumEntitiesSpawned")]
public int MinimumEntitiesSpawned { get; set; } = 1;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("MaximumEntitiesSpawned")]
public int MaximumEntitiesSpawned { get; set; } = 1;
public CancellationTokenSource? TokenSource;
void ISerializationHooks.AfterDeserialization()
{
if (MinimumEntitiesSpawned > MaximumEntitiesSpawned)
throw new ArgumentException("MaximumEntitiesSpawned can't be lower than MinimumEntitiesSpawned!");
}
if (MinimumEntitiesSpawned > MaximumEntitiesSpawned)
throw new ArgumentException("MaximumEntitiesSpawned can't be lower than MinimumEntitiesSpawned!");
}
}

View File

@@ -1,3 +1,4 @@
using System.Linq;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Silicons.Laws;
using Content.Server.Station.Components;
@@ -143,6 +144,24 @@ public sealed class IonStormRule : StationEventSystem<IonStormRuleComponent>
});
}
// sets all unobfuscated laws' indentifier in order from highest to lowest priority
// This could technically override the Obfuscation from the code above, but it seems unlikely enough to basically never happen
int orderDeduction = -1;
for (int i = 0; i < laws.Laws.Count; i++)
{
string notNullIdentifier = laws.Laws[i].LawIdentifierOverride ?? (i - orderDeduction).ToString();
if (notNullIdentifier.Any(char.IsSymbol))
{
orderDeduction += 1;
}
else
{
laws.Laws[i].LawIdentifierOverride = (i - orderDeduction).ToString();
}
}
_adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent):silicon} had its laws changed by an ion storm to {laws.LoggingString()}");
// laws unique to this silicon, dont use station laws anymore

View File

@@ -93,6 +93,9 @@ public sealed partial class ActivatableUISystem : EntitySystem
if (component.InHandsOnly)
return;
if (component.AllowedItems != null)
return;
args.Handled = InteractUI(args.User, uid, component);
}
@@ -104,6 +107,9 @@ public sealed partial class ActivatableUISystem : EntitySystem
if (component.RightClickOnly)
return;
if (component.AllowedItems != null)
return;
args.Handled = InteractUI(args.User, uid, component);
}

View File

@@ -0,0 +1,10 @@
namespace Content.Server.Wires;
/// <summary>
/// Picks a random wire on the entity's <see cref="WireComponent"/> and cuts it.
/// Runs at MapInit and removes itself afterwards.
/// </summary>
[RegisterComponent]
public sealed partial class CutWireOnMapInitComponent : Component
{
}

View File

@@ -0,0 +1,34 @@
using Robust.Shared.Random;
namespace Content.Server.Wires;
/// <summary>
/// Handles cutting a random wire on devices that have <see cref="CutWireOnMapInitComponent"/>.
/// </summary>
public sealed partial class CutWireOnMapInitSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<CutWireOnMapInitComponent, MapInitEvent>(OnMapInit, after: [typeof(WiresSystem)]);
}
private void OnMapInit(Entity<CutWireOnMapInitComponent> entity, ref MapInitEvent args)
{
if (TryComp<WiresComponent>(entity, out var panel) && panel.WiresList.Count > 0)
{
// Pick a random wire
var targetWire = _random.Pick(panel.WiresList);
// Cut the wire
if (targetWire.Action == null || targetWire.Action.Cut(EntityUid.Invalid, targetWire))
targetWire.IsCut = true;
}
// Our work here is done
RemCompDeferred(entity, entity.Comp);
}
}

View File

@@ -1,4 +1,5 @@
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
namespace Content.Server.Wires;
@@ -15,7 +16,7 @@ public sealed partial class WiresComponent : Component
/// The layout ID of this entity's wires.
/// </summary>
[DataField(required: true)]
public string LayoutId { get; set; } = default!;
public ProtoId<WireLayoutPrototype> LayoutId { get; set; } = default!;
/// <summary>
/// The serial number of this board. Randomly generated upon start,

View File

@@ -318,6 +318,7 @@ public sealed class AccessReaderSystem : EntitySystem
{
component.AccessLists.Add(new HashSet<ProtoId<AccessLevelPrototype>>(){access});
}
Dirty(uid, component);
RaiseLocalEvent(uid, new AccessReaderConfigurationChangedEvent());
}

View File

@@ -80,6 +80,10 @@ public abstract class AlertsSystem : EntitySystem
/// <param name="showCooldown">if true, the cooldown will be visibly shown over the alert icon</param>
public void ShowAlert(EntityUid euid, AlertType alertType, short? severity = null, (TimeSpan, TimeSpan)? cooldown = null, bool autoRemove = false, bool showCooldown = true )
{
// This should be handled as part of networking.
if (_timing.ApplyingState)
return;
if (!TryComp(euid, out AlertsComponent? alertsComponent))
return;
@@ -148,6 +152,9 @@ public abstract class AlertsSystem : EntitySystem
/// </summary>
public void ClearAlert(EntityUid euid, AlertType alertType)
{
if (_timing.ApplyingState)
return;
if (!EntityManager.TryGetComponent(euid, out AlertsComponent? alertsComponent))
return;

View File

@@ -95,13 +95,13 @@ public sealed partial class AnomalyComponent : Component
/// The minimum interval between pulses.
/// </summary>
[DataField]
public TimeSpan MinPulseLength = TimeSpan.FromMinutes(1);
public TimeSpan MinPulseLength = TimeSpan.FromMinutes(2);
/// <summary>
/// The maximum interval between pulses.
/// </summary>
[DataField]
public TimeSpan MaxPulseLength = TimeSpan.FromMinutes(2);
public TimeSpan MaxPulseLength = TimeSpan.FromMinutes(4);
/// <summary>
/// A percentage by which the length of a pulse might vary.

View File

@@ -4,6 +4,7 @@ using Content.Shared.DragDrop;
using Content.Shared.GameTicking;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.Containers;
using Robust.Shared.Map;
@@ -22,6 +23,7 @@ public abstract class SharedCryostorageSystem : EntitySystem
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] protected readonly SharedMindSystem Mind = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
protected EntityUid? PausedMap { get; private set; }
@@ -81,6 +83,12 @@ public abstract class SharedCryostorageSystem : EntitySystem
if (args.Container.ID != comp.ContainerId)
return;
if (_mobState.IsIncapacitated(args.EntityUid))
{
args.Cancel();
return;
}
if (!TryComp<MindContainerComponent>(args.EntityUid, out var mindContainer))
{
args.Cancel();

View File

@@ -543,8 +543,8 @@ namespace Content.Shared.CCVar
* Console
*/
public static readonly CVarDef<bool>
ConsoleLoginLocal = CVarDef.Create("console.loginlocal", true, CVar.ARCHIVE | CVar.SERVERONLY);
public static readonly CVarDef<bool> ConsoleLoginLocal =
CVarDef.Create("console.loginlocal", true, CVar.ARCHIVE | CVar.SERVERONLY);
/// <summary>
/// Automatically log in the given user as host, equivalent to the <c>promotehost</c> command.
@@ -726,7 +726,7 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> CombatModeIndicatorsPointShow =
CVarDef.Create("hud.combat_mode_indicators_point_show", true, CVar.ARCHIVE | CVar.CLIENTONLY);
public static readonly CVarDef<bool> LoocAboveHeadShow =
CVarDef.Create("hud.show_looc_above_head", true, CVar.ARCHIVE | CVar.CLIENTONLY);
@@ -836,6 +836,7 @@ namespace Content.Shared.CCVar
/// <summary>
/// Should the ban details in admin channel include PII? (IP, HWID, etc)
/// </summary>
public static readonly CVarDef<bool> AdminShowPIIOnBan =
CVarDef.Create("admin.show_pii_onban", false, CVar.SERVERONLY);
@@ -1224,6 +1225,9 @@ namespace Content.Shared.CCVar
/// </summary>
public static readonly CVarDef<bool> OocEnableDuringRound =
CVarDef.Create("ooc.enable_during_round", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER);
public static readonly CVarDef<bool> ShowOocPatronColor =
CVarDef.Create("ooc.show_ooc_patron_color", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.CLIENT);
/*
* LOOC

View File

@@ -32,16 +32,30 @@ public sealed partial class CargoBountyConsoleComponent : Component
/// </summary>
[DataField("printSound")]
public SoundSpecifier PrintSound = new SoundPathSpecifier("/Audio/Machines/printer.ogg");
/// <summary>
/// The sound made when the bounty is skipped.
/// </summary>
[DataField("skipSound")]
public SoundSpecifier SkipSound = new SoundPathSpecifier("/Audio/Effects/Cargo/ping.ogg");
/// <summary>
/// The sound made when bounty skipping is denied due to lacking access.
/// </summary>
[DataField("denySound")]
public SoundSpecifier DenySound = new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_two.ogg");
}
[NetSerializable, Serializable]
public sealed class CargoBountyConsoleState : BoundUserInterfaceState
{
public List<CargoBountyData> Bounties;
public TimeSpan UntilNextSkip;
public CargoBountyConsoleState(List<CargoBountyData> bounties)
public CargoBountyConsoleState(List<CargoBountyData> bounties, TimeSpan untilNextSkip)
{
Bounties = bounties;
UntilNextSkip = untilNextSkip;
}
}
@@ -55,3 +69,14 @@ public sealed class BountyPrintLabelMessage : BoundUserInterfaceMessage
BountyId = bountyId;
}
}
[Serializable, NetSerializable]
public sealed class BountySkipMessage : BoundUserInterfaceMessage
{
public string BountyId;
public BountySkipMessage(string bountyId)
{
BountyId = bountyId;
}
}

View File

@@ -27,6 +27,6 @@ public sealed partial class TypingIndicatorPrototype : IPrototype
public Vector2 Offset = new(0, 0);
[DataField("shader")]
public string Shader = "unshaded";
public string Shader = "shaded";
}

View File

@@ -91,7 +91,7 @@ public abstract class ClothingSystem : EntitySystem
private void ToggleVisualLayer(EntityUid equipee, HumanoidVisualLayers layer, string tag)
{
InventorySystem.InventorySlotEnumerator enumerator = _invSystem.GetSlotEnumerator(equipee);
InventorySystem.InventorySlotEnumerator enumerator = _invSystem.GetSlotEnumerator(equipee, SlotFlags.HEAD ^ SlotFlags.MASK);
bool shouldLayerShow = true;
while (enumerator.NextItem(out EntityUid item))
@@ -164,7 +164,7 @@ public abstract class ClothingSystem : EntitySystem
{
if (args.Handled || args.Cancelled || args.Target is not { } target)
return;
args.Handled = _invSystem.TryEquip(args.User, target, ent, args.Slot, clothing: ent.Comp, predicted: true, checkDoafter: false);
args.Handled = _invSystem.TryEquip(args.User, target, ent, args.Slot, clothing: ent.Comp, predicted: true, checkDoafter: false);
}
private void OnUnequipDoAfter(Entity<ClothingComponent> ent, ref ClothingUnequipDoAfterEvent args)

View File

@@ -11,7 +11,7 @@ namespace Content.Shared.Communications
public sealed class CommunicationsConsoleInterfaceState : BoundUserInterfaceState
{
public readonly bool CanAnnounce;
public readonly bool CanBroadcast;
public readonly bool CanBroadcast = true;
public readonly bool CanCall;
public readonly TimeSpan? ExpectedCountdownEnd;
public readonly bool CountdownStarted;

View File

@@ -29,4 +29,10 @@ public sealed partial class SpillableComponent : Component
/// </summary>
[DataField]
public FixedPoint2 MaxMeleeSpillAmount = FixedPoint2.New(20);
/// <summary>
/// Should this item be spilled when thrown?
/// </summary>
[DataField]
public bool SpillWhenThrown = true;
}

View File

@@ -134,8 +134,10 @@ public abstract partial class SharedHandsSystem
return true;
}
var (itemPos, itemRot) = TransformSystem.GetWorldPositionRotation(entity);
var origin = new MapCoordinates(itemPos, itemXform.MapID);
var target = targetDropLocation.Value.ToMap(EntityManager, TransformSystem);
TransformSystem.SetWorldPosition(itemXform, GetFinalDropCoordinates(uid, userXform.MapPosition, target));
TransformSystem.SetWorldPositionRotation(entity, GetFinalDropCoordinates(uid, origin, target), itemRot);
return true;
}

View File

@@ -1,9 +1,10 @@
using System.Linq;
using Content.Shared.Decals;
using Content.Shared.Examine;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Corvax.TTS;
using Content.Shared.Decals;
using Content.Shared.IdentityManagement;
using Content.Shared.Preferences;
using Robust.Shared.GameObjects.Components.Localization;
using Robust.Shared.Network;
@@ -23,7 +24,7 @@ namespace Content.Shared.Humanoid;
public abstract class SharedHumanoidAppearanceSystem : EntitySystem
{
[Dependency] private readonly INetManager _netManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly MarkingManager _markingManager = default!;
[ValidatePrototypeId<SpeciesPrototype>]
@@ -41,7 +42,9 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<HumanoidAppearanceComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<HumanoidAppearanceComponent, ExaminedEvent>(OnExamined);
}
private void OnInit(EntityUid uid, HumanoidAppearanceComponent humanoid, ComponentInit args)
@@ -52,7 +55,7 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
}
if (string.IsNullOrEmpty(humanoid.Initial)
|| !_prototypeManager.TryIndex(humanoid.Initial, out HumanoidProfilePrototype? startingSet))
|| !_proto.TryIndex(humanoid.Initial, out HumanoidProfilePrototype? startingSet))
{
LoadProfile(uid, HumanoidCharacterProfile.DefaultWithSpecies(humanoid.Species), humanoid);
return;
@@ -67,6 +70,15 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
LoadProfile(uid, startingSet.Profile, humanoid);
}
private void OnExamined(EntityUid uid, HumanoidAppearanceComponent component, ExaminedEvent args)
{
var identity = Identity.Entity(uid, EntityManager);
var species = GetSpeciesRepresentation(component.Species).ToLower();
var age = GetAgeRepresentation(component.Species, component.Age);
args.PushText(Loc.GetString("humanoid-appearance-component-examine", ("user", identity), ("age", age), ("species", species)));
}
/// <summary>
/// Toggles a humanoid's sprite layer visibility.
/// </summary>
@@ -147,7 +159,7 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
/// <param name="humanoid">Humanoid component of the entity</param>
public void SetSpecies(EntityUid uid, string species, bool sync = true, HumanoidAppearanceComponent? humanoid = null)
{
if (!Resolve(uid, ref humanoid) || !_prototypeManager.TryIndex<SpeciesPrototype>(species, out var prototype))
if (!Resolve(uid, ref humanoid) || !_proto.TryIndex<SpeciesPrototype>(species, out var prototype))
{
return;
}
@@ -155,7 +167,7 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
humanoid.Species = species;
humanoid.MarkingSet.EnsureSpecies(species, humanoid.SkinColor, _markingManager);
var oldMarkings = humanoid.MarkingSet.GetForwardEnumerator().ToList();
humanoid.MarkingSet = new(oldMarkings, prototype.MarkingPoints, _markingManager, _prototypeManager);
humanoid.MarkingSet = new(oldMarkings, prototype.MarkingPoints, _markingManager, _proto);
if (sync)
Dirty(uid, humanoid);
@@ -175,7 +187,7 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
if (!Resolve(uid, ref humanoid))
return;
if (!_prototypeManager.TryIndex<SpeciesPrototype>(humanoid.Species, out var species))
if (!_proto.TryIndex<SpeciesPrototype>(humanoid.Species, out var species))
{
return;
}
@@ -299,24 +311,24 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
// Hair/facial hair - this may eventually be deprecated.
// We need to ensure hair before applying it or coloring can try depend on markings that can be invalid
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, out var hairAlpha, _prototypeManager)
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, out var hairAlpha, _proto)
? profile.Appearance.SkinColor.WithAlpha(hairAlpha) : profile.Appearance.HairColor;
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair, out var facialHairAlpha, _prototypeManager)
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair, out var facialHairAlpha, _proto)
? profile.Appearance.SkinColor.WithAlpha(facialHairAlpha) : profile.Appearance.FacialHairColor;
if (_markingManager.Markings.TryGetValue(profile.Appearance.HairStyleId, out var hairPrototype) &&
_markingManager.CanBeApplied(profile.Species, profile.Sex, hairPrototype, _prototypeManager))
_markingManager.CanBeApplied(profile.Species, profile.Sex, hairPrototype, _proto))
{
AddMarking(uid, profile.Appearance.HairStyleId, hairColor, false);
}
if (_markingManager.Markings.TryGetValue(profile.Appearance.FacialHairStyleId, out var facialHairPrototype) &&
_markingManager.CanBeApplied(profile.Species, profile.Sex, facialHairPrototype, _prototypeManager))
_markingManager.CanBeApplied(profile.Species, profile.Sex, facialHairPrototype, _proto))
{
AddMarking(uid, profile.Appearance.FacialHairStyleId, facialHairColor, false);
}
humanoid.MarkingSet.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _prototypeManager);
humanoid.MarkingSet.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _proto);
// Finally adding marking with forced colors
foreach (var (marking, prototype) in markingFColored)
@@ -422,4 +434,39 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
comp.VoicePrototypeId = voiceId;
}
// Corvax-TTS-End
/// <summary>
/// Takes ID of the species prototype, returns UI-friendly name of the species.
/// </summary>
public string GetSpeciesRepresentation(string speciesId)
{
if (_proto.TryIndex<SpeciesPrototype>(speciesId, out var species))
{
return Loc.GetString(species.Name);
}
Log.Error("Tried to get representation of unknown species: {speciesId}");
return Loc.GetString("humanoid-appearance-component-unknown-species");
}
public string GetAgeRepresentation(string species, int age)
{
if (!_proto.TryIndex<SpeciesPrototype>(species, out var speciesPrototype))
{
Log.Error("Tried to get age representation of species that couldn't be indexed: " + species);
return Loc.GetString("identity-age-young");
}
if (age < speciesPrototype.YoungAge)
{
return Loc.GetString("identity-age-young");
}
if (age < speciesPrototype.OldAge)
{
return Loc.GetString("identity-age-middle-aged");
}
return Loc.GetString("identity-age-old");
}
}

View File

@@ -682,7 +682,7 @@ namespace Content.Shared.Interaction
if (!inRange && popup && _gameTiming.IsFirstTimePredicted)
{
var message = Loc.GetString("interaction-system-user-interaction-cannot-reach");
_popupSystem.PopupEntity(message, origin, origin);
_popupSystem.PopupClient(message, origin, origin);
}
return inRange;

View File

@@ -23,6 +23,8 @@ public sealed class SuitSensorStatus
public List<string> JobDepartments;
public bool IsAlive;
public int? TotalDamage;
public int? TotalDamageThreshold;
public float? DamagePercentage => TotalDamageThreshold == null || TotalDamage == null ? null : TotalDamage / TotalDamageThreshold;
public NetCoordinates? Coordinates;
}
@@ -58,6 +60,7 @@ public static class SuitSensorConstants
public const string NET_JOB_DEPARTMENTS = "jobDepartments";
public const string NET_IS_ALIVE = "alive";
public const string NET_TOTAL_DAMAGE = "vitals";
public const string NET_TOTAL_DAMAGE_THRESHOLD = "vitalsThreshold";
public const string NET_COORDINATES = "coords";
public const string NET_SUIT_SENSOR_UID = "uid";

View File

@@ -98,16 +98,6 @@ public class RCDSystem : EntitySystem
component.ProtoId = args.ProtoId;
UpdateCachedPrototype(uid, component);
Dirty(uid, component);
if (args.Session.AttachedEntity != null)
{
// Popup message
var msg = (component.CachedPrototype.Prototype != null) ?
Loc.GetString("rcd-component-change-build-mode", ("name", Loc.GetString(component.CachedPrototype.SetName))) :
Loc.GetString("rcd-component-change-mode", ("mode", Loc.GetString(component.CachedPrototype.SetName)));
_popup.PopupClient(msg, uid, args.Session.AttachedEntity.Value);
}
}
private void OnExamine(EntityUid uid, RCDComponent component, ExaminedEvent args)
@@ -118,9 +108,18 @@ public class RCDSystem : EntitySystem
// Update cached prototype if required
UpdateCachedPrototype(uid, component);
var msg = (component.CachedPrototype.Prototype != null) ?
Loc.GetString("rcd-component-examine-build-details", ("name", Loc.GetString(component.CachedPrototype.SetName))) :
Loc.GetString("rcd-component-examine-mode-details", ("mode", Loc.GetString(component.CachedPrototype.SetName)));
var msg = Loc.GetString("rcd-component-examine-mode-details", ("mode", Loc.GetString(component.CachedPrototype.SetName)));
if (component.CachedPrototype.Mode == RcdMode.ConstructTile || component.CachedPrototype.Mode == RcdMode.ConstructObject)
{
var name = Loc.GetString(component.CachedPrototype.SetName);
if (component.CachedPrototype.Prototype != null &&
_protoManager.TryIndex(component.CachedPrototype.Prototype, out var proto))
name = proto.Name;
msg = Loc.GetString("rcd-component-examine-build-details", ("name", name));
}
args.PushMarkup(msg);
}
@@ -176,7 +175,7 @@ public class RCDSystem : EntitySystem
else
{
var deconstructedTile = _mapSystem.GetTileRef(mapGridData.Value.GridUid, mapGridData.Value.Component, mapGridData.Value.Location);
var protoName = deconstructedTile.IsSpace() ? _deconstructTileProto : _deconstructLatticeProto;
var protoName = !deconstructedTile.IsSpace() ? _deconstructTileProto : _deconstructLatticeProto;
if (_protoManager.TryIndex(protoName, out var deconProto))
{
@@ -206,7 +205,7 @@ public class RCDSystem : EntitySystem
// Try to start the do after
var effect = Spawn(effectPrototype, mapGridData.Value.Location);
var ev = new RCDDoAfterEvent(GetNetCoordinates(mapGridData.Value.Location), component.ProtoId, cost, EntityManager.GetNetEntity(effect));
var ev = new RCDDoAfterEvent(GetNetCoordinates(mapGridData.Value.Location), component.ConstructionDirection, component.ProtoId, cost, EntityManager.GetNetEntity(effect));
var doAfterArgs = new DoAfterArgs(EntityManager, user, delay, ev, uid, target: args.Target, used: uid)
{
@@ -263,7 +262,7 @@ public class RCDSystem : EntitySystem
return;
// Finalize the operation
FinalizeRCDOperation(uid, component, mapGridData.Value, args.Target, args.User);
FinalizeRCDOperation(uid, component, mapGridData.Value, args.Direction, args.Target, args.User);
// Play audio and consume charges
_audio.PlayPredicted(component.SuccessSound, uid, args.User);
@@ -419,7 +418,7 @@ public class RCDSystem : EntitySystem
foreach (var fixture in fixtures.Fixtures.Values)
{
// Continue if no collision is possible
if (fixture.CollisionLayer <= 0 || (fixture.CollisionLayer & (int) component.CachedPrototype.CollisionMask) == 0)
if (!fixture.Hard || fixture.CollisionLayer <= 0 || (fixture.CollisionLayer & (int) component.CachedPrototype.CollisionMask) == 0)
continue;
// Continue if our custom collision bounds are not intersected
@@ -494,7 +493,7 @@ public class RCDSystem : EntitySystem
#region Entity construction/deconstruction
private void FinalizeRCDOperation(EntityUid uid, RCDComponent component, MapGridData mapGridData, EntityUid? target, EntityUid user)
private void FinalizeRCDOperation(EntityUid uid, RCDComponent component, MapGridData mapGridData, Direction direction, EntityUid? target, EntityUid user)
{
if (!_net.IsServer)
return;
@@ -521,7 +520,7 @@ public class RCDSystem : EntitySystem
Transform(ent).LocalRotation = Transform(uid).LocalRotation;
break;
case RcdRotation.User:
Transform(ent).LocalRotation = component.ConstructionDirection.ToAngle();
Transform(ent).LocalRotation = direction.ToAngle();
break;
}
@@ -617,6 +616,9 @@ public sealed partial class RCDDoAfterEvent : DoAfterEvent
[DataField(required: true)]
public NetCoordinates Location { get; private set; } = default!;
[DataField]
public Direction Direction { get; private set; } = default!;
[DataField]
public ProtoId<RCDPrototype> StartingProtoId { get; private set; } = default!;
@@ -628,9 +630,10 @@ public sealed partial class RCDDoAfterEvent : DoAfterEvent
private RCDDoAfterEvent() { }
public RCDDoAfterEvent(NetCoordinates location, ProtoId<RCDPrototype> startingProtoId, int cost, NetEntity? effect = null)
public RCDDoAfterEvent(NetCoordinates location, Direction direction, ProtoId<RCDPrototype> startingProtoId, int cost, NetEntity? effect = null)
{
Location = location;
Direction = direction;
StartingProtoId = startingProtoId;
Cost = cost;
Effect = effect;

View File

@@ -46,6 +46,12 @@ public partial class StatusIconData : IComparable<StatusIconData>
/// </summary>
[DataField]
public int Offset = 0;
/// <summary>
/// Sets if the icon should be rendered with or without the effect of lighting.
/// </summary>
[DataField]
public bool IsShaded = false;
}
/// <summary>

View File

@@ -159,11 +159,11 @@ public sealed class DumpableSystem : EntitySystem
{
dumped = true;
var targetPos = _transformSystem.GetWorldPosition(args.Args.Target.Value);
var (targetPos, targetRot) = _transformSystem.GetWorldPositionRotation(args.Args.Target.Value);
foreach (var entity in dumpQueue)
{
_transformSystem.SetWorldPosition(entity, targetPos + _random.NextVector2Box() / 4);
_transformSystem.SetWorldPositionRotation(entity, targetPos + _random.NextVector2Box() / 4, targetRot);
}
}
else

View File

@@ -48,7 +48,7 @@ public abstract class SharedTrayScannerSystem : EntitySystem
private void OnTrayScannerGetState(EntityUid uid, TrayScannerComponent scanner, ref ComponentGetState args)
{
args.State = new TrayScannerState(scanner.Enabled);
args.State = new TrayScannerState(scanner.Enabled, scanner.Range);
}
private void OnTrayScannerHandleState(EntityUid uid, TrayScannerComponent scanner, ref ComponentHandleState args)
@@ -56,6 +56,7 @@ public abstract class SharedTrayScannerSystem : EntitySystem
if (args.Current is not TrayScannerState state)
return;
scanner.Range = state.Range;
SetScannerEnabled(uid, state.Enabled, scanner);
}
}

View File

@@ -22,9 +22,11 @@ public sealed partial class TrayScannerComponent : Component
public sealed class TrayScannerState : ComponentState
{
public bool Enabled;
public float Range;
public TrayScannerState(bool enabled)
public TrayScannerState(bool enabled, float range)
{
Enabled = enabled;
Range = range;
}
}

View File

@@ -144,5 +144,13 @@ Entries:
id: 19
time: '2024-03-31T02:05:44.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26546
- author: PJB3005
changes:
- message: The new "grant_connect_bypass" command grants a player the ability to
connect, bypassing whitelist, player cap and panic bunker.
type: Add
id: 20
time: '2024-04-09T15:25:21.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26771
Name: Admin
Order: 1

View File

@@ -1,299 +1,4 @@
Entries:
- author: yathxyz
changes:
- message: Updated nixpkgs input
type: Tweak
id: 5793
time: '2024-01-26T01:40:52.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24572
- author: mirrorcult
changes:
- message: We lied Atomic Amnesia MMX is back
type: Add
id: 5794
time: '2024-01-26T05:48:29.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24575
- author: EmoGarbage404
changes:
- message: Cigarettes no longer deal cellular damage when smoked.
type: Remove
id: 5795
time: '2024-01-26T09:50:03.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24568
- author: ERORR404V1
changes:
- message: Added mime hardsuit
type: Add
id: 5796
time: '2024-01-26T14:43:50.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24198
- author: icekot8
changes:
- message: Correct display of syndicate jaws of life in hand
type: Add
id: 5797
time: '2024-01-27T02:27:14.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24583
- author: Agoichi
changes:
- message: Detective cabinet now have security holoprojector in interests of investigation
type: Tweak
- message: Security lockers have chance to spawn security holoprojector (0.5)
type: Tweak
id: 5798
time: '2024-01-27T02:29:40.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24582
- author: TheShuEd
changes:
- message: Flesh and Rock anomalies have been reworked to place entities more dynamically
when spawning.
type: Tweak
id: 5799
time: '2024-01-27T02:52:07.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24449
- author: PJB3005
changes:
- message: PACMAN-type portable generators now show power statistics for the network
they're connected to.
type: Add
- message: JRPACMAN has been buffed from 5 kW to 8 kW.
type: Tweak
id: 5800
time: '2024-01-27T02:53:44.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24604
- author: Blackern5000
changes:
- message: Shotgun slugs can now be printed in the security techfab.
type: Add
- message: Shotgun slugs now fire a single strong projectile when fired.
type: Tweak
id: 5801
time: '2024-01-27T02:56:57.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24196
- author: I-JustUser-I
changes:
- message: Zombie Outbreak event now has a minimum limit of 15 players.
type: Tweak
id: 5802
time: '2024-01-27T03:53:09.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24577
- author: mirrorcult
changes:
- message: Navmap now defaults to showing departments
type: Tweak
id: 5803
time: '2024-01-27T12:08:50.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24613
- author: Tayrtahn
changes:
- message: Vending machines can now be repaired with a welder.
type: Tweak
id: 5804
time: '2024-01-27T12:12:53.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24603
- author: graevy
changes:
- message: Added hallway screen prototypes and comms console text broadcasts.
type: Add
id: 5805
time: '2024-01-27T13:51:25.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24189
- author: mirrorcult
changes:
- message: Lights are now shaded with the same color that they glow.
type: Tweak
id: 5806
time: '2024-01-27T17:43:45.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24612
- author: Boaz1111
changes:
- message: The PKA shuttle gun now breaks rocks in one hit.
type: Tweak
id: 5807
time: '2024-01-27T17:47:35.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24627
- author: FungiFellow
changes:
- message: Ion Storms are twice as likely to occur.
type: Tweak
id: 5808
time: '2024-01-27T23:14:09.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24633
- author: PJB3005
changes:
- message: Security barriers need 5 seconds to lock and unlock.
type: Tweak
id: 5809
time: '2024-01-28T00:28:02.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24637
- author: themias
changes:
- message: Added cowboy hats and boots to autodrobe, secdrobe, and maints
type: Add
- message: Added cowboy accent
type: Add
id: 5810
time: '2024-01-28T03:23:16.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24299
- author: shampunj
changes:
- message: A new game preset! Can only be selected by admins. All at once.
type: Add
id: 5811
time: '2024-01-28T10:41:36.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/23171
- author: Doctor-Cpu
changes:
- message: 3kliksphilips name.
type: Fix
id: 5812
time: '2024-01-28T10:46:32.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24657
- author: mirrorcult
changes:
- message: Speech sounds are now quieter
type: Tweak
id: 5813
time: '2024-01-28T10:49:55.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24579
- author: TheShuEd
changes:
- message: The fire anomaly is now heavier in content.
type: Tweak
- message: Artifacts no longer block projectiles.
type: Tweak
id: 5814
time: '2024-01-29T01:30:55.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24666
- author: Krunk
changes:
- message: Health analysis interfaces now also display a subject's temperature in
Kelvin.
type: Add
id: 5815
time: '2024-01-29T01:32:54.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24643
- author: Ubaser
changes:
- message: Detectives now work as independent agents, separate from security, and
are encouraged to answer any requests for help.
type: Tweak
id: 5816
time: '2024-01-29T06:45:27.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/23114
- author: mirrorcult
changes:
- message: Rotting examine text doesn't have weird grammatical errors now
type: Fix
id: 5817
time: '2024-01-29T07:50:18.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24689
- author: Eden077
changes:
- message: Synaptizine now deals less poison damage.
type: Tweak
id: 5818
time: '2024-01-29T07:55:52.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24676
- author: mirrorcult
changes:
- message: Various annoying sounds are now a little quieter
type: Tweak
id: 5819
time: '2024-01-29T09:51:31.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24690
- author: SpeltIncorrectyl
changes:
- message: Portable generators can now be connected to the signal network and controlled
remotely via devices like a signal transmitter.
type: Add
id: 5820
time: '2024-01-29T14:56:29.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24157
- author: Tayrtahn
changes:
- message: Welders properly display their lit status again.
type: Fix
id: 5821
time: '2024-01-29T23:04:52.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24705
- author: Tayrtahn
changes:
- message: Water bottles now display their fill level while held.
type: Add
id: 5822
time: '2024-01-29T23:19:56.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24708
- author: SlamBamActionman
changes:
- message: Arachnids slipping in water now get a cute hat!
type: Add
id: 5823
time: '2024-01-30T00:21:26.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/23822
- author: Tayrtahn
changes:
- message: Pressing shift as a ghost no longer cancels following your target
type: Fix
id: 5824
time: '2024-01-30T01:33:35.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24715
- author: liltenhead
changes:
- message: Jugs are now destructible.
type: Tweak
id: 5825
time: '2024-01-30T08:11:43.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24719
- author: Emisse
changes:
- message: Aspid
type: Remove
id: 5826
time: '2024-01-30T10:26:02.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24725
- author: mirrorcult
changes:
- message: Throwing items now scale a bit when thrown to simulate rising/falling
type: Add
id: 5827
time: '2024-01-30T10:50:41.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24724
- author: Emisse
changes:
- message: Gemini
type: Remove
id: 5828
time: '2024-01-30T10:54:55.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24728
- author: CrigCrag
changes:
- message: Added a new large salvage wreck.
type: Add
id: 5829
time: '2024-01-30T10:56:38.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24656
- author: themias
changes:
- message: Fixed Centcom cargo gifts not being fulfilled
type: Fix
id: 5830
time: '2024-01-30T11:05:20.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24701
- author: Scribbles0
changes:
- message: You can now make anomaly cores orbit you.
type: Add
id: 5831
time: '2024-01-30T11:12:24.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24716
- author: MIXnikita
changes:
- message: New sound effects for some shuttle guns
type: Tweak
id: 5832
time: '2024-01-30T13:28:17.0000000+00:00'
url: https://api.github.com/repos/space-wizards/space-station-14/pulls/24714
- author: themias
changes:
- message: Stun batons now toggle off after being drained by an EMP.
@@ -3810,3 +3515,316 @@
id: 6292
time: '2024-04-02T05:18:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26515
- author: lzk228
changes:
- message: Typing indicator now can be shaded by shadows.
type: Tweak
id: 6293
time: '2024-04-03T02:12:47.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26678
- author: EmoGarbage404
changes:
- message: Increased time between pulses for various anomalies.
type: Tweak
id: 6294
time: '2024-04-03T03:15:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26677
- author: Plykiya
changes:
- message: Dropped items are no longer rotated to world north.
type: Fix
id: 6295
time: '2024-04-03T05:31:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26662
- author: deltanedas
changes:
- message: Disabled scooping foam due to a reagent duplication bug.
type: Fix
id: 6296
time: '2024-04-03T13:41:23.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26686
- author: Aserovich
changes:
- message: New lobby art!
type: Add
id: 6297
time: '2024-04-04T05:28:30.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26505
- author: Beck Thompson
changes:
- message: Items thrown at disposals now have to be insertable to display the miss
message.
type: Fix
id: 6298
time: '2024-04-04T06:25:47.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26716
- author: Tayrtahn
changes:
- message: Some devices may have broken wiring at the start of each round.
type: Add
id: 6299
time: '2024-04-04T06:28:09.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26695
- author: lzk228
changes:
- message: Turning off thrusters and gyroscopes now stop consume power.
type: Fix
id: 6300
time: '2024-04-04T06:28:33.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26690
- author: Aexxie
changes:
- message: Added the option to disable your OOC Patron name color.
type: Add
id: 6301
time: '2024-04-04T07:20:06.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26653
- author: DinoWattz
changes:
- message: Fixed pocket slots being able to hide character snout markings.
type: Fix
id: 6302
time: '2024-04-04T08:35:44.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26708
- author: VasilisThePikachu
changes:
- message: Mop buckets and Janitorial Trolleys will not spill their contents as
soon as they are pushed.
type: Fix
- message: Mop buckets are no longer solid. So you can now walk through them.
type: Fix
id: 6303
time: '2024-04-04T08:39:55.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26706
- author: ZeroDayDaemon
changes:
- message: Lowered the number of ducks in the duck crate and reduced the price of
it.
type: Tweak
id: 6304
time: '2024-04-04T19:30:13.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26729
- author: PrPleGoo
changes:
- message: The medical HUD's brightness now scales with lighting again.
type: Tweak
- message: Most HUD icon's brightness now scale with lighting.
type: Tweak
id: 6305
time: '2024-04-04T23:05:01.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26726
- author: Daemon
changes:
- message: Practice projectiles have been given standardized minimal damage.
type: Tweak
- message: The practice laser gun now works with shooting targets.
type: Tweak
id: 6306
time: '2024-04-05T03:15:02.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26731
- author: Daemon
changes:
- message: Shooting targets can now have their popup type changed with a left click
to show total damage, damage of a single hit, both, or just a notice that it
was hit.
type: Tweak
id: 6307
time: '2024-04-05T07:19:41.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26734
- author: Vermidia
changes:
- message: Baseball bats now require a knife to craft
type: Tweak
id: 6308
time: '2024-04-05T15:41:35.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26742
- author: deltanedas
changes:
- message: Making fultons now requires cloth and they are faster to make.
type: Tweak
id: 6309
time: '2024-04-05T15:42:12.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26747
- author: superjj18
changes:
- message: Broadcasting works again!
type: Fix
id: 6310
time: '2024-04-05T17:29:22.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26750
- author: Golinth
changes:
- message: Fixed mindshield icons being glow in the dark
type: Fix
id: 6311
time: '2024-04-05T20:35:32.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26754
- author: Blackern5000
changes:
- message: Added sap
type: Add
- message: Added syrup, it can be made by boiling sap.
type: Add
- message: Dionae now bleed sap instead of water
type: Tweak
id: 6312
time: '2024-04-05T21:06:12.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/25748
- author: osjarw
changes:
- message: Thin firelocks are now constructable/deconstructable
type: Fix
id: 6313
time: '2024-04-06T01:55:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26745
- author: BITTERLYNX
changes:
- message: Rodents are more visually pleasing to burn
type: Fix
- message: mothroach and hammy also more visually pleasing to burn
type: Fix
id: 6314
time: '2024-04-06T04:41:23.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26758
- author: Plykiya
changes:
- message: You can now carefully walk over glass shards and D4.
type: Tweak
id: 6315
time: '2024-04-06T04:49:14.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26763
- author: PursuitInAshes
changes:
- message: Sake Bottles can now be found in the booze-o-mat.
type: Tweak
id: 6316
time: '2024-04-06T20:16:47.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26776
- author: osjarw
changes:
- message: Removed broken anom behaviour, which causes APE shots to fly through
the anom.
type: Remove
id: 6317
time: '2024-04-06T22:27:16.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26775
- author: Vermidia
changes:
- message: Water coolers show how full/what they're full of again.
type: Fix
id: 6318
time: '2024-04-06T23:58:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26784
- author: Crotalus
changes:
- message: Show missing materials in lathe tooltip
type: Add
id: 6319
time: '2024-04-08T03:16:11.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26795
- author: chromiumboy
changes:
- message: Fixed the RCD not being able to build on top of puddles
type: Fix
- message: RCD constructions can no longer be rotated while in progress
type: Tweak
- message: The RCD now reports construction mode changes to its user
type: Add
id: 6320
time: '2024-04-08T03:17:29.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26792
- author: lzk228
changes:
- message: Bombsuit and jani bombsuit are similar now.
type: Tweak
id: 6321
time: '2024-04-08T15:05:58.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26806
- author: lzk228
changes:
- message: Clothing restock crate was splitted to clothing and autodrobe restock
crates.
type: Tweak
- message: Clothing is cheaper.
type: Tweak
id: 6322
time: '2024-04-08T15:10:58.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26805
- author: Hanzdegloker
changes:
- message: Spears can now be quipped to your suit slot and cost slightly more to
make.
type: Tweak
id: 6323
time: '2024-04-08T15:34:35.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26724
- author: KittenColony
changes:
- message: Added 13 new gauze wraps for moth that fit their twig bodies
type: Add
- message: Gauze markings have been moved to the Overlay category, allowing gauze
to not take up marking points
type: Tweak
id: 6324
time: '2024-04-09T08:04:51.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/25481
- author: Killerqu00
changes:
- message: Quartermasters can now skip a single bounty in the list once every 15
minutes.
type: Add
id: 6325
time: '2024-04-09T22:18:07.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26537
- author: SkaldetSkaeg
changes:
- message: The Flippo lighter is now quieter and has a delay on use.
type: Tweak
id: 6326
time: '2024-04-09T22:20:57.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26846
- author: notquitehadouken
changes:
- message: Gave botanists droppers for easier chemical moving.
type: Add
id: 6327
time: '2024-04-10T17:28:03.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26839
- author: botanySupremist
changes:
- message: Clipping harvestable plants now yields undamaged seeds.
type: Add
id: 6328
time: '2024-04-10T17:51:25.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/25541
- author: deltanedas
changes:
- message: Fixed some doors having no access when they should.
type: Fix
id: 6329
time: '2024-04-10T20:06:31.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26858
- author: Flareguy
changes:
- message: Added emergency nitrogen lockers. You can scarcely find them in public
areas, or scattered around in maintenance tunnels.
type: Add
id: 6330
time: '2024-04-10T21:20:05.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26752
- author: Jark255
changes:
- message: Door electronics now require network configurators to change the access
of them, rather by hand.
type: Fix
id: 6331
time: '2024-04-11T12:21:15.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26888
- author: lunarcomets
changes:
- message: Cryogenic sleep units now remove crew members from the manifest, and
announce when crew members go into cryogenic storage.
type: Tweak
id: 6332
time: '2024-04-11T20:48:46.0000000+00:00'
url: https://github.com/space-wizards/space-station-14/pull/26813

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,16 @@
## Strings for the "grant_connect_bypass" command.
cmd-grant_connect_bypass-desc = Temporarily allow a user to bypass regular connection checks.
cmd-grant_connect_bypass-help = Usage: grant_connect_bypass <user> [duration minutes]
Temporarily grants a user the ability to bypass regular connections restrictions.
The bypass only applies to this game server and will expire after (by default) 1 hour.
They will be able to join regardless of whitelist, panic bunker, or player cap.
cmd-grant_connect_bypass-arg-user = <user>
cmd-grant_connect_bypass-arg-duration = [duration minutes]
cmd-grant_connect_bypass-invalid-args = Expected 1 or 2 arguments
cmd-grant_connect_bypass-unknown-user = Unable to find user '{$user}'
cmd-grant_connect_bypass-invalid-duration = Invalid duration '{$duration}'
cmd-grant_connect_bypass-success = Successfully added bypass for user '{$user}'

View File

@@ -0,0 +1,5 @@
### Announcement
earlyleave-cryo-announcement = {$character} ({$job}) has entered cryogenic storage!
earlyleave-cryo-sender = Station

View File

@@ -1,5 +1,6 @@
bounty-console-menu-title = Cargo bounty console
bounty-console-label-button-text = Print label
bounty-console-skip-button-text = Skip
bounty-console-time-label = Time: [color=orange]{$time}[/color]
bounty-console-reward-label = Reward: [color=limegreen]${$reward}[/color]
bounty-console-manifest-label = Manifest: [color=orange]{$item}[/color]

View File

@@ -42,6 +42,7 @@ ui-options-volume-percent = { TOSTRING($volume, "P0") }
ui-options-show-held-item = Show held item next to cursor
ui-options-show-combat-mode-indicators = Show combat mode indicators with cursor
ui-options-opaque-storage-window = Opaque storage window
ui-options-show-ooc-patron-color = Show OOC Patreon color
ui-options-show-looc-on-head = Show LOOC chat above characters head
ui-options-fancy-speech = Show names in speech bubbles
ui-options-fancy-name-background = Add background to speech bubble names

View File

@@ -13,6 +13,10 @@ lathe-menu-material-amount = { $amount ->
[1] {NATURALFIXED($amount, 2)} {$unit}
*[other] {NATURALFIXED($amount, 2)} {MAKEPLURAL($unit)}
}
lathe-menu-material-amount-missing = { $amount ->
[1] {NATURALFIXED($amount, 2)} {$unit} of {$material} ([color=red]{NATURALFIXED($missingAmount, 2)} {$unit} missing[/color])
*[other] {NATURALFIXED($amount, 2)} {MAKEPLURAL($unit)} of {$material} ([color=red]{NATURALFIXED($missingAmount, 2)} {MAKEPLURAL($unit)} missing[/color])
}
lathe-menu-no-materials-message = No materials loaded.
lathe-menu-fabricating-message = Fabricating...
lathe-menu-materials-title = Materials

View File

@@ -1,17 +1,17 @@
marking-GauzeLefteyePatch-gauze_lefteye_2 = Gauze eyepatch (Left)
marking-GauzeLefteyePatch = Gauze eyepatch (Left)
marking-GauzeLefteyeTape-gauze_lefteye_1 = Gauze eyepad (Left)
marking-GauzeLefteyeTape = Gauze eyepad (Left)
marking-GauzeLefteyePad-gauze_lefteye_1 = Gauze eyepad (Left)
marking-GauzeLefteyePad = Gauze eyepad (Left)
marking-GauzeRighteyePatch-gauze_righteye_2 = Gauze eyepatch (Right)
marking-GauzeRighteyePatch = Gauze eyepatch (Right)
marking-GauzeRighteyeTape-gauze_righteye_1 = Gauze eyepad (Right)
marking-GauzeRighteyeTape = Gauze eyepad (Right)
marking-GauzeRighteyePad-gauze_righteye_1 = Gauze eyepad (Right)
marking-GauzeRighteyePad = Gauze eyepad (Right)
marking-GauzeShoulder-gauze_shoulder = Gauze Shoulder
marking-GauzeShoulder = Gauze Shoulder
marking-GauzeShoulder-gauze_shoulder = Gauze Shoulder Sling
marking-GauzeShoulder = Gauze Shoulder Sling
marking-GauzeStomach-gauze_abdomen = Gauze Stomach Wrap
marking-GauzeStomach = Gauze Stomach Wrap
@@ -46,17 +46,57 @@ marking-GauzeUpperLegRight = Gauze Thigh Wrap (Right)
marking-GauzeBlindfold-gauze_blindfold = Gauze Blindfold
marking-GauzeBlindfold = Gauze Blindfold
marking-GauzeLizardBlindfold-gauze_lizardblindfold = Gauze Blindfold
marking-GauzeLizardBlindfold-gauze_lizard_blindfold = Gauze Blindfold
marking-GauzeLizardBlindfold = Gauze Blindfold
marking-GauzeLizardFootRight-gauze_lizardfoot_r = Gauze Foot Wrap (Right)
marking-GauzeLizardFootRight-gauze_lizard_foot_r = Gauze Foot Wrap (Right)
marking-GauzeLizardFootRight = Gauze Foot Wrap (Right)
marking-GauzeLizardFootLeft-gauze_lizardfoot_l = Gauze Foot Wrap (Left)
marking-GauzeLizardFootLeft-gauze_lizard_foot_l = Gauze Foot Wrap (Left)
marking-GauzeLizardFootLeft = Gauze Foot Wrap (Left)
marking-GauzeLizardLefteyePatch-gauze_lizardlefteye = Adjusted Gauze eyepatch (Left)
marking-GauzeLizardLefteyePatch = Adjusted Gauze eyepatch (Left)
marking-GauzeLizardLefteyePatch-gauze_lizard_lefteye = Reptilian Gauze eyepatch (Left)
marking-GauzeLizardLefteyePatch = Reptilian Gauze eyepatch (Left)
marking-GauzeLizardRighteyePatch-gauze_lizard_righteye = Reptilian Gauze eyepatch (Right)
marking-GauzeLizardRighteyePatch = Reptilian Gauze Eyepatch (Right)
marking-GauzeMothStomach-gauze_moth_abdomen = Insectoid Stomach Wrap
marking-GauzeMothStomach = Insectoid Stomach Wrap
marking-GauzeMothShoulder-gauze_moth_shoulder = Insectoid Shoulder Sling
marking-GauzeMothShoulder = Insectoid Shoulder Sling
marking-GauzeMothBlindfold-gauze_moth_blindfold = Insectoid Blindfold
marking-GauzeMothBlindfold = Insectoid Blindfold
marking-GauzeMothLeftEyePatch-gauze_moth_lefteye_2 = Insectoid Gauze eyepatch (Left)
marking-GauzeMothLeftEyePatch = Insectoid Gauze eyepatch (Left)
marking-GauzeMothLeftEyePad-gauze_moth_lefteye_1 = Insectoid Gauze eyepad (Left)
marking-GauzeMothLeftEyePad = Insectoid Gauze eyepad (Left)
marking-GauzeMothRightEyePatch-gauze_moth_righteye_2 = Insectoid Gauze eyepatch (Right)
marking-GauzeMothRightEyePatch = Insectoid Gauze eyepatch (Right)
marking-GauzeMothRightEyePad-gauze_moth_righteye_1 = Insectoid Gauze eyepad (Right)
marking-GauzeMothRightEyePad = Insectoid Gauze eyepad (Right)
marking-GauzeMothUpperArmRight-gauze_moth_upperarm_r = Insectoid Gauze Forearm Wrap (Right)
marking-GauzeMothUpperArmRight = Insectoid Gauze Forearm Wrap (Right)
marking-GauzeMothUpperArmLeft-gauze_moth_upperarm_l = Insectoid Gauze Forearm Wrap (Left)
marking-GauzeMothUpperArmLeft = Insectoid Gauze Forearm Wrap (Left)
marking-GauzeMothUpperLegRight-gauze_moth_upperleg_r = Insectoid Gauze Thigh Wrap (Right)
marking-GauzeMothUpperLegRight = Insectoid Insectoid Gauze Thigh Wrap (Right)
marking-GauzeMothUpperLegLeft-gauze_moth_upperleg_l = Insectoid Gauze Thigh Wrap (Left)
marking-GauzeMothUpperLegLeft = Insectoid Gauze Thigh Wrap (Left)
marking-GauzeMothLowerLegRight-gauze_moth_lowerleg_r = Insectoid Gauze Shin Wrap (Right)
marking-GauzeMothLowerLegRight = Insectoid Gauze Shin Wrap (Right)
marking-GauzeMothLowerLegLeft-gauze_moth_lowerleg_l = Insectoid Gauze Shin Wrap (Left)
marking-GauzeMothLowerLegLeft = Insectoid Gauze Shin Wrap (Left)
marking-GauzeLizardRighteyePatch-gauze_lizardrighteye = Adjusted Gauze eyepatch (Right)
marking-GauzeLizardRighteyePatch = Adjusted Gauze Eyepatch (Right)

View File

@@ -43,24 +43,5 @@ rcd-component-lighting = Lighting
### Prototype names (note: constructable items will be puralized)
rcd-component-deconstruct = deconstruct
rcd-component-wall-solid = solid wall
rcd-component-floor-steel = steel tile
rcd-component-plating = hull plate
rcd-component-catwalk = catwalk
rcd-component-wall-reinforced = reinforced wall
rcd-component-grille = grille
rcd-component-window = window
rcd-component-window-directional = directional window
rcd-component-window-reinforced-directional = directional reinforced window
rcd-component-reinforced-window = reinforced window
rcd-component-airlock = standard airlock
rcd-component-airlock-glass = glass airlock
rcd-component-firelock = firelock
rcd-component-computer-frame = computer frame
rcd-component-machine-frame = machine frame
rcd-component-tube-light = light
rcd-component-window-bulb-light = small light
rcd-component-window-lv-cable = LV cable
rcd-component-window-mv-cable = MV cable
rcd-component-window-hv-cable = HV cable
rcd-component-window-cable-terminal = cable terminal

View File

@@ -7,6 +7,9 @@ reagent-desc-insect-blood = Okay, this is really gross. It almost looks.. alive?
reagent-name-slime = slime
reagent-desc-slime = You thought this was gradient blood at first, but you were mistaken.
reagent-name-sap = sap
reagent-desc-sap = Sticky, sweet tree blood.
reagent-name-hemocyanin-blood = blue blood
reagent-desc-hemocyanin-blood = Contains copper as opposed to iron which gives it a distinct blue color.

View File

@@ -39,3 +39,6 @@ reagent-desc-soysauce = A salty soy-based flavoring.
reagent-name-table-salt = table salt
reagent-desc-table-salt = Commonly known as salt, Sodium Chloride is often used to season food or kill borers instantly.
reagent-name-syrup = syrup
reagent-desc-syrup = Delicious syrup made from tree sap, somehow stickier than glue.

View File

@@ -117,3 +117,6 @@ chatsan-replacement-42 = of course
chatsan-word-43 = ig
chatsan-replacement-43 = i guess
chatsan-word-44 = tbf
chatsan-replacement-44 = to be fair

File diff suppressed because it is too large Load Diff

View File

@@ -470,6 +470,7 @@
# chatsan-word-41: chatsan-replacement-41
# chatsan-word-42: chatsan-replacement-42
# chatsan-word-43: chatsan-replacement-43
# chatsan-word-44: chatsan-replacement-44
corvax-chatsan-word-1: corvax-chatsan-replacement-1
corvax-chatsan-word-2: corvax-chatsan-replacement-2
corvax-chatsan-word-3: corvax-chatsan-replacement-3

View File

@@ -20,7 +20,6 @@
InconstancyParticle: 0.5
FullUnknown: 0.5
Jumping: 0.3
Moving: 0.1
#Complex
FastUnknown: 0.2
JumpingUnknown: 0.1
@@ -133,19 +132,6 @@
shuffleOnParticleHit: true
prob: 0.8
- type: anomalyBehavior
id: Moving
earnPointModifier: 2.2
description: anomaly-behavior-moving
components:
- type: RandomWalk
minSpeed: 0
maxSpeed: 0.3
- type: CanMoveInAir
- type: Physics
bodyType: Dynamic
bodyStatus: InAir
- type: anomalyBehavior
id: Jumping
earnPointModifier: 1.8

View File

@@ -37,7 +37,7 @@
- state: lung-l-slime
- state: lung-r-slime
- type: Lung
Alert: LowNitrogen
alert: LowNitrogen
- type: Metabolizer
removeEmpty: true
solutionOnBody: false

View File

@@ -46,7 +46,7 @@
- ReagentId: UncookedAnimalProteins
Quantity: 5
- type: Metabolizer
updateFrequency: 1.5
updateInterval: 1.5
- type: entity
id: OrganArachnidLungs
@@ -60,7 +60,7 @@
- state: lung-r
- type: Lung
- type: Metabolizer
updateFrequency: 1.5
updateInterval: 1.5
removeEmpty: true
solutionOnBody: false
solution: "Lung"
@@ -92,7 +92,7 @@
- type: Sprite
state: heart-on
- type: Metabolizer
updateFrequency: 1.5
updateInterval: 1.5
maxReagents: 2
metabolizerTypes: [Arachnid]
groups:
@@ -110,7 +110,7 @@
- type: Sprite
state: liver
- type: Metabolizer # The liver metabolizes certain chemicals only, like alcohol.
updateFrequency: 1.5
updateInterval: 1.5
maxReagents: 1
metabolizerTypes: [Animal]
groups:
@@ -130,7 +130,7 @@
- state: kidney-r
# The kidneys just remove anything that doesn't currently have any metabolisms, as a stopgap.
- type: Metabolizer
updateFrequency: 1.5
updateInterval: 1.5
maxReagents: 5
metabolizerTypes: [Animal]
removeEmpty: true

View File

@@ -4,7 +4,7 @@
sprite: Clothing/Head/Helmets/bombsuit.rsi
state: icon
product: CrateEmergencyExplosive
cost: 650
cost: 1000
category: cargoproduct-category-name-emergency
group: market

View File

@@ -54,7 +54,7 @@
sprite: Mobs/Animals/duck.rsi
state: icon-0
product: CrateNPCDuck
cost: 6000
cost: 4000
category: cargoproduct-category-name-livestock
group: market

View File

@@ -33,7 +33,17 @@
sprite: Objects/Specific/Service/vending_machine_restock.rsi
state: base
product: CrateVendingMachineRestockClothesFilled
cost: 6000
cost: 2400
category: cargoproduct-category-name-service
group: market
- type: cargoProduct
id: CrateVendingMachineRestockAutoDrobe
icon:
sprite: Objects/Specific/Service/vending_machine_restock.rsi
state: base
product: CrateVendingMachineRestockAutoDrobeFilled
cost: 1200
category: cargoproduct-category-name-service
group: market

View File

@@ -117,7 +117,7 @@
components:
- type: StorageFill
contents:
- id: BodyBag_Folded
- id: BodyBagFolded
amount: 4
- type: Sprite
layers:

View File

@@ -75,10 +75,10 @@
- type: StorageFill
contents:
- id: MobDuckMallard
amount: 2
- id: MobDuckWhite
amount: 2
amount: 1
- id: MobDuckBrown
amount: 1
- id: MobDuckWhite
amount: 2
- type: entity

View File

@@ -22,11 +22,20 @@
id: CrateVendingMachineRestockClothesFilled
parent: CratePlastic
name: clothing restock crate
description: Contains a pair of restock boxes, one for the ClothesMate and one for the AutoDrobe.
description: Contains a restock box for the clothes vending machines.
components:
- type: StorageFill
contents:
- id: VendingMachineRestockClothes
- type: entity
id: CrateVendingMachineRestockAutoDrobeFilled
parent: CratePlastic
name: AutoDrobe restock crate
description: Contains a restock box for the AutoDrobe.
components:
- type: StorageFill
contents:
- id: VendingMachineRestockCostumes
- type: entity

View File

@@ -61,6 +61,21 @@
- id: BoxMRE
prob: 0.1
- type: entity
id: ClosetEmergencyN2FilledRandom
parent: ClosetEmergencyN2
suffix: Filled, Random
components:
- type: StorageFill
contents:
- id: ClothingMaskBreath
- id: EmergencyNitrogenTankFilled
prob: 0.80
orGroup: EmergencyTankOrRegularTank
- id: NitrogenTankFilled
prob: 0.20
orGroup: EmergencyTankOrRegularTank
- type: entity
id: ClosetFireFilled
parent: ClosetFire

View File

@@ -104,6 +104,7 @@
- id: ClothingBeltPlant
- id: PlantBag ##Some maps don't have nutrivend
- id: BoxMouthSwab
- id: Dropper
- id: HandLabeler
- id: ClothingUniformOveralls
- id: ClothingHeadHatTrucker

View File

@@ -39,6 +39,7 @@
DrinkWhiskeyBottleFull: 5
DrinkWineBottleFull: 5
DrinkChampagneBottleFull: 2 #because the premium drink
DrinkSakeBottleFull: 3
DrinkBeerCan: 5
DrinkWineCan: 5
emaggedInventory:

View File

@@ -6,6 +6,7 @@
HydroponicsToolClippers: 4
HydroponicsToolScythe: 4
HydroponicsToolHatchet: 4
Dropper: 4
PlantBag: 3
PlantBGoneSpray: 20
WeedSpray: 20

View File

@@ -14,7 +14,7 @@
materialComposition:
Cloth: 50
- type: StaticPrice
price: 25
price: 20
- type: entity
abstract: true

View File

@@ -113,7 +113,7 @@
#Janitorial Bombsuit Helmet
- type: entity
parent: ClothingHeadBase
parent: ClothingHeadHelmetBombSuit
id: ClothingHeadHelmetJanitorBombSuit
name: janitorial bombsuit helmet
description: A heavy helmet designed to withstand explosions formed from reactions between chemicals.
@@ -123,9 +123,6 @@
sprite: Clothing/Head/Helmets/janitor_bombsuit.rsi
- type: Clothing
sprite: Clothing/Head/Helmets/janitor_bombsuit.rsi
- type: IngestionBlocker
- type: ExplosionResistance
damageCoefficient: 0.9
#Cult Helmet
- type: entity

View File

@@ -177,6 +177,8 @@
materialComposition:
Steel: 50
Plastic: 100
- type: StaticPrice
price: 12.5 # increases in price after decomposed into raw materials
- type: entity
parent: ClothingMaskBase

View File

@@ -43,7 +43,6 @@
suffix: Voice Mask, Chameleon
components:
- type: VoiceMasker
default: ClothingMaskGas
# Corvax-HiddenDesc-Start
- type: HiddenDescription
entries:

View File

@@ -41,7 +41,7 @@
- key: enum.StorageUiKey.Key
type: StorageBoundUserInterface
- type: StaticPrice
price: 80
price: 70
- type: entity
abstract: true

View File

@@ -8,6 +8,9 @@
sprite: Clothing/OuterClothing/Suits/bombsuit.rsi
- type: Clothing
sprite: Clothing/OuterClothing/Suits/bombsuit.rsi
- type: ClothingSpeedModifier
walkModifier: 0.8
sprintModifier: 0.8
- type: Armor
modifiers:
coefficients:
@@ -24,7 +27,7 @@
- WhitelistChameleon
- type: entity
parent: ClothingOuterBaseLarge
parent: ClothingOuterSuitBomb
id: ClothingOuterSuitJanitorBomb
name: janitorial bomb suit
description: A heavy helmet designed to withstand explosions formed from reactions between chemicals.
@@ -34,16 +37,6 @@
sprite: Clothing/OuterClothing/Suits/janitor_bombsuit.rsi
- type: Clothing
sprite: Clothing/OuterClothing/Suits/janitor_bombsuit.rsi
- type: ClothingSpeedModifier
walkModifier: 0.8
sprintModifier: 0.8
- type: ExplosionResistance
damageCoefficient: 0.15
- type: GroupExamine
- type: Tag
tags:
- Hardsuit
- WhitelistChameleon
- type: entity
parent: ClothingOuterBaseLarge

View File

@@ -32,7 +32,7 @@
- ClothMade
- WhitelistChameleon
- type: StaticPrice
price: 70
price: 50
- type: entity
parent: ClothingOuterWinterCoat

View File

@@ -10,7 +10,7 @@
tags:
- WhitelistChameleon
- type: StaticPrice
price: 15
price: 10
- type: entity
abstract: true

View File

@@ -77,8 +77,9 @@
animationState: foam-dissolve
- type: Slippery
- type: StepTrigger
- type: ScoopableSolution
solution: solutionArea
# disabled until foam reagent duplication is fixed
#- type: ScoopableSolution
# solution: solutionArea
- type: entity
id: MetalFoam

View File

@@ -1,8 +1,8 @@
- type: marking
id: GauzeLefteyePatch
bodyPart: Eyes
markingCategory: Head
speciesRestriction: [Moth, Dwarf, Human, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Arachnid]
coloring:
default:
type:
@@ -13,10 +13,10 @@
state: gauze_lefteye_2
- type: marking
id: GauzeLefteyeTape
id: GauzeLefteyePad
bodyPart: Eyes
markingCategory: Head
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -29,8 +29,8 @@
- type: marking
id: GauzeRighteyePatch
bodyPart: Eyes
markingCategory: Head
speciesRestriction: [Moth, Dwarf, Human, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Arachnid]
coloring:
default:
type:
@@ -41,10 +41,10 @@
state: gauze_righteye_2
- type: marking
id: GauzeRighteyeTape
id: GauzeRighteyePad
bodyPart: Eyes
markingCategory: Head
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -57,8 +57,8 @@
- type: marking
id: GauzeBlindfold
bodyPart: Eyes
markingCategory: Head
speciesRestriction: [Moth, Dwarf, Human, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Arachnid]
coloring:
default:
type:
@@ -71,8 +71,8 @@
- type: marking
id: GauzeShoulder
bodyPart: Chest
markingCategory: Chest
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -85,8 +85,8 @@
- type: marking
id: GauzeStomach
bodyPart: Chest
markingCategory: Chest
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -99,8 +99,8 @@
- type: marking
id: GauzeUpperArmRight
bodyPart: RArm
markingCategory: Arms
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -113,8 +113,8 @@
- type: marking
id: GauzeLowerArmRight
bodyPart: RArm, RHand
markingCategory: Arms
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -127,8 +127,8 @@
- type: marking
id: GauzeLeftArm
bodyPart: LArm, LHand
markingCategory: Arms
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -141,8 +141,8 @@
- type: marking
id: GauzeLowerLegLeft
bodyPart: LFoot
markingCategory: Legs
speciesRestriction: [Moth, Dwarf, Human, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Arachnid]
coloring:
default:
type:
@@ -155,8 +155,8 @@
- type: marking
id: GauzeUpperLegLeft
bodyPart: LLeg
markingCategory: Legs
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -169,8 +169,8 @@
- type: marking
id: GauzeUpperLegRight
bodyPart: RLeg
markingCategory: Legs
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -183,8 +183,8 @@
- type: marking
id: GauzeLowerLegRight
bodyPart: RFoot
markingCategory: Legs
speciesRestriction: [Moth, Dwarf, Human, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Arachnid]
coloring:
default:
type:
@@ -197,8 +197,8 @@
- type: marking
id: GauzeBoxerWrapRight
bodyPart: RHand
markingCategory: Arms
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -211,8 +211,8 @@
- type: marking
id: GauzeBoxerWrapLeft
bodyPart: LHand
markingCategory: Arms
speciesRestriction: [Moth, Dwarf, Human, Reptilian, Arachnid]
markingCategory: Overlay
speciesRestriction: [Dwarf, Human, Reptilian, Arachnid]
coloring:
default:
type:
@@ -226,7 +226,7 @@
- type: marking
id: GauzeLizardLefteyePatch
bodyPart: Eyes
markingCategory: Head
markingCategory: Overlay
speciesRestriction: [Reptilian]
coloring:
default:
@@ -235,12 +235,12 @@
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_lizardlefteye
state: gauze_lizard_lefteye
- type: marking
id: GauzeLizardRighteyePatch
bodyPart: Eyes
markingCategory: Head
markingCategory: Overlay
speciesRestriction: [Reptilian]
coloring:
default:
@@ -249,12 +249,12 @@
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_lizardrighteye
state: gauze_lizard_righteye
- type: marking
id: GauzeLizardFootRight
bodyPart: RFoot
markingCategory: Legs
markingCategory: Overlay
speciesRestriction: [Reptilian]
coloring:
default:
@@ -263,12 +263,12 @@
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_lizardfoot_r
state: gauze_lizard_foot_r
- type: marking
id: GauzeLizardFootLeft
bodyPart: LFoot
markingCategory: Legs
markingCategory: Overlay
speciesRestriction: [Reptilian]
coloring:
default:
@@ -277,12 +277,12 @@
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_lizardfoot_l
state: gauze_lizard_foot_l
- type: marking
id: GauzeLizardBlindfold
bodyPart: Eyes
markingCategory: Head
markingCategory: Overlay
speciesRestriction: [Reptilian]
coloring:
default:
@@ -291,5 +291,187 @@
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_lizardblindfold
state: gauze_lizard_blindfold
# Moth Specific Markings
- type: marking
id: GauzeMothBlindfold
bodyPart: Eyes
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_blindfold
- type: marking
id: GauzeMothShoulder
bodyPart: Chest
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_shoulder
- type: marking
id: GauzeMothStomach
bodyPart: Chest
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_abdomen
- type: marking
id: GauzeMothLeftEyePatch
bodyPart: Eyes
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_lefteye_2
- type: marking
id: GauzeMothLeftEyePad
bodyPart: Eyes
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_lefteye_1
- type: marking
id: GauzeMothRightEyePatch
bodyPart: Eyes
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_righteye_2
- type: marking
id: GauzeMothRightEyePad
bodyPart: Eyes
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_righteye_1
- type: marking
id: GauzeMothUpperArmRight
bodyPart: RArm
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_upperarm_r
- type: marking
id: GauzeMothUpperArmLeft
bodyPart: LArm
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_upperarm_l
- type: marking
id: GauzeMothUpperLegRight
bodyPart: RLeg
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_upperleg_r
- type: marking
id: GauzeMothUpperLegLeft
bodyPart: LLeg
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_upperleg_l
- type: marking
id: GauzeMothLowerLegRight
bodyPart: RFoot
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_lowerleg_r
- type: marking
id: GauzeMothLowerLegLeft
bodyPart: LFoot
markingCategory: Overlay
speciesRestriction: [Moth]
coloring:
default:
type:
!type:SimpleColoring
color: "#FFFFFF"
sprites:
- sprite: Mobs/Customization/gauze.rsi
state: gauze_moth_lowerleg_l

View File

@@ -102,8 +102,6 @@
- type: BorgChassis
- type: WiresPanel
- type: ActivatableUIRequiresPanel
- type: Wires
layoutId: Borg
- type: NameIdentifier
group: Silicon
- type: ContainerContainer

Some files were not shown because too many files have changed in this diff Show More