Merge remote-tracking branch 'refs/remotes/upstream/master' into ed-17-05-2024-upstream
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<Control xmlns="https://spacestation14.io">
|
||||
<Control xmlns="https://spacestation14.io" HorizontalExpand="True">
|
||||
<BoxContainer Name="MainContainer"
|
||||
Orientation="Horizontal"
|
||||
SetWidth="160">
|
||||
HorizontalExpand="True">
|
||||
<PanelContainer Name="ColorPanel"
|
||||
VerticalExpand="True"
|
||||
SetWidth="7"
|
||||
@@ -16,8 +16,7 @@
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True"
|
||||
Margin="-5 0 0 0">
|
||||
<Label Name="ReagentNameLabel"
|
||||
StyleClasses="LabelSubText" />
|
||||
<Label Name="ReagentNameLabel" />
|
||||
<Label Name="FillLabel"
|
||||
StyleClasses="LabelSubText"
|
||||
Margin="0 -5 0 0" />
|
||||
|
||||
@@ -20,10 +20,12 @@ public sealed partial class ReagentCardControl : Control
|
||||
StorageSlotId = item.StorageSlotId;
|
||||
ColorPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = item.ReagentColor };
|
||||
ReagentNameLabel.Text = item.ReagentLabel;
|
||||
ReagentNameLabel.FontColorOverride = Color.White;
|
||||
FillLabel.Text = item.StoredAmount;
|
||||
FillLabel.Text = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", item.Quantity));;
|
||||
EjectButtonIcon.Text = Loc.GetString("reagent-dispenser-window-eject-container-button");
|
||||
|
||||
if (item.Quantity == 0.0)
|
||||
MainButton.Disabled = true;
|
||||
|
||||
MainButton.OnPressed += args => OnPressed?.Invoke(StorageSlotId);
|
||||
EjectButton.OnPressed += args => OnEjectButtonPressed?.Invoke(StorageSlotId);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
xmlns:ui="clr-namespace:Content.Client.Chemistry.UI"
|
||||
Title="{Loc 'reagent-dispenser-bound-user-interface-title'}"
|
||||
MinSize="680 460">
|
||||
MinSize="600 300"
|
||||
SetSize="800 500">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<BoxContainer Orientation="Vertical" MinWidth="170">
|
||||
<Label Text="{Loc 'reagent-dispenser-window-amount-to-dispense-label'}" HorizontalAlignment="Center" />
|
||||
|
||||
@@ -121,28 +121,4 @@ namespace Content.Client.Chemistry.UI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DispenseReagentButton : Button
|
||||
{
|
||||
public string ReagentId { get; }
|
||||
|
||||
public DispenseReagentButton(string reagentId, string text, string amount)
|
||||
{
|
||||
AddStyleClass("OpenRight");
|
||||
ReagentId = reagentId;
|
||||
Text = text + " " + amount;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EjectJugButton : Button
|
||||
{
|
||||
public string ReagentId { get; }
|
||||
|
||||
public EjectJugButton(string reagentId)
|
||||
{
|
||||
AddStyleClass("OpenLeft");
|
||||
ReagentId = reagentId;
|
||||
Text = "⏏";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,4 @@ using Content.Shared.CriminalRecords.Systems;
|
||||
|
||||
namespace Content.Client.CriminalRecords.Systems;
|
||||
|
||||
public sealed class CriminalRecordsConsoleSystem : SharedCriminalRecordsConsoleSystem
|
||||
{
|
||||
}
|
||||
public sealed class CriminalRecordsConsoleSystem : SharedCriminalRecordsConsoleSystem;
|
||||
|
||||
@@ -2,6 +2,4 @@ using Content.Shared.CriminalRecords.Systems;
|
||||
|
||||
namespace Content.Client.CriminalRecords.Systems;
|
||||
|
||||
public sealed class CriminalRecordsHackerSystem : SharedCriminalRecordsHackerSystem
|
||||
{
|
||||
}
|
||||
public sealed class CriminalRecordsHackerSystem : SharedCriminalRecordsHackerSystem;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
using Content.Shared.CriminalRecords.Systems;
|
||||
|
||||
namespace Content.Client.CriminalRecords.Systems;
|
||||
|
||||
public sealed class CriminalRecordsSystem : SharedCriminalRecordsSystem;
|
||||
@@ -153,7 +153,7 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
|
||||
}
|
||||
}
|
||||
else if (state == VisualState.OverlayCharging)
|
||||
sprite.LayerSetState(DisposalUnitVisualLayers.OverlayFlush, new RSI.StateId("disposal-charging"));
|
||||
sprite.LayerSetState(DisposalUnitVisualLayers.OverlayFlush, chargingState);
|
||||
else
|
||||
_animationSystem.Stop(uid, AnimationKey);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<!-- Left side -->
|
||||
<BoxContainer Orientation="Vertical" Margin="10 10 10 10" HorizontalExpand="True">
|
||||
<!-- Middle container -->
|
||||
<BoxContainer Orientation="Horizontal" SeparationOverride="10">
|
||||
<BoxContainer Orientation="Horizontal" SeparationOverride="10" HorizontalExpand="True">
|
||||
<!-- Name box-->
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<ui:HighlightedContainer>
|
||||
@@ -31,13 +31,13 @@
|
||||
</ui:HighlightedContainer>
|
||||
</BoxContainer>
|
||||
<!-- Import/Export -->
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<ui:HighlightedContainer>
|
||||
<BoxContainer Orientation="Horizontal" SeparationOverride="5">
|
||||
<BoxContainer Orientation="Vertical" MinSize="60 0" HorizontalExpand="True" HorizontalAlignment="Right">
|
||||
<ui:HighlightedContainer Name="ProfileHighlight">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<Button Name="SaveButton" Text="{Loc 'humanoid-profile-editor-save-button'}"/>
|
||||
<Button Name="ResetButton" Disabled="True" Text="{Loc 'humanoid-profile-editor-reset-button'}"/>
|
||||
<Button Name="ImportButton" Text="{Loc 'humanoid-profile-editor-import-button'}"/>
|
||||
<Button Name="ExportButton" Text="{Loc 'humanoid-profile-editor-export-button'}"/>
|
||||
<Button Name="SaveButton" Text="{Loc 'humanoid-profile-editor-save-button'}" />
|
||||
<Button Name="ResetButton" Disabled="True" Text="{Loc 'humanoid-profile-editor-reset-button'}"/>
|
||||
</BoxContainer>
|
||||
</ui:HighlightedContainer>
|
||||
</BoxContainer>
|
||||
|
||||
@@ -68,7 +68,7 @@ public sealed partial class RCDMenu : RadialMenu
|
||||
tooltip = Loc.GetString(entProto.Name);
|
||||
}
|
||||
|
||||
tooltip = char.ToUpper(tooltip[0]) + tooltip.Remove(0, 1);
|
||||
tooltip = OopsConcat(char.ToUpper(tooltip[0]).ToString(), tooltip.Remove(0, 1));
|
||||
|
||||
var button = new RCDMenuButton()
|
||||
{
|
||||
@@ -119,6 +119,12 @@ public sealed partial class RCDMenu : RadialMenu
|
||||
SendRCDSystemMessageAction += bui.SendRCDSystemMessage;
|
||||
}
|
||||
|
||||
private static string OopsConcat(string a, string b)
|
||||
{
|
||||
// This exists to prevent Roslyn being clever and compiling something that fails sandbox checks.
|
||||
return a + b;
|
||||
}
|
||||
|
||||
private void AddRCDMenuButtonOnClickActions(Control control)
|
||||
{
|
||||
var radialContainer = control as RadialContainer;
|
||||
|
||||
@@ -20,10 +20,14 @@ public sealed class SalvageMagnetBoundUserInterface : BoundUserInterface
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
_window = new OfferingWindow();
|
||||
_window.Title = Loc.GetString("salvage-magnet-window-title");
|
||||
_window.OnClose += Close;
|
||||
_window.OpenCenteredLeft();
|
||||
|
||||
if (_window is null)
|
||||
{
|
||||
_window = new OfferingWindow();
|
||||
_window.Title = Loc.GetString("salvage-magnet-window-title");
|
||||
_window.OnClose += Close;
|
||||
_window.OpenCenteredLeft();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
@@ -108,4 +112,15 @@ public sealed class SalvageMagnetBoundUserInterface : BoundUserInterface
|
||||
_window.AddOption(option);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_window?.Close();
|
||||
_window?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ public sealed class StorageContainer : BaseWindow
|
||||
|
||||
//todo. at some point, we may want to only rebuild the pieces that have actually received new data.
|
||||
|
||||
_pieceGrid.Children.Clear();
|
||||
_pieceGrid.RemoveAllChildren();
|
||||
_pieceGrid.Rows = boundingGrid.Height + 1;
|
||||
_pieceGrid.Columns = boundingGrid.Width + 1;
|
||||
for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++)
|
||||
@@ -275,18 +275,29 @@ public sealed class StorageContainer : BaseWindow
|
||||
|
||||
if (_entity.TryGetComponent<ItemComponent>(itemEnt, out var itemEntComponent))
|
||||
{
|
||||
var gridPiece = new ItemGridPiece((itemEnt, itemEntComponent), itemPos, _entity)
|
||||
ItemGridPiece gridPiece;
|
||||
|
||||
if (_storageController.CurrentlyDragging?.Entity is { } dragging
|
||||
&& dragging == itemEnt)
|
||||
{
|
||||
MinSize = size,
|
||||
Marked = Array.IndexOf(containedEntities, itemEnt) switch
|
||||
_storageController.CurrentlyDragging.Orphan();
|
||||
gridPiece = _storageController.CurrentlyDragging;
|
||||
}
|
||||
else
|
||||
{
|
||||
gridPiece = new ItemGridPiece((itemEnt, itemEntComponent), itemPos, _entity)
|
||||
{
|
||||
0 => ItemGridPieceMarks.First,
|
||||
1 => ItemGridPieceMarks.Second,
|
||||
_ => null,
|
||||
}
|
||||
};
|
||||
gridPiece.OnPiecePressed += OnPiecePressed;
|
||||
gridPiece.OnPieceUnpressed += OnPieceUnpressed;
|
||||
MinSize = size,
|
||||
Marked = Array.IndexOf(containedEntities, itemEnt) switch
|
||||
{
|
||||
0 => ItemGridPieceMarks.First,
|
||||
1 => ItemGridPieceMarks.Second,
|
||||
_ => null,
|
||||
}
|
||||
};
|
||||
gridPiece.OnPiecePressed += OnPiecePressed;
|
||||
gridPiece.OnPieceUnpressed += OnPieceUnpressed;
|
||||
}
|
||||
|
||||
control.AddChild(gridPiece);
|
||||
}
|
||||
|
||||
@@ -314,15 +314,16 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
_entity.GetNetEntity(storageEnt)));
|
||||
}
|
||||
|
||||
_menuDragHelper.EndDrag();
|
||||
_container?.BuildItemPieces();
|
||||
}
|
||||
else //if we just clicked, then take it out of the bag.
|
||||
{
|
||||
_menuDragHelper.EndDrag();
|
||||
_entity.RaisePredictiveEvent(new StorageInteractWithItemEvent(
|
||||
_entity.GetNetEntity(control.Entity),
|
||||
_entity.GetNetEntity(storageEnt)));
|
||||
}
|
||||
_menuDragHelper.EndDrag();
|
||||
args.Handle();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ using Robust.Client.State;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Weapons.Melee;
|
||||
|
||||
@@ -66,7 +64,7 @@ public sealed partial class MeleeWeaponSystem : SharedMeleeWeaponSystem
|
||||
if (!TryGetWeapon(entity, out var weaponUid, out var weapon))
|
||||
return;
|
||||
|
||||
if (!CombatMode.IsInCombatMode(entity) || !Blocker.CanAttack(entity))
|
||||
if (!CombatMode.IsInCombatMode(entity) || !Blocker.CanAttack(entity, weapon: (weaponUid, weapon)))
|
||||
{
|
||||
weapon.Attacking = false;
|
||||
return;
|
||||
|
||||
@@ -27,6 +27,9 @@ public sealed class IdCardSystem : SharedIdCardSystem
|
||||
|
||||
private void OnMicrowaved(EntityUid uid, IdCardComponent component, BeingMicrowavedEvent args)
|
||||
{
|
||||
if (!component.CanMicrowave)
|
||||
return;
|
||||
|
||||
if (TryComp<AccessComponent>(uid, out var access))
|
||||
{
|
||||
float randomPick = _random.NextFloat();
|
||||
|
||||
@@ -205,47 +205,30 @@ namespace Content.Server.Atmos.EntitySystems
|
||||
if (!flammable.OnFire && !otherFlammable.OnFire)
|
||||
return; // Neither are on fire
|
||||
|
||||
if (flammable.OnFire && otherFlammable.OnFire)
|
||||
// Both are on fire -> equalize fire stacks.
|
||||
// Weight each thing's firestacks by its mass
|
||||
var mass1 = 1f;
|
||||
var mass2 = 1f;
|
||||
if (_physicsQuery.TryComp(uid, out var physics) && _physicsQuery.TryComp(otherUid, out var otherPhys))
|
||||
{
|
||||
// Both are on fire -> equalize fire stacks.
|
||||
// Weight each thing's firestacks by its mass
|
||||
var mass1 = 1f;
|
||||
var mass2 = 1f;
|
||||
if (_physicsQuery.TryComp(uid, out var physics) && _physicsQuery.TryComp(otherUid, out var otherPhys))
|
||||
{
|
||||
mass1 = physics.Mass;
|
||||
mass2 = otherPhys.Mass;
|
||||
}
|
||||
|
||||
var total = mass1 + mass2;
|
||||
var avg = (flammable.FireStacks * mass1 + otherFlammable.FireStacks * mass2) / total;
|
||||
flammable.FireStacks = flammable.CanExtinguish ? avg : Math.Max(flammable.FireStacks, avg);
|
||||
otherFlammable.FireStacks = otherFlammable.CanExtinguish ? avg : Math.Max(otherFlammable.FireStacks, avg);
|
||||
UpdateAppearance(uid, flammable);
|
||||
UpdateAppearance(otherUid, otherFlammable);
|
||||
return;
|
||||
mass1 = physics.Mass;
|
||||
mass2 = otherPhys.Mass;
|
||||
}
|
||||
|
||||
// Only one is on fire -> attempt to spread the fire.
|
||||
var (srcUid, srcFlammable, destUid, destFlammable) = flammable.OnFire
|
||||
? (uid, flammable, otherUid, otherFlammable)
|
||||
: (otherUid, otherFlammable, uid, flammable);
|
||||
// when the thing on fire is more massive than the other, the following happens:
|
||||
// - the thing on fire loses a small number of firestacks
|
||||
// - the other thing gains a large number of firestacks
|
||||
// so a person on fire engulfs a mouse, but an engulfed mouse barely does anything to a person
|
||||
var total = mass1 + mass2;
|
||||
var avg = (flammable.FireStacks + otherFlammable.FireStacks) / total;
|
||||
|
||||
// if the thing on fire has less mass, spread less firestacks and vice versa
|
||||
var ratio = 0.5f;
|
||||
if (_physicsQuery.TryComp(srcUid, out var srcPhysics) && _physicsQuery.TryComp(destUid, out var destPhys))
|
||||
{
|
||||
ratio *= srcPhysics.Mass / destPhys.Mass;
|
||||
}
|
||||
|
||||
var lost = srcFlammable.FireStacks * ratio;
|
||||
destFlammable.FireStacks += lost;
|
||||
Ignite(destUid, srcUid, destFlammable);
|
||||
if (srcFlammable.CanExtinguish)
|
||||
{
|
||||
srcFlammable.FireStacks -= lost;
|
||||
UpdateAppearance(srcUid, srcFlammable);
|
||||
}
|
||||
// swap the entity losing stacks depending on whichever has the most firestack kilos
|
||||
var (src, dest) = flammable.FireStacks * mass1 > otherFlammable.FireStacks * mass2
|
||||
? (-1f, 1f)
|
||||
: (1f, -1f);
|
||||
// bring each entity to the same firestack mass, firestacks being scaled by the other's mass
|
||||
AdjustFireStacks(uid, src * avg * mass2, flammable, ignite: true);
|
||||
AdjustFireStacks(otherUid, dest * avg * mass1, otherFlammable, ignite: true);
|
||||
}
|
||||
|
||||
private void OnIsHot(EntityUid uid, FlammableComponent flammable, IsHotEvent args)
|
||||
@@ -283,17 +266,30 @@ namespace Content.Server.Atmos.EntitySystems
|
||||
_appearance.SetData(uid, ToggleableLightVisuals.Enabled, flammable.OnFire, appearance);
|
||||
}
|
||||
|
||||
public void AdjustFireStacks(EntityUid uid, float relativeFireStacks, FlammableComponent? flammable = null)
|
||||
public void AdjustFireStacks(EntityUid uid, float relativeFireStacks, FlammableComponent? flammable = null, bool ignite = false)
|
||||
{
|
||||
if (!Resolve(uid, ref flammable))
|
||||
return;
|
||||
|
||||
flammable.FireStacks = MathF.Min(MathF.Max(flammable.MinimumFireStacks, flammable.FireStacks + relativeFireStacks), flammable.MaximumFireStacks);
|
||||
SetFireStacks(uid, flammable.FireStacks + relativeFireStacks, flammable, ignite);
|
||||
}
|
||||
|
||||
if (flammable.OnFire && flammable.FireStacks <= 0)
|
||||
public void SetFireStacks(EntityUid uid, float stacks, FlammableComponent? flammable = null, bool ignite = false)
|
||||
{
|
||||
if (!Resolve(uid, ref flammable))
|
||||
return;
|
||||
|
||||
flammable.FireStacks = MathF.Min(MathF.Max(flammable.MinimumFireStacks, stacks), flammable.MaximumFireStacks);
|
||||
|
||||
if (flammable.FireStacks <= 0)
|
||||
{
|
||||
Extinguish(uid, flammable);
|
||||
}
|
||||
else
|
||||
{
|
||||
flammable.OnFire = ignite;
|
||||
UpdateAppearance(uid, flammable);
|
||||
}
|
||||
}
|
||||
|
||||
public void Extinguish(EntityUid uid, FlammableComponent? flammable = null)
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Rotting;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Rejuvenate;
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Timing;
|
||||
@@ -22,83 +16,16 @@ public sealed class RottingSystem : SharedRottingSystem
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PerishableComponent, MapInitEvent>(OnPerishableMapInit);
|
||||
SubscribeLocalEvent<PerishableComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
SubscribeLocalEvent<PerishableComponent, ExaminedEvent>(OnPerishableExamined);
|
||||
|
||||
SubscribeLocalEvent<RottingComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<RottingComponent, MobStateChangedEvent>(OnRottingMobStateChanged);
|
||||
SubscribeLocalEvent<RottingComponent, BeingGibbedEvent>(OnGibbed);
|
||||
SubscribeLocalEvent<RottingComponent, RejuvenateEvent>(OnRejuvenate);
|
||||
|
||||
SubscribeLocalEvent<TemperatureComponent, IsRottingEvent>(OnTempIsRotting);
|
||||
}
|
||||
|
||||
private void OnPerishableMapInit(EntityUid uid, PerishableComponent component, MapInitEvent args)
|
||||
{
|
||||
component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate;
|
||||
}
|
||||
|
||||
private void OnMobStateChanged(EntityUid uid, PerishableComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
if (args.NewMobState != MobState.Dead && args.OldMobState != MobState.Dead)
|
||||
return;
|
||||
|
||||
if (HasComp<RottingComponent>(uid))
|
||||
return;
|
||||
|
||||
component.RotAccumulator = TimeSpan.Zero;
|
||||
component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate;
|
||||
}
|
||||
|
||||
private void OnShutdown(EntityUid uid, RottingComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (TryComp<PerishableComponent>(uid, out var perishable))
|
||||
{
|
||||
perishable.RotNextUpdate = TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRottingMobStateChanged(EntityUid uid, RottingComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
if (args.NewMobState == MobState.Dead)
|
||||
return;
|
||||
RemCompDeferred(uid, component);
|
||||
}
|
||||
|
||||
public bool IsRotProgressing(EntityUid uid, PerishableComponent? perishable)
|
||||
{
|
||||
// things don't perish by default.
|
||||
if (!Resolve(uid, ref perishable, false))
|
||||
return false;
|
||||
|
||||
// only dead things or inanimate objects can rot
|
||||
if (TryComp<MobStateComponent>(uid, out var mobState) && !_mobState.IsDead(uid, mobState))
|
||||
return false;
|
||||
|
||||
if (_container.TryGetOuterContainer(uid, Transform(uid), out var container) &&
|
||||
HasComp<AntiRottingContainerComponent>(container.Owner))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var ev = new IsRottingEvent();
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
|
||||
return !ev.Handled;
|
||||
}
|
||||
|
||||
public bool IsRotten(EntityUid uid, RottingComponent? rotting = null)
|
||||
{
|
||||
return Resolve(uid, ref rotting, false);
|
||||
}
|
||||
|
||||
private void OnGibbed(EntityUid uid, RottingComponent component, BeingGibbedEvent args)
|
||||
{
|
||||
if (!TryComp<PhysicsComponent>(uid, out var physics))
|
||||
@@ -112,36 +39,6 @@ public sealed class RottingSystem : SharedRottingSystem
|
||||
tileMix?.AdjustMoles(Gas.Ammonia, molsToDump);
|
||||
}
|
||||
|
||||
private void OnPerishableExamined(Entity<PerishableComponent> perishable, ref ExaminedEvent args)
|
||||
{
|
||||
int stage = PerishStage(perishable, MaxStages);
|
||||
if (stage < 1 || stage > MaxStages)
|
||||
{
|
||||
// We dont push an examined string if it hasen't started "perishing" or it's already rotting
|
||||
return;
|
||||
}
|
||||
|
||||
var isMob = HasComp<MobStateComponent>(perishable);
|
||||
var description = "perishable-" + stage + (!isMob ? "-nonmob" : string.Empty);
|
||||
args.PushMarkup(Loc.GetString(description, ("target", Identity.Entity(perishable, EntityManager))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return an integer from 0 to maxStage representing how close to rotting an entity is. Used to
|
||||
/// generate examine messages for items that are starting to rot.
|
||||
/// </summary>
|
||||
public int PerishStage(Entity<PerishableComponent> perishable, int maxStages)
|
||||
{
|
||||
if (perishable.Comp.RotAfter.TotalSeconds == 0 || perishable.Comp.RotAccumulator.TotalSeconds == 0)
|
||||
return 0;
|
||||
return (int)(1 + maxStages * perishable.Comp.RotAccumulator.TotalSeconds / perishable.Comp.RotAfter.TotalSeconds);
|
||||
}
|
||||
|
||||
private void OnRejuvenate(EntityUid uid, RottingComponent component, RejuvenateEvent args)
|
||||
{
|
||||
RemCompDeferred<RottingComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnTempIsRotting(EntityUid uid, TemperatureComponent component, ref IsRottingEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
@@ -149,29 +46,6 @@ public sealed class RottingSystem : SharedRottingSystem
|
||||
args.Handled = component.CurrentTemperature < Atmospherics.T0C + 0.85f;
|
||||
}
|
||||
|
||||
|
||||
public void ReduceAccumulator(EntityUid uid, TimeSpan time)
|
||||
{
|
||||
if (!TryComp<PerishableComponent>(uid, out var perishable))
|
||||
return;
|
||||
|
||||
if (!TryComp<RottingComponent>(uid, out var rotting))
|
||||
{
|
||||
perishable.RotAccumulator -= time;
|
||||
return;
|
||||
}
|
||||
var total = (rotting.TotalRotTime + perishable.RotAccumulator) - time;
|
||||
|
||||
if (total < perishable.RotAfter)
|
||||
{
|
||||
RemCompDeferred(uid, rotting);
|
||||
perishable.RotAccumulator = total;
|
||||
}
|
||||
|
||||
else
|
||||
rotting.TotalRotTime = total - perishable.RotAfter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is anything speeding up the decay?
|
||||
/// e.g. buried in a grave
|
||||
|
||||
@@ -107,9 +107,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
quantity = sol.Volume;
|
||||
reagentColor = sol.GetColor(_prototypeManager);
|
||||
}
|
||||
var storedAmount = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", quantity));
|
||||
|
||||
inventory.Add(new ReagentInventoryItem(storageSlotId, reagentLabel, storedAmount, reagentColor));
|
||||
inventory.Add(new ReagentInventoryItem(storageSlotId, reagentLabel, quantity, reagentColor));
|
||||
}
|
||||
|
||||
return inventory;
|
||||
|
||||
@@ -27,7 +27,7 @@ public sealed class CriminalRecordsConsoleSystem : SharedCriminalRecordsConsoleS
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly RadioSystem _radio = default!;
|
||||
[Dependency] private readonly SharedIdCardSystem _idCard = default!;
|
||||
[Dependency] private readonly StationRecordsSystem _stationRecords = default!;
|
||||
[Dependency] private readonly StationRecordsSystem _records = default!;
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||
|
||||
@@ -80,7 +80,7 @@ public sealed class CriminalRecordsConsoleSystem : SharedCriminalRecordsConsoleS
|
||||
if (!CheckSelected(ent, msg.Actor, out var mob, out var key))
|
||||
return;
|
||||
|
||||
if (!_stationRecords.TryGetRecord<CriminalRecord>(key.Value, out var record) || record.Status == msg.Status)
|
||||
if (!_records.TryGetRecord<CriminalRecord>(key.Value, out var record) || record.Status == msg.Status)
|
||||
return;
|
||||
|
||||
// validate the reason
|
||||
@@ -106,7 +106,7 @@ public sealed class CriminalRecordsConsoleSystem : SharedCriminalRecordsConsoleS
|
||||
// will probably never fail given the checks above
|
||||
_criminalRecords.TryChangeStatus(key.Value, msg.Status, msg.Reason);
|
||||
|
||||
var name = RecordName(key.Value);
|
||||
var name = _records.RecordName(key.Value);
|
||||
var officer = Loc.GetString("criminal-records-console-unknown-officer");
|
||||
if (_idCard.TryFindIdCard(mob.Value, out var id) && id.Comp.FullName is { } fullName)
|
||||
officer = fullName;
|
||||
@@ -145,7 +145,6 @@ public sealed class CriminalRecordsConsoleSystem : SharedCriminalRecordsConsoleS
|
||||
ent.Comp.SecurityChannel, ent);
|
||||
|
||||
UpdateUserInterface(ent);
|
||||
UpdateCriminalIdentity(name, msg.Status);
|
||||
}
|
||||
|
||||
private void OnAddHistory(Entity<CriminalRecordsConsoleComponent> ent, ref CriminalRecordAddHistory msg)
|
||||
@@ -189,15 +188,15 @@ public sealed class CriminalRecordsConsoleSystem : SharedCriminalRecordsConsoleS
|
||||
return;
|
||||
}
|
||||
|
||||
var listing = _stationRecords.BuildListing((owningStation.Value, stationRecords), console.Filter);
|
||||
var listing = _records.BuildListing((owningStation.Value, stationRecords), console.Filter);
|
||||
|
||||
var state = new CriminalRecordsConsoleState(listing, console.Filter);
|
||||
if (console.ActiveKey is { } id)
|
||||
{
|
||||
// get records to display when a crewmember is selected
|
||||
var key = new StationRecordKey(id, owningStation.Value);
|
||||
_stationRecords.TryGetRecord(key, out state.StationRecord, stationRecords);
|
||||
_stationRecords.TryGetRecord(key, out state.CriminalRecord, stationRecords);
|
||||
_records.TryGetRecord(key, out state.StationRecord, stationRecords);
|
||||
_records.TryGetRecord(key, out state.CriminalRecord, stationRecords);
|
||||
state.SelectedKey = id;
|
||||
}
|
||||
|
||||
@@ -232,17 +231,6 @@ public sealed class CriminalRecordsConsoleSystem : SharedCriminalRecordsConsoleS
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name from a record, or empty string if this somehow fails.
|
||||
/// </summary>
|
||||
private string RecordName(StationRecordKey key)
|
||||
{
|
||||
if (!_stationRecords.TryGetRecord<GeneralStationRecord>(key, out var record))
|
||||
return "";
|
||||
|
||||
return record.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the new identity's name has a criminal record attached to it, and gives the entity the icon that
|
||||
/// belongs to the status if it does.
|
||||
@@ -255,14 +243,14 @@ public sealed class CriminalRecordsConsoleSystem : SharedCriminalRecordsConsoleS
|
||||
// TODO use the entity's station? Not the station of the map that it happens to currently be on?
|
||||
var station = _station.GetStationInMap(xform.MapID);
|
||||
|
||||
if (station != null && _stationRecords.GetRecordByName(station.Value, name) is { } id)
|
||||
if (station != null && _records.GetRecordByName(station.Value, name) is { } id)
|
||||
{
|
||||
if (_stationRecords.TryGetRecord<CriminalRecord>(new StationRecordKey(id, station.Value),
|
||||
if (_records.TryGetRecord<CriminalRecord>(new StationRecordKey(id, station.Value),
|
||||
out var record))
|
||||
{
|
||||
if (record.Status != SecurityStatus.None)
|
||||
{
|
||||
SetCriminalIcon(name, record.Status, uid);
|
||||
_criminalRecords.SetCriminalIcon(name, record.Status, uid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Content.Shared.CriminalRecords.Components;
|
||||
using Content.Shared.CriminalRecords.Systems;
|
||||
using Content.Shared.Dataset;
|
||||
using Content.Shared.Security;
|
||||
using Content.Shared.StationRecords;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
@@ -14,6 +15,7 @@ namespace Content.Server.CriminalRecords.Systems;
|
||||
public sealed class CriminalRecordsHackerSystem : SharedCriminalRecordsHackerSystem
|
||||
{
|
||||
[Dependency] private readonly ChatSystem _chat = default!;
|
||||
[Dependency] private readonly CriminalRecordsSystem _criminalRecords = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
@@ -38,8 +40,7 @@ public sealed class CriminalRecordsHackerSystem : SharedCriminalRecordsHackerSys
|
||||
foreach (var (key, record) in _records.GetRecordsOfType<CriminalRecord>(station))
|
||||
{
|
||||
var reason = _random.Pick(reasons.Values);
|
||||
record.Status = SecurityStatus.Wanted;
|
||||
record.Reason = reason;
|
||||
_criminalRecords.OverwriteStatus(new StationRecordKey(key, station), record, SecurityStatus.Wanted, reason);
|
||||
// no radio message since spam
|
||||
// no history since lazy and its easy to remove anyway
|
||||
// main damage with this is existing arrest warrants are lost and to anger beepsky
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.StationRecords.Systems;
|
||||
using Content.Shared.CriminalRecords;
|
||||
using Content.Shared.CriminalRecords.Systems;
|
||||
using Content.Shared.Security;
|
||||
using Content.Shared.StationRecords;
|
||||
using Content.Server.GameTicking;
|
||||
@@ -15,10 +16,10 @@ namespace Content.Server.CriminalRecords.Systems;
|
||||
/// - See security officers' actions in Criminal Records in the radio
|
||||
/// - See reasons for any action with no need to ask the officer personally
|
||||
/// </summary>
|
||||
public sealed class CriminalRecordsSystem : EntitySystem
|
||||
public sealed class CriminalRecordsSystem : SharedCriminalRecordsSystem
|
||||
{
|
||||
[Dependency] private readonly GameTicker _ticker = default!;
|
||||
[Dependency] private readonly StationRecordsSystem _stationRecords = default!;
|
||||
[Dependency] private readonly StationRecordsSystem _records = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -29,28 +30,40 @@ public sealed class CriminalRecordsSystem : EntitySystem
|
||||
|
||||
private void OnGeneralRecordCreated(AfterGeneralRecordCreatedEvent ev)
|
||||
{
|
||||
_stationRecords.AddRecordEntry(ev.Key, new CriminalRecord());
|
||||
_stationRecords.Synchronize(ev.Key);
|
||||
_records.AddRecordEntry(ev.Key, new CriminalRecord());
|
||||
_records.Synchronize(ev.Key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to change the status of the record found by the StationRecordKey.
|
||||
/// Reason should only be passed if status is Wanted.
|
||||
/// Reason should only be passed if status is Wanted, nullability isn't checked.
|
||||
/// </summary>
|
||||
/// <returns>True if the status is changed, false if not</returns>
|
||||
public bool TryChangeStatus(StationRecordKey key, SecurityStatus status, string? reason)
|
||||
{
|
||||
// don't do anything if its the same status
|
||||
if (!_stationRecords.TryGetRecord<CriminalRecord>(key, out var record)
|
||||
if (!_records.TryGetRecord<CriminalRecord>(key, out var record)
|
||||
|| status == record.Status)
|
||||
return false;
|
||||
|
||||
OverwriteStatus(key, record, status, reason);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the status without checking previous status or reason nullability.
|
||||
/// </summary>
|
||||
public void OverwriteStatus(StationRecordKey key, CriminalRecord record, SecurityStatus status, string? reason)
|
||||
{
|
||||
record.Status = status;
|
||||
record.Reason = reason;
|
||||
|
||||
_stationRecords.Synchronize(key);
|
||||
var name = _records.RecordName(key);
|
||||
if (name != string.Empty)
|
||||
UpdateCriminalIdentity(name, status);
|
||||
|
||||
return true;
|
||||
_records.Synchronize(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -59,7 +72,7 @@ public sealed class CriminalRecordsSystem : EntitySystem
|
||||
/// <returns>True if adding succeeded, false if not</returns>
|
||||
public bool TryAddHistory(StationRecordKey key, CrimeHistory entry)
|
||||
{
|
||||
if (!_stationRecords.TryGetRecord<CriminalRecord>(key, out var record))
|
||||
if (!_records.TryGetRecord<CriminalRecord>(key, out var record))
|
||||
return false;
|
||||
|
||||
record.History.Add(entry);
|
||||
@@ -81,7 +94,7 @@ public sealed class CriminalRecordsSystem : EntitySystem
|
||||
/// <returns>True if the line was removed, false if not</returns>
|
||||
public bool TryDeleteHistory(StationRecordKey key, uint index)
|
||||
{
|
||||
if (!_stationRecords.TryGetRecord<CriminalRecord>(key, out var record))
|
||||
if (!_records.TryGetRecord<CriminalRecord>(key, out var record))
|
||||
return false;
|
||||
|
||||
if (index >= record.History.Count)
|
||||
|
||||
@@ -36,7 +36,7 @@ public sealed class IgnitionSourceSystem : EntitySystem
|
||||
/// </summary>
|
||||
public void SetIgnited(Entity<IgnitionSourceComponent?> ent, bool ignited = true)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp))
|
||||
if (!Resolve(ent, ref ent.Comp, false))
|
||||
return;
|
||||
|
||||
ent.Comp.Ignited = ignited;
|
||||
|
||||
@@ -39,6 +39,7 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
|
||||
[Dependency] private readonly IConsoleHost _console = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IParallelManager _parallel = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
||||
@@ -119,6 +120,9 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
|
||||
SetSeed(uid, component, _random.Next());
|
||||
}
|
||||
|
||||
if (_proto.TryIndex(component.Template, out var biome))
|
||||
SetTemplate(uid, component, biome);
|
||||
|
||||
var xform = Transform(uid);
|
||||
var mapId = xform.MapID;
|
||||
|
||||
@@ -151,6 +155,15 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
|
||||
}
|
||||
}
|
||||
|
||||
public void SetEnabled(Entity<BiomeComponent?> ent, bool enabled = true)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp) || ent.Comp.Enabled == enabled)
|
||||
return;
|
||||
|
||||
ent.Comp.Enabled = enabled;
|
||||
Dirty(ent, ent.Comp);
|
||||
}
|
||||
|
||||
public void SetSeed(EntityUid uid, BiomeComponent component, int seed, bool dirty = true)
|
||||
{
|
||||
component.Seed = seed;
|
||||
|
||||
@@ -223,6 +223,17 @@ public sealed class StationRecordsSystem : SharedStationRecordsSystem
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the name for a record, or an empty string if it has no record.
|
||||
/// </summary>
|
||||
public string RecordName(StationRecordKey key)
|
||||
{
|
||||
if (!TryGetRecord<GeneralStationRecord>(key, out var record))
|
||||
return string.Empty;
|
||||
|
||||
return record.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all records of a specific type from a station.
|
||||
/// </summary>
|
||||
|
||||
@@ -496,7 +496,7 @@ namespace Content.Server.Strip
|
||||
|
||||
if (!_handsSystem.TryGetHand(target, handName, out var handSlot, target.Comp))
|
||||
{
|
||||
_popupSystem.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message", ("owner", target)), user);
|
||||
_popupSystem.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message", ("owner", Identity.Name(target, EntityManager, user))), user);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -511,7 +511,7 @@ namespace Content.Server.Strip
|
||||
|
||||
if (!_handsSystem.CanDropHeld(target, handSlot, false))
|
||||
{
|
||||
_popupSystem.PopupCursor(Loc.GetString("strippable-component-cannot-drop-message", ("owner", target)), user);
|
||||
_popupSystem.PopupCursor(Loc.GetString("strippable-component-cannot-drop-message", ("owner", Identity.Name(target, EntityManager, user))), user);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,4 +46,7 @@ public sealed partial class IdCardComponent : Component
|
||||
|
||||
[DataField]
|
||||
public LocId FullNameLocId = "access-id-card-component-owner-full-name-job-title-text";
|
||||
|
||||
[DataField]
|
||||
public bool CanMicrowave = true;
|
||||
}
|
||||
|
||||
@@ -1,29 +1,85 @@
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Rejuvenate;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Atmos.Rotting;
|
||||
|
||||
public abstract class SharedRottingSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
|
||||
public const int MaxStages = 3;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PerishableComponent, MapInitEvent>(OnPerishableMapInit);
|
||||
SubscribeLocalEvent<PerishableComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
SubscribeLocalEvent<PerishableComponent, ExaminedEvent>(OnPerishableExamined);
|
||||
|
||||
SubscribeLocalEvent<RottingComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<RottingComponent, MobStateChangedEvent>(OnRottingMobStateChanged);
|
||||
SubscribeLocalEvent<RottingComponent, RejuvenateEvent>(OnRejuvenate);
|
||||
SubscribeLocalEvent<RottingComponent, ExaminedEvent>(OnExamined);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the rot stage, usually from 0 to 2 inclusive.
|
||||
/// </summary>
|
||||
public int RotStage(EntityUid uid, RottingComponent? comp = null, PerishableComponent? perishable = null)
|
||||
private void OnPerishableMapInit(EntityUid uid, PerishableComponent component, MapInitEvent args)
|
||||
{
|
||||
if (!Resolve(uid, ref comp, ref perishable))
|
||||
return 0;
|
||||
component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate;
|
||||
}
|
||||
|
||||
return (int) (comp.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds);
|
||||
private void OnMobStateChanged(EntityUid uid, PerishableComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
if (args.NewMobState != MobState.Dead && args.OldMobState != MobState.Dead)
|
||||
return;
|
||||
|
||||
if (HasComp<RottingComponent>(uid))
|
||||
return;
|
||||
|
||||
component.RotAccumulator = TimeSpan.Zero;
|
||||
component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate;
|
||||
}
|
||||
|
||||
private void OnPerishableExamined(Entity<PerishableComponent> perishable, ref ExaminedEvent args)
|
||||
{
|
||||
int stage = PerishStage(perishable, MaxStages);
|
||||
if (stage < 1 || stage > MaxStages)
|
||||
{
|
||||
// We dont push an examined string if it hasen't started "perishing" or it's already rotting
|
||||
return;
|
||||
}
|
||||
|
||||
var isMob = HasComp<MobStateComponent>(perishable);
|
||||
var description = "perishable-" + stage + (!isMob ? "-nonmob" : string.Empty);
|
||||
args.PushMarkup(Loc.GetString(description, ("target", Identity.Entity(perishable, EntityManager))));
|
||||
}
|
||||
|
||||
private void OnShutdown(EntityUid uid, RottingComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (TryComp<PerishableComponent>(uid, out var perishable))
|
||||
{
|
||||
perishable.RotNextUpdate = TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRottingMobStateChanged(EntityUid uid, RottingComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
if (args.NewMobState == MobState.Dead)
|
||||
return;
|
||||
RemCompDeferred(uid, component);
|
||||
}
|
||||
|
||||
private void OnRejuvenate(EntityUid uid, RottingComponent component, RejuvenateEvent args)
|
||||
{
|
||||
RemCompDeferred<RottingComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnExamined(EntityUid uid, RottingComponent component, ExaminedEvent args)
|
||||
@@ -41,4 +97,75 @@ public abstract class SharedRottingSystem : EntitySystem
|
||||
|
||||
args.PushMarkup(Loc.GetString(description, ("target", Identity.Entity(uid, EntityManager))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return an integer from 0 to maxStage representing how close to rotting an entity is. Used to
|
||||
/// generate examine messages for items that are starting to rot.
|
||||
/// </summary>
|
||||
public int PerishStage(Entity<PerishableComponent> perishable, int maxStages)
|
||||
{
|
||||
if (perishable.Comp.RotAfter.TotalSeconds == 0 || perishable.Comp.RotAccumulator.TotalSeconds == 0)
|
||||
return 0;
|
||||
return (int)(1 + maxStages * perishable.Comp.RotAccumulator.TotalSeconds / perishable.Comp.RotAfter.TotalSeconds);
|
||||
}
|
||||
|
||||
public bool IsRotProgressing(EntityUid uid, PerishableComponent? perishable)
|
||||
{
|
||||
// things don't perish by default.
|
||||
if (!Resolve(uid, ref perishable, false))
|
||||
return false;
|
||||
|
||||
// only dead things or inanimate objects can rot
|
||||
if (TryComp<MobStateComponent>(uid, out var mobState) && !_mobState.IsDead(uid, mobState))
|
||||
return false;
|
||||
|
||||
if (_container.TryGetOuterContainer(uid, Transform(uid), out var container) &&
|
||||
HasComp<AntiRottingContainerComponent>(container.Owner))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var ev = new IsRottingEvent();
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
|
||||
return !ev.Handled;
|
||||
}
|
||||
|
||||
public bool IsRotten(EntityUid uid, RottingComponent? rotting = null)
|
||||
{
|
||||
return Resolve(uid, ref rotting, false);
|
||||
}
|
||||
|
||||
public void ReduceAccumulator(EntityUid uid, TimeSpan time)
|
||||
{
|
||||
if (!TryComp<PerishableComponent>(uid, out var perishable))
|
||||
return;
|
||||
|
||||
if (!TryComp<RottingComponent>(uid, out var rotting))
|
||||
{
|
||||
perishable.RotAccumulator -= time;
|
||||
return;
|
||||
}
|
||||
var total = (rotting.TotalRotTime + perishable.RotAccumulator) - time;
|
||||
|
||||
if (total < perishable.RotAfter)
|
||||
{
|
||||
RemCompDeferred(uid, rotting);
|
||||
perishable.RotAccumulator = total;
|
||||
}
|
||||
|
||||
else
|
||||
rotting.TotalRotTime = total - perishable.RotAfter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the rot stage, usually from 0 to 2 inclusive.
|
||||
/// </summary>
|
||||
public int RotStage(EntityUid uid, RottingComponent? comp = null, PerishableComponent? perishable = null)
|
||||
{
|
||||
if (!Resolve(uid, ref comp, ref perishable))
|
||||
return 0;
|
||||
|
||||
return (int) (comp.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,13 +573,13 @@ namespace Content.Shared.CCVar
|
||||
/// When a mob is walking should its X / Y movement be relative to its parent (true) or the map (false).
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> RelativeMovement =
|
||||
CVarDef.Create("physics.relative_movement", true, CVar.ARCHIVE | CVar.REPLICATED);
|
||||
CVarDef.Create("physics.relative_movement", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
public static readonly CVarDef<float> TileFrictionModifier =
|
||||
CVarDef.Create("physics.tile_friction", 40.0f, CVar.ARCHIVE | CVar.REPLICATED);
|
||||
CVarDef.Create("physics.tile_friction", 40.0f, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
public static readonly CVarDef<float> StopSpeed =
|
||||
CVarDef.Create("physics.stop_speed", 0.1f, CVar.ARCHIVE | CVar.REPLICATED);
|
||||
CVarDef.Create("physics.stop_speed", 0.1f, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
/// <summary>
|
||||
/// Whether mobs can push objects like lockers.
|
||||
@@ -588,7 +588,7 @@ namespace Content.Shared.CCVar
|
||||
/// Technically client doesn't need to know about it but this may prevent a bug in the distant future so it stays.
|
||||
/// </remarks>
|
||||
public static readonly CVarDef<bool> MobPushing =
|
||||
CVarDef.Create("physics.mob_pushing", false, CVar.REPLICATED);
|
||||
CVarDef.Create("physics.mob_pushing", false, CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
/*
|
||||
* Music
|
||||
@@ -1547,10 +1547,10 @@ namespace Content.Shared.CCVar
|
||||
CVarDef.Create("viewport.scale_render", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
public static readonly CVarDef<int> ViewportMinimumWidth =
|
||||
CVarDef.Create("viewport.minimum_width", 15, CVar.REPLICATED);
|
||||
CVarDef.Create("viewport.minimum_width", 15, CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
public static readonly CVarDef<int> ViewportMaximumWidth =
|
||||
CVarDef.Create("viewport.maximum_width", 21, CVar.REPLICATED);
|
||||
CVarDef.Create("viewport.maximum_width", 21, CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
public static readonly CVarDef<int> ViewportWidth =
|
||||
CVarDef.Create("viewport.width", 21, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
@@ -1655,7 +1655,7 @@ namespace Content.Shared.CCVar
|
||||
CVarDef.Create("chat.chat_sanitizer_enabled", true, CVar.SERVERONLY);
|
||||
|
||||
public static readonly CVarDef<bool> ChatShowTypingIndicator =
|
||||
CVarDef.Create("chat.show_typing_indicator", true, CVar.CLIENTONLY);
|
||||
CVarDef.Create("chat.show_typing_indicator", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER);
|
||||
|
||||
public static readonly CVarDef<bool> ChatEnableFancyBubbles =
|
||||
CVarDef.Create("chat.enable_fancy_bubbles", true, CVar.CLIENTONLY | CVar.ARCHIVE, "Toggles displaying fancy speech bubbles, which display the speaking character's name.");
|
||||
|
||||
@@ -152,10 +152,16 @@ public abstract class SharedChatSystem : EntitySystem
|
||||
if (string.IsNullOrEmpty(message))
|
||||
return message;
|
||||
// Capitalize first letter
|
||||
message = char.ToUpper(message[0]) + message.Remove(0, 1);
|
||||
message = OopsConcat(char.ToUpper(message[0]).ToString(), message.Remove(0, 1));
|
||||
return message;
|
||||
}
|
||||
|
||||
private static string OopsConcat(string a, string b)
|
||||
{
|
||||
// This exists to prevent Roslyn being clever and compiling something that fails sandbox checks.
|
||||
return a + b;
|
||||
}
|
||||
|
||||
public string SanitizeMessageCapitalizeTheWordI(string message, string theWordI = "i")
|
||||
{
|
||||
if (string.IsNullOrEmpty(message))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Chemistry
|
||||
@@ -93,11 +94,11 @@ namespace Content.Shared.Chemistry
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ReagentInventoryItem(string storageSlotId, string reagentLabel, string storedAmount, Color reagentColor)
|
||||
public sealed class ReagentInventoryItem(string storageSlotId, string reagentLabel, FixedPoint2 quantity, Color reagentColor)
|
||||
{
|
||||
public string StorageSlotId = storageSlotId;
|
||||
public string ReagentLabel = reagentLabel;
|
||||
public string StoredAmount = storedAmount;
|
||||
public FixedPoint2 Quantity = quantity;
|
||||
public Color ReagentColor = reagentColor;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,52 +1,6 @@
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.IdentityManagement.Components;
|
||||
using Content.Shared.Security;
|
||||
using Content.Shared.Security.Components;
|
||||
|
||||
namespace Content.Shared.CriminalRecords.Systems;
|
||||
|
||||
public abstract class SharedCriminalRecordsConsoleSystem : EntitySystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Any entity that has a the name of the record that was just changed as their visible name will get their icon
|
||||
/// updated with the new status, if the record got removed their icon will be removed too.
|
||||
/// </summary>
|
||||
public void UpdateCriminalIdentity(string name, SecurityStatus status)
|
||||
{
|
||||
var query = EntityQueryEnumerator<IdentityComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out var identity))
|
||||
{
|
||||
if (!Identity.Name(uid, EntityManager).Equals(name))
|
||||
continue;
|
||||
|
||||
if (status == SecurityStatus.None)
|
||||
RemComp<CriminalRecordComponent>(uid);
|
||||
else
|
||||
SetCriminalIcon(name, status, uid);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decides the icon that should be displayed on the entity based on the security status
|
||||
/// </summary>
|
||||
public void SetCriminalIcon(string name, SecurityStatus status, EntityUid characterUid)
|
||||
{
|
||||
EnsureComp<CriminalRecordComponent>(characterUid, out var record);
|
||||
|
||||
var previousIcon = record.StatusIcon;
|
||||
|
||||
record.StatusIcon = status switch
|
||||
{
|
||||
SecurityStatus.Paroled => "SecurityIconParoled",
|
||||
SecurityStatus.Wanted => "SecurityIconWanted",
|
||||
SecurityStatus.Detained => "SecurityIconIncarcerated",
|
||||
SecurityStatus.Discharged => "SecurityIconDischarged",
|
||||
SecurityStatus.Suspected => "SecurityIconSuspected",
|
||||
_ => record.StatusIcon
|
||||
};
|
||||
|
||||
if(previousIcon != record.StatusIcon)
|
||||
Dirty(characterUid, record);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Station records aren't predicted, just exists for access.
|
||||
/// </summary>
|
||||
public abstract class SharedCriminalRecordsConsoleSystem : EntitySystem;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.IdentityManagement.Components;
|
||||
using Content.Shared.Security;
|
||||
using Content.Shared.Security.Components;
|
||||
|
||||
namespace Content.Shared.CriminalRecords.Systems;
|
||||
|
||||
public abstract class SharedCriminalRecordsSystem : EntitySystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Any entity that has a the name of the record that was just changed as their visible name will get their icon
|
||||
/// updated with the new status, if the record got removed their icon will be removed too.
|
||||
/// </summary>
|
||||
public void UpdateCriminalIdentity(string name, SecurityStatus status)
|
||||
{
|
||||
var query = EntityQueryEnumerator<IdentityComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out var identity))
|
||||
{
|
||||
if (!Identity.Name(uid, EntityManager).Equals(name))
|
||||
continue;
|
||||
|
||||
if (status == SecurityStatus.None)
|
||||
RemComp<CriminalRecordComponent>(uid);
|
||||
else
|
||||
SetCriminalIcon(name, status, uid);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decides the icon that should be displayed on the entity based on the security status
|
||||
/// </summary>
|
||||
public void SetCriminalIcon(string name, SecurityStatus status, EntityUid characterUid)
|
||||
{
|
||||
EnsureComp<CriminalRecordComponent>(characterUid, out var record);
|
||||
|
||||
var previousIcon = record.StatusIcon;
|
||||
|
||||
record.StatusIcon = status switch
|
||||
{
|
||||
SecurityStatus.Paroled => "SecurityIconParoled",
|
||||
SecurityStatus.Wanted => "SecurityIconWanted",
|
||||
SecurityStatus.Detained => "SecurityIconIncarcerated",
|
||||
SecurityStatus.Discharged => "SecurityIconDischarged",
|
||||
SecurityStatus.Suspected => "SecurityIconSuspected",
|
||||
_ => record.StatusIcon
|
||||
};
|
||||
|
||||
if (previousIcon != record.StatusIcon)
|
||||
Dirty(characterUid, record);
|
||||
}
|
||||
}
|
||||
@@ -30,14 +30,13 @@ public sealed partial class BiomeComponent : Component
|
||||
public List<IBiomeLayer> Layers = new();
|
||||
|
||||
/// <summary>
|
||||
/// Templates to use for <see cref="Layers"/>. Optional as this can be set elsewhere.
|
||||
/// Templates to use for <see cref="Layers"/>.
|
||||
/// If this is set on mapinit, it will fill out layers automatically.
|
||||
/// If not set, use <c>BiomeSystem</c> to do it.
|
||||
/// Prototype reloading will also use this.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is really just here for prototype reload support.
|
||||
/// </remarks>
|
||||
[ViewVariables(VVAccess.ReadWrite),
|
||||
DataField("template", customTypeSerializer: typeof(PrototypeIdSerializer<BiomeTemplatePrototype>))]
|
||||
public string? Template;
|
||||
[DataField]
|
||||
public ProtoId<BiomeTemplatePrototype>? Template;
|
||||
|
||||
/// <summary>
|
||||
/// If we've already generated a tile and couldn't deload it then we won't ever reload it in future.
|
||||
|
||||
@@ -6,8 +6,13 @@ namespace Content.Shared.Weapons.Ranged.Components;
|
||||
/// <summary>
|
||||
/// Indicates that this gun requires wielding to be useable.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(WieldableSystem))]
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
[Access(typeof(WieldableSystem))]
|
||||
public sealed partial class GunRequiresWieldComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan LastPopup;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan PopupCooldown = TimeSpan.FromSeconds(1);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using Content.Shared.Weapons.Ranged.Components;
|
||||
|
||||
namespace Content.Shared.Weapons.Ranged.Events;
|
||||
|
||||
/// <summary>
|
||||
@@ -15,7 +17,7 @@ public record struct ShotAttemptedEvent
|
||||
/// <summary>
|
||||
/// The gun being shot.
|
||||
/// </summary>
|
||||
public EntityUid Used;
|
||||
public Entity<GunComponent> Used;
|
||||
|
||||
public bool Cancelled { get; private set; }
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ public abstract partial class SharedGunSystem : EntitySystem
|
||||
var prevention = new ShotAttemptedEvent
|
||||
{
|
||||
User = user,
|
||||
Used = gunUid
|
||||
Used = (gunUid, gun)
|
||||
};
|
||||
RaiseLocalEvent(gunUid, ref prevention);
|
||||
if (prevention.Cancelled)
|
||||
|
||||
@@ -16,7 +16,7 @@ using Content.Shared.Weapons.Ranged.Events;
|
||||
using Content.Shared.Weapons.Ranged.Systems;
|
||||
using Content.Shared.Wieldable.Components;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Wieldable;
|
||||
|
||||
@@ -30,6 +30,7 @@ public sealed class WieldableSystem : EntitySystem
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly UseDelaySystem _delay = default!;
|
||||
[Dependency] private readonly SharedGunSystem _gun = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -42,7 +43,7 @@ public sealed class WieldableSystem : EntitySystem
|
||||
SubscribeLocalEvent<WieldableComponent, GetVerbsEvent<InteractionVerb>>(AddToggleWieldVerb);
|
||||
|
||||
SubscribeLocalEvent<MeleeRequiresWieldComponent, AttemptMeleeEvent>(OnMeleeAttempt);
|
||||
SubscribeLocalEvent<GunRequiresWieldComponent, AttemptShootEvent>(OnShootAttempt);
|
||||
SubscribeLocalEvent<GunRequiresWieldComponent, ShotAttemptedEvent>(OnShootAttempt);
|
||||
SubscribeLocalEvent<GunWieldBonusComponent, ItemWieldedEvent>(OnGunWielded);
|
||||
SubscribeLocalEvent<GunWieldBonusComponent, ItemUnwieldedEvent>(OnGunUnwielded);
|
||||
SubscribeLocalEvent<GunWieldBonusComponent, GunRefreshModifiersEvent>(OnGunRefreshModifiers);
|
||||
@@ -61,16 +62,21 @@ public sealed class WieldableSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnShootAttempt(EntityUid uid, GunRequiresWieldComponent component, ref AttemptShootEvent args)
|
||||
private void OnShootAttempt(EntityUid uid, GunRequiresWieldComponent component, ref ShotAttemptedEvent args)
|
||||
{
|
||||
if (TryComp<WieldableComponent>(uid, out var wieldable) &&
|
||||
!wieldable.Wielded)
|
||||
{
|
||||
args.Cancelled = true;
|
||||
args.Cancel();
|
||||
|
||||
if (!HasComp<MeleeWeaponComponent>(uid) && !HasComp<MeleeRequiresWieldComponent>(uid))
|
||||
var time = _timing.CurTime;
|
||||
if (time > component.LastPopup + component.PopupCooldown &&
|
||||
!HasComp<MeleeWeaponComponent>(uid) &&
|
||||
!HasComp<MeleeRequiresWieldComponent>(uid))
|
||||
{
|
||||
args.Message = Loc.GetString("wieldable-component-requires", ("item", uid));
|
||||
component.LastPopup = time;
|
||||
var message = Loc.GetString("wieldable-component-requires", ("item", uid));
|
||||
_popupSystem.PopupClient(message, args.Used, args.User);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +1,4 @@
|
||||
Entries:
|
||||
- author: Brandon-Huu
|
||||
changes:
|
||||
- message: Removed the ability for command or any antag-safe role to be initial
|
||||
infected in zombie mode
|
||||
type: Remove
|
||||
id: 6090
|
||||
time: '2024-03-05T04:34:18.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/25785
|
||||
- author: Whisper
|
||||
changes:
|
||||
- message: Glass shards can be added to flatcaps to create bladed flatcaps!
|
||||
type: Add
|
||||
id: 6091
|
||||
time: '2024-03-05T20:57:55.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/25780
|
||||
- author: MACMAN2003
|
||||
changes:
|
||||
- message: Added clockwork structures and brass to build them with.
|
||||
type: Add
|
||||
id: 6092
|
||||
time: '2024-03-06T00:25:59.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/24673
|
||||
- author: deepdarkdepths
|
||||
changes:
|
||||
- message: Added the paramedic's cap to the uniform printer.
|
||||
type: Add
|
||||
id: 6093
|
||||
time: '2024-03-06T01:17:50.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/25861
|
||||
- author: lzk228
|
||||
changes:
|
||||
- message: Livestock crate and artifact container now can go under plastic flaps.
|
||||
type: Tweak
|
||||
id: 6094
|
||||
time: '2024-03-06T01:33:20.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/25862
|
||||
- author: PJB3005
|
||||
changes:
|
||||
- message: Saving paper is on ctrl+enter again. Also there's a visible "save" button
|
||||
now.
|
||||
type: Tweak
|
||||
id: 6095
|
||||
time: '2024-03-06T01:35:26.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/25870
|
||||
- author: ps3moira
|
||||
changes:
|
||||
- message: Changed brick, wood, and web walls to be unable to conjoin with different
|
||||
walls.
|
||||
type: Tweak
|
||||
id: 6096
|
||||
time: '2024-03-06T01:36:04.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/25674
|
||||
- author: Froffy
|
||||
changes:
|
||||
- message: Water can now be scooped from water tiles, such as planetary rivers.
|
||||
type: Add
|
||||
id: 6097
|
||||
time: '2024-03-06T01:37:24.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/25825
|
||||
- author: Ko4erga
|
||||
changes:
|
||||
- message: '"Post light" updated.'
|
||||
type: Tweak
|
||||
id: 6098
|
||||
time: '2024-03-06T01:39:47.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/25814
|
||||
- author: Ilya246
|
||||
changes:
|
||||
- message: Gas leak events are now 4 times as strong, and may leak water vapor.
|
||||
The fog is coming.
|
||||
type: Tweak
|
||||
id: 6099
|
||||
time: '2024-03-06T01:41:04.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/25864
|
||||
- author: Just_Art
|
||||
changes:
|
||||
- message: Added bob 5 hair!
|
||||
@@ -3870,3 +3796,75 @@
|
||||
id: 6589
|
||||
time: '2024-05-13T00:03:07.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/27962
|
||||
- author: lzk228
|
||||
changes:
|
||||
- message: Fixed color jumpskirts female mask.
|
||||
type: Fix
|
||||
id: 6590
|
||||
time: '2024-05-13T19:25:58.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/27984
|
||||
- author: aspiringLich
|
||||
changes:
|
||||
- message: Tweaked the Chemical, Booze, and Soda Dispenser UIs to aid readability.
|
||||
type: Tweak
|
||||
id: 6591
|
||||
time: '2024-05-13T21:46:17.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/27958
|
||||
- author: deltanedas
|
||||
changes:
|
||||
- message: Fixed fire spreading being insane.
|
||||
type: Fix
|
||||
id: 6592
|
||||
time: '2024-05-13T21:49:44.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/27986
|
||||
- author: DrSmugleaf
|
||||
changes:
|
||||
- message: Failing to fire a gun that requires wielding will no longer delay the
|
||||
next shot.
|
||||
type: Tweak
|
||||
id: 6593
|
||||
time: '2024-05-14T04:53:47.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/27973
|
||||
- author: lzk228
|
||||
changes:
|
||||
- message: Grill and hotplate can be anchored on the table.
|
||||
type: Fix
|
||||
id: 6594
|
||||
time: '2024-05-14T23:57:23.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/28026
|
||||
- author: ShadowCommander
|
||||
changes:
|
||||
- message: Fixed salvage magnet UI opening multiple times when activated.
|
||||
type: Fix
|
||||
id: 6595
|
||||
time: '2024-05-14T23:59:46.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/28010
|
||||
- author: Vermidia
|
||||
changes:
|
||||
- message: Shuttle roles get PDAs and headsets now
|
||||
type: Fix
|
||||
id: 6596
|
||||
time: '2024-05-15T10:30:54.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/28045
|
||||
- author: EdenTheLiznerd
|
||||
changes:
|
||||
- message: Removed the throngler from the grand lottery
|
||||
type: Tweak
|
||||
id: 6597
|
||||
time: '2024-05-15T21:02:58.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/28060
|
||||
- author: deltanedas
|
||||
changes:
|
||||
- message: Fixed ninja criminal records hack not changing sechud icons.
|
||||
type: Fix
|
||||
id: 6598
|
||||
time: '2024-05-16T20:51:06.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/28021
|
||||
- author: EmoGarbage404
|
||||
changes:
|
||||
- message: Fixed a bug that would cause items in your inventory to get stuck to
|
||||
your cursor.
|
||||
type: Fix
|
||||
id: 6599
|
||||
time: '2024-05-17T07:51:28.0000000+00:00'
|
||||
url: https://github.com/space-wizards/space-station-14/pull/27960
|
||||
|
||||
@@ -428,7 +428,7 @@ entities:
|
||||
- type: Physics
|
||||
canCollide: False
|
||||
- type: InsideEntityStorage
|
||||
- proto: ClothingHeadHelmetHardsuitBasic
|
||||
- proto: ClothingHeadHelmetEVALarge
|
||||
entities:
|
||||
- uid: 82
|
||||
components:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -110,9 +110,6 @@
|
||||
- id: WeaponRifleAk
|
||||
prob: 0.0001
|
||||
orGroup: Weapons
|
||||
- id: Throngler
|
||||
prob: 0.0001
|
||||
orGroup: Weapons
|
||||
- id: WeaponLauncherPirateCannon
|
||||
prob: 0.001
|
||||
orGroup: Weapons
|
||||
|
||||
@@ -133,6 +133,5 @@
|
||||
- "You can weld glass shards into glass sheets."
|
||||
- "By right clicking on a player, and then clicking the heart icon, you can quickly examine them to check for injuries or how badly they're bleeding. You can also do this to yourself."
|
||||
- "Monkeys and kobolds have a rare chance to be sentient. Ook!"
|
||||
- "Lottery crates can very rarely contain The Throngler."
|
||||
- "You can tell if an area with firelocks up is spaced by looking to see if the firelocks have lights beside them."
|
||||
- "Instead of picking it up, you can alt-click food to eat it. This also works for mice and other creatures without hands."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# White Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorWhite
|
||||
name: white jumpskirt
|
||||
description: A generic white jumpskirt with no rank markings.
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
# Grey Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorGrey
|
||||
name: grey jumpskirt
|
||||
description: A tasteful grey jumpskirt that reminds you of the good old days.
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
# Black Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorBlack
|
||||
name: black jumpskirt
|
||||
description: A generic black jumpskirt with no rank markings.
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
# Blue Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorBlue
|
||||
name: blue jumpskirt
|
||||
description: A generic blue jumpskirt with no rank markings.
|
||||
@@ -120,7 +120,7 @@
|
||||
|
||||
# Dark Blue Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorDarkBlue
|
||||
name: dark blue jumpskirt
|
||||
description: A generic dark blue jumpskirt with no rank markings.
|
||||
@@ -151,7 +151,7 @@
|
||||
|
||||
# Teal Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorTeal
|
||||
name: teal jumpskirt
|
||||
description: A generic teal jumpskirt with no rank markings.
|
||||
@@ -182,7 +182,7 @@
|
||||
|
||||
# Green Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorGreen
|
||||
name: green jumpskirt
|
||||
description: A generic green jumpskirt with no rank markings.
|
||||
@@ -213,7 +213,7 @@
|
||||
|
||||
# Dark Green Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorDarkGreen
|
||||
name: dark green jumpskirt
|
||||
description: A generic dark green jumpskirt with no rank markings.
|
||||
@@ -244,7 +244,7 @@
|
||||
|
||||
# Orange Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorOrange
|
||||
name: orange jumpskirt
|
||||
description: Don't wear this near paranoid security officers.
|
||||
@@ -275,7 +275,7 @@
|
||||
|
||||
# Pink Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorPink
|
||||
name: pink jumpskirt
|
||||
description: Just looking at this makes you feel <i>fabulous</i>.
|
||||
@@ -306,7 +306,7 @@
|
||||
|
||||
# Red Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorRed
|
||||
name: red jumpskirt
|
||||
description: A generic red jumpskirt with no rank markings.
|
||||
@@ -337,7 +337,7 @@
|
||||
|
||||
# Yellow Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorYellow
|
||||
name: yellow jumpskirt
|
||||
description: A generic yellow jumpskirt with no rank markings.
|
||||
@@ -368,7 +368,7 @@
|
||||
|
||||
# Purple Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorPurple
|
||||
name: purple jumpskirt
|
||||
description: A generic light purple jumpskirt with no rank markings.
|
||||
@@ -399,7 +399,7 @@
|
||||
|
||||
# Light Brown Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorLightBrown
|
||||
name: light brown jumpskirt
|
||||
description: A generic light brown jumpskirt with no rank markings.
|
||||
@@ -430,7 +430,7 @@
|
||||
|
||||
# Brown Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorBrown
|
||||
name: brown jumpskirt
|
||||
description: A generic brown jumpskirt with no rank markings.
|
||||
@@ -461,7 +461,7 @@
|
||||
|
||||
# Maroon Jumpskirt
|
||||
- type: entity
|
||||
parent: ClothingUniformBase
|
||||
parent: ClothingUniformSkirtBase
|
||||
id: ClothingUniformJumpskirtColorMaroon
|
||||
name: maroon jumpskirt
|
||||
description: A generic maroon jumpskirt with no rank markings.
|
||||
|
||||
@@ -629,7 +629,7 @@
|
||||
settings: short
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Loadout
|
||||
roleLoadout: [ JobCargoTechnician ]
|
||||
prototypes: [ LostCargoTechGearSuit, LostCargoTechGearCoat ]
|
||||
- type: RandomMetadata
|
||||
nameSegments:
|
||||
- names_first
|
||||
@@ -684,7 +684,7 @@
|
||||
settings: short
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Loadout
|
||||
roleLoadout: [ JobClown ]
|
||||
prototypes: [ ClownTroupe ]
|
||||
- type: RandomMetadata
|
||||
nameSegments:
|
||||
- names_clown
|
||||
@@ -742,7 +742,7 @@
|
||||
settings: short
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Loadout
|
||||
roleLoadout: [ JobChef ]
|
||||
prototypes: [ TravelingChef ]
|
||||
- type: RandomMetadata
|
||||
nameSegments:
|
||||
- names_first
|
||||
@@ -805,7 +805,7 @@
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Loadout
|
||||
roleLoadout: [ JobResearchDirector ]
|
||||
prototypes: [ DisasterVictimRD, DisasterVictimRDAlt ]
|
||||
- type: RandomMetadata
|
||||
nameSegments:
|
||||
- names_first
|
||||
@@ -823,7 +823,7 @@
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Loadout
|
||||
roleLoadout: [ JobChiefMedicalOfficer ]
|
||||
prototypes: [ DisasterVictimCMO, DisasterVictimCMOAlt ]
|
||||
- type: RandomMetadata
|
||||
nameSegments:
|
||||
- names_first
|
||||
@@ -841,7 +841,7 @@
|
||||
settings: default
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Loadout
|
||||
roleLoadout: [ JobCaptain ]
|
||||
prototypes: [ DisasterVictimCaptain, DisasterVictimCaptainAlt ]
|
||||
- type: RandomMetadata
|
||||
nameSegments:
|
||||
- names_first
|
||||
@@ -888,7 +888,7 @@
|
||||
settings: short
|
||||
- type: GhostTakeoverAvailable
|
||||
- type: Loadout
|
||||
prototypes: [ SyndicateOperativeGearCivilian ]
|
||||
prototypes: [ SyndicateOperativeGearDisasterVictim ]
|
||||
- type: RandomMetadata
|
||||
nameSegments:
|
||||
- names_first
|
||||
|
||||
@@ -553,7 +553,7 @@
|
||||
- type: Sprite
|
||||
state: medical
|
||||
- type: MachineBoard
|
||||
prototype: chem_master
|
||||
prototype: ChemMaster
|
||||
requirements:
|
||||
Capacitor: 1
|
||||
materialRequirements:
|
||||
|
||||
@@ -16,6 +16,17 @@
|
||||
- ItemMask
|
||||
restitution: 0.3 # fite me
|
||||
friction: 0.2
|
||||
- type: Damageable
|
||||
damageContainer: StructuralInorganic
|
||||
damageModifierSet: StrongMetallic # We only want explosions breaking them (for the most part)
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 75
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: [ "Destruction" ]
|
||||
- type: Tag
|
||||
tags:
|
||||
- Cartridge
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
- type: entity
|
||||
id: soda_dispenser
|
||||
name: soda dispenser
|
||||
suffix: Filled
|
||||
parent: ReagentDispenserBase
|
||||
id: SodaDispenser
|
||||
name: soda dispenser
|
||||
description: A beverage dispenser with a selection of soda and several other common beverages. Has a single fill slot for containers.
|
||||
suffix: Filled
|
||||
components:
|
||||
- type: Rotatable
|
||||
- type: Sprite
|
||||
@@ -24,9 +24,9 @@
|
||||
- Bartender
|
||||
|
||||
- type: entity
|
||||
parent: SodaDispenser
|
||||
id: SodaDispenserEmpty
|
||||
suffix: Empty
|
||||
parent: soda_dispenser
|
||||
components:
|
||||
- type: ReagentDispenser
|
||||
storageWhitelist:
|
||||
|
||||
@@ -51,10 +51,6 @@
|
||||
disposals: !type:Container
|
||||
- type: Physics
|
||||
bodyType: Static
|
||||
- type: Fixtures
|
||||
fixtures:
|
||||
fix1:
|
||||
hard: false
|
||||
- type: Construction
|
||||
graph: Toilet
|
||||
node: toilet
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
- type: entity
|
||||
id: chem_master
|
||||
id: ChemMaster
|
||||
parent: [ BaseMachinePowered, ConstructibleMachine ]
|
||||
name: ChemMaster 4000
|
||||
description: An industrial grade chemical manipulator with pill and bottle production included.
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
mask:
|
||||
- TabletopMachineMask
|
||||
layer:
|
||||
- Impassable
|
||||
- MidImpassable
|
||||
- LowImpassable
|
||||
- TabletopMachineLayer
|
||||
hard: false
|
||||
- type: ApcPowerReceiver
|
||||
powerLoad: 300
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
- TabletopMachineMask
|
||||
layer:
|
||||
- TabletopMachineLayer
|
||||
hard: false
|
||||
- type: Sprite
|
||||
sprite: Structures/Machines/microwave.rsi
|
||||
drawdepth: SmallObjects
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
- TabletopMachineMask
|
||||
layer:
|
||||
- TabletopMachineLayer
|
||||
hard: false
|
||||
- type: Sprite
|
||||
sprite: Structures/Machines/juicer.rsi
|
||||
drawdepth: SmallObjects
|
||||
|
||||
@@ -80,6 +80,18 @@
|
||||
shoes: ClothingShoesBootsCombat
|
||||
gloves: ClothingHandsGlovesColorBlack
|
||||
|
||||
# Syndicate Operative Outfit - Disaster Victim
|
||||
- type: startingGear
|
||||
id: SyndicateOperativeGearDisasterVictim
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitSyndieFormal
|
||||
back: ClothingBackpackDuffelSyndicate
|
||||
shoes: ClothingShoesBootsCombat
|
||||
gloves: ClothingHandsGlovesColorBlack
|
||||
id: SyndiPDA
|
||||
ears: ClothingHeadsetAltSyndicate
|
||||
|
||||
|
||||
#Syndicate Operative Outfit - Basic
|
||||
- type: startingGear
|
||||
id: SyndicateOperativeGearBasic
|
||||
@@ -318,6 +330,140 @@
|
||||
- type: startingGear
|
||||
id: BananaClown
|
||||
equipment:
|
||||
id: ClownPDA
|
||||
back: ClothingBackpackClown
|
||||
shoes: ClothingShoesClownBanana
|
||||
jumpsuit: ClothingUniformJumpsuitClownBanana
|
||||
mask: ClothingMaskClownBanana
|
||||
ears: ClothingHeadsetService
|
||||
pocket1: BikeHorn
|
||||
pocket2: ClownRecorder
|
||||
|
||||
#Clown Troupe
|
||||
- type: startingGear
|
||||
id: ClownTroupe
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitClown
|
||||
shoes: ClothingShoesClown
|
||||
id: ClownPDA
|
||||
back: ClothingBackpackClown
|
||||
ears: ClothingHeadsetService
|
||||
mask: ClothingMaskClown
|
||||
pocket1: BikeHorn
|
||||
pocket2: ClownRecorder
|
||||
|
||||
#Lost Cargo Tech
|
||||
- type: startingGear
|
||||
id: LostCargoTechGearSuit
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitCargo
|
||||
shoes: ClothingShoesColorBlack
|
||||
head: ClothingHeadHatCargosoft
|
||||
id: CargoPDA
|
||||
back: ClothingBackpackCargo
|
||||
ears: ClothingHeadsetCargo
|
||||
pocket1: AppraisalTool
|
||||
|
||||
- type: startingGear
|
||||
id: LostCargoTechGearCoat
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitCargo
|
||||
shoes: ClothingShoesBootsWinterCargo
|
||||
head: ClothingHeadHatCargosoft
|
||||
id: CargoPDA
|
||||
back: ClothingBackpackDuffelCargo
|
||||
ears: ClothingHeadsetCargo
|
||||
pocket1: AppraisalTool
|
||||
outerClothing: ClothingOuterWinterCargo
|
||||
|
||||
#Traveling Chef
|
||||
- type: startingGear
|
||||
id: TravelingChef
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitChef
|
||||
shoes: ClothingShoesColorWhite
|
||||
id: ChefPDA
|
||||
back: ClothingBackpackSatchel
|
||||
ears: ClothingHeadsetService
|
||||
belt: ClothingBeltChef
|
||||
|
||||
#CMO Disaster Victim
|
||||
- type: startingGear
|
||||
id: DisasterVictimCMO
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitCMO
|
||||
shoes: ClothingShoesColorBrown
|
||||
head: ClothingHeadMirror
|
||||
neck: ClothingCloakCmo
|
||||
id: CMOPDA
|
||||
back: ClothingBackpackMedical
|
||||
ears: ClothingHeadsetCMO
|
||||
belt: ClothingBeltMedical
|
||||
outerClothing: ClothingOuterCoatLabCmo
|
||||
|
||||
- type: startingGear
|
||||
id: DisasterVictimCMOAlt
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitCMOTurtle
|
||||
shoes: ClothingShoesColorBrown
|
||||
head: ClothingHeadHatBeretCmo
|
||||
neck: ClothingNeckMantleCMO
|
||||
id: CMOPDA
|
||||
back: ClothingBackpackSatchelMedical
|
||||
ears: ClothingHeadsetCMO
|
||||
belt: ClothingBeltMedical
|
||||
outerClothing: ClothingOuterCoatLabCmo
|
||||
|
||||
#Captain Disaster Victim
|
||||
- type: startingGear
|
||||
id: DisasterVictimCaptain
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitCaptain
|
||||
shoes: ClothingShoesBootsLaceup
|
||||
eyes: ClothingEyesGlassesSunglasses
|
||||
gloves: ClothingHandsGlovesCaptain
|
||||
head: ClothingHeadHatCaptain
|
||||
neck: ClothingNeckCloakCap
|
||||
id: CaptainPDA
|
||||
back: ClothingBackpackCaptain
|
||||
ears: ClothingHeadsetAltCommand
|
||||
outerClothing: ClothingOuterArmorCaptainCarapace
|
||||
|
||||
- type: startingGear
|
||||
id: DisasterVictimCaptainAlt
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitCapFormal
|
||||
shoes: ClothingShoesBootsLaceup
|
||||
eyes: ClothingEyesGlassesSunglasses
|
||||
gloves: ClothingHandsGlovesCaptain
|
||||
head: ClothingHeadHatCapcap
|
||||
neck: ClothingNeckMantleCap
|
||||
id: CaptainPDA
|
||||
back: ClothingBackpackSatchelCaptain
|
||||
ears: ClothingHeadsetAltCommand
|
||||
outerClothing: ClothingOuterArmorCaptainCarapace
|
||||
|
||||
#RD Disaster Victim
|
||||
- type: startingGear
|
||||
id: DisasterVictimRD
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitResearchDirector
|
||||
shoes: ClothingShoesColorBrown
|
||||
head: ClothingHeadHatBeretRND
|
||||
neck: ClothingNeckCloakRd
|
||||
id: RnDPDA
|
||||
back: ClothingBackpackScience
|
||||
ears: ClothingHeadsetRD
|
||||
outerClothing: ClothingOuterCoatRD
|
||||
|
||||
- type: startingGear
|
||||
id: DisasterVictimRDAlt
|
||||
equipment:
|
||||
jumpsuit: ClothingUniformJumpsuitResearchDirector
|
||||
shoes: ClothingShoesColorBrown
|
||||
head: ClothingHeadHatBeretRND
|
||||
neck: ClothingNeckMantleRD
|
||||
id: RnDPDA
|
||||
back: ClothingBackpackSatchelScience
|
||||
ears: ClothingHeadsetRD
|
||||
outerClothing: ClothingOuterCoatRD
|
||||
|
||||
@@ -10,7 +10,7 @@ While chemists primarily make medications, there's a very wide variety of chemic
|
||||
<GuideEntityEmbed Entity="ChemDispenser"/>
|
||||
<GuideEntityEmbed Entity="ChemBag"/>
|
||||
<GuideEntityEmbed Entity="KitchenReagentGrinder"/>
|
||||
<GuideEntityEmbed Entity="chem_master"/>
|
||||
<GuideEntityEmbed Entity="ChemMaster"/>
|
||||
</Box>
|
||||
<Box>
|
||||
<GuideEntityEmbed Entity="LargeBeaker"/>
|
||||
|
||||
@@ -17,6 +17,6 @@ Right now, medbay is divided into two different sets of care:
|
||||
<GuideEntityEmbed Entity="ChemDispenser"/>
|
||||
<GuideEntityEmbed Entity="LargeBeaker"/>
|
||||
<GuideEntityEmbed Entity="PillCanister"/>
|
||||
<GuideEntityEmbed Entity="chem_master"/>
|
||||
<GuideEntityEmbed Entity="ChemMaster"/>
|
||||
</Box>
|
||||
</Document>
|
||||
|
||||
@@ -7,7 +7,7 @@ The materials for these drinks can be found in various places:
|
||||
</Box>
|
||||
<Box>
|
||||
<GuideEntityEmbed Entity="BoozeDispenser"/>
|
||||
<GuideEntityEmbed Entity="soda_dispenser"/>
|
||||
<GuideEntityEmbed Entity="SodaDispenser"/>
|
||||
<GuideEntityEmbed Entity="VendingMachineBooze"/>
|
||||
</Box>
|
||||
|
||||
|
||||
@@ -348,3 +348,7 @@ ReinforcementRadioSyndicateMonkeyNukeops: ReinforcementRadioSyndicateAncestorNuk
|
||||
|
||||
# 2024-05-01
|
||||
DrinkBottleGoldschlager: DrinkBottleGildlager
|
||||
|
||||
# 2024-05-14
|
||||
soda_dispenser: SodaDispenser
|
||||
chem_master: ChemMaster
|
||||
|
||||
Submodule RobustToolbox updated: 970da5f717...ec794ce4e4
Reference in New Issue
Block a user