Compare commits
144 Commits
ed-2025-02
...
ed-07-03-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a463fe64d1 | ||
|
|
9cb1f806de | ||
|
|
d97d7f6fc4 | ||
|
|
228258e575 | ||
|
|
6aac9d6447 | ||
|
|
0b5712ce97 | ||
|
|
cea7d93d12 | ||
|
|
4a11cf9c53 | ||
|
|
19e9b3bc40 | ||
|
|
1ad686f42e | ||
|
|
06697abcdb | ||
|
|
1265355260 | ||
|
|
b1e985d0ad | ||
|
|
ce0ec78e8d | ||
|
|
e6a28307a4 | ||
|
|
c1acf81541 | ||
|
|
7b5283b35b | ||
|
|
45a6919994 | ||
|
|
0d23f79eb6 | ||
|
|
35e6bae5fe | ||
|
|
44f4c17266 | ||
|
|
e54e8a95ee | ||
|
|
d9a5869504 | ||
|
|
f9ff91d74b | ||
|
|
b7b52e664d | ||
|
|
b202897c36 | ||
|
|
acc9886242 | ||
|
|
2855cc906b | ||
|
|
81b9cdfff7 | ||
|
|
3fb7cc0cd7 | ||
|
|
a0b190fd97 | ||
|
|
719ee50c96 | ||
|
|
c7c2e7265b | ||
|
|
bef78c62c0 | ||
|
|
bab794e68f | ||
|
|
3d9ce10f58 | ||
|
|
9ea547d8be | ||
|
|
4dfd3e5740 | ||
|
|
7bf09bfdb5 | ||
|
|
08cb26dbf0 | ||
|
|
a16dd2fd3e | ||
|
|
98cca7b0f8 | ||
|
|
cec05d697e | ||
|
|
3c20f63292 | ||
|
|
439e1c6dc0 | ||
|
|
41c51e2905 | ||
|
|
5fdf702e3c | ||
|
|
c7b9a76342 | ||
|
|
19c23682b0 | ||
|
|
2db57f11ac | ||
|
|
3f014d2b77 | ||
|
|
7520d8a2c8 | ||
|
|
4d0e63caeb | ||
|
|
f80f305d1d | ||
|
|
e705d04a12 | ||
|
|
a5aab8b8a1 | ||
|
|
0c6081fe10 | ||
|
|
3127f73c48 | ||
|
|
53dc27cb1e | ||
|
|
c20fb21ac1 | ||
|
|
7b0b401312 | ||
|
|
9a12bfd4e8 | ||
|
|
1c62e335b9 | ||
|
|
7351a9d1bd | ||
|
|
f850b69e89 | ||
|
|
16c377a05b | ||
|
|
9d62e8c0e7 | ||
|
|
3557be1cff | ||
|
|
7bd98b9075 | ||
|
|
6c3dbbccfe | ||
|
|
c698b163b6 | ||
|
|
8f164cffe4 | ||
|
|
058d9fec09 | ||
|
|
7c6028bc80 | ||
|
|
7283f9b6dc | ||
|
|
e86770f5a0 | ||
|
|
08a274dc28 | ||
|
|
68de58eb66 | ||
|
|
6ea742d4b4 | ||
|
|
11dd26e08e | ||
|
|
6e269c65d8 | ||
|
|
f65ff0bd37 | ||
|
|
d949feeacf | ||
|
|
9615bc64f8 | ||
|
|
9f4a4b81ac | ||
|
|
f165223a5e | ||
|
|
ab9c78b066 | ||
|
|
92006deede | ||
|
|
263f915671 | ||
|
|
183ea1043b | ||
|
|
7ddad07118 | ||
|
|
594811a686 | ||
|
|
afe83e1231 | ||
|
|
8265fb215b | ||
|
|
7f67ff4b26 | ||
|
|
e761ab5815 | ||
|
|
920df98f76 | ||
|
|
1e435822c7 | ||
|
|
309d21bb4c | ||
|
|
285decd734 | ||
|
|
5eeba30211 | ||
|
|
237df1c9a1 | ||
|
|
02f5015830 | ||
|
|
52df2dbe15 | ||
|
|
1a76e4fd52 | ||
|
|
2958706e04 | ||
|
|
004e54af51 | ||
|
|
ebc1bff4cb | ||
|
|
c899ae7649 | ||
|
|
08bc8436a5 | ||
|
|
4d72a2d5f3 | ||
|
|
16787a0281 | ||
|
|
e22c3b1eeb | ||
|
|
5fbe217db3 | ||
|
|
059c64a75f | ||
|
|
363eec1465 | ||
|
|
d1415d9dcb | ||
|
|
7fc8dcb811 | ||
|
|
670791ac49 | ||
|
|
51104a7316 | ||
|
|
bb110b376e | ||
|
|
02f0190c35 | ||
|
|
45e7891706 | ||
|
|
22398ea342 | ||
|
|
0148c441e6 | ||
|
|
615d548021 | ||
|
|
969e7bdd39 | ||
|
|
c71e6e67aa | ||
|
|
88308356db | ||
|
|
c3784a3005 | ||
|
|
f4fab85e34 | ||
|
|
6fa4767b4c | ||
|
|
ac9c8b8275 | ||
|
|
5385683b7e | ||
|
|
05de5bd3eb | ||
|
|
6f925dd610 | ||
|
|
0d84d25067 | ||
|
|
b7c86cae71 | ||
|
|
fa73217b52 | ||
|
|
91f2c46f56 | ||
|
|
1404095f27 | ||
|
|
9fb5517afa | ||
|
|
fe69de942f | ||
|
|
5794ecd28f |
@@ -85,7 +85,7 @@ internal sealed class AdminNameOverlay : Overlay
|
||||
{
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + (lineoffset * 2), _antagLabelClassic, uiScale, _antagColorClassic);
|
||||
}
|
||||
else if (!classic && _filter.Contains(playerInfo.RoleProto.ID))
|
||||
else if (!classic && _filter.Contains(playerInfo.RoleProto))
|
||||
{
|
||||
var label = Loc.GetString(playerInfo.RoleProto.Name).ToUpper();
|
||||
var color = playerInfo.RoleProto.Color;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Client.UserInterface.Fragments;
|
||||
using Content.Shared.CartridgeLoader;
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
@@ -13,16 +14,23 @@ public sealed partial class LogProbeUi : UIFragment
|
||||
return _fragment!;
|
||||
}
|
||||
|
||||
public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner)
|
||||
public override void Setup(BoundUserInterface ui, EntityUid? fragmentOwner)
|
||||
{
|
||||
_fragment = new LogProbeUiFragment();
|
||||
|
||||
_fragment.OnPrintPressed += () =>
|
||||
{
|
||||
var ev = new LogProbePrintMessage();
|
||||
var message = new CartridgeUiMessage(ev);
|
||||
ui.SendMessage(message);
|
||||
};
|
||||
}
|
||||
|
||||
public override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
if (state is not LogProbeUiState logProbeUiState)
|
||||
if (state is not LogProbeUiState cast)
|
||||
return;
|
||||
|
||||
_fragment?.UpdateState(logProbeUiState.PulledLogs);
|
||||
_fragment?.UpdateState(cast.EntityName, cast.PulledLogs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,4 +18,9 @@
|
||||
<ScrollContainer VerticalExpand="True" HScrollEnabled="True">
|
||||
<BoxContainer Orientation="Vertical" Name="ProbedDeviceContainer"/>
|
||||
</ScrollContainer>
|
||||
<BoxContainer Orientation="Horizontal" Margin="4 8">
|
||||
<Button Name="PrintButton" HorizontalAlignment="Left" Text="{Loc 'log-probe-print-button'}" Disabled="True"/>
|
||||
<BoxContainer HorizontalExpand="True"/>
|
||||
<Label Name="EntityName" Align="Right"/>
|
||||
</BoxContainer>
|
||||
</cartridges:LogProbeUiFragment>
|
||||
|
||||
@@ -8,17 +8,24 @@ namespace Content.Client.CartridgeLoader.Cartridges;
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class LogProbeUiFragment : BoxContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Action invoked when the print button gets pressed.
|
||||
/// </summary>
|
||||
public Action? OnPrintPressed;
|
||||
|
||||
public LogProbeUiFragment()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
PrintButton.OnPressed += _ => OnPrintPressed?.Invoke();
|
||||
}
|
||||
|
||||
public void UpdateState(List<PulledAccessLog> logs)
|
||||
public void UpdateState(string name, List<PulledAccessLog> logs)
|
||||
{
|
||||
ProbedDeviceContainer.RemoveAllChildren();
|
||||
EntityName.Text = name;
|
||||
PrintButton.Disabled = string.IsNullOrEmpty(name);
|
||||
|
||||
//Reverse the list so the oldest entries appear at the bottom
|
||||
logs.Reverse();
|
||||
ProbedDeviceContainer.RemoveAllChildren();
|
||||
|
||||
var count = 1;
|
||||
foreach (var log in logs)
|
||||
|
||||
@@ -217,7 +217,7 @@ namespace Content.Client.Chat.UI
|
||||
{
|
||||
StyleClasses = { "speechBox", speechStyleClass },
|
||||
Children = { label },
|
||||
ModulateSelfOverride = Color.White.WithAlpha(0.75f)
|
||||
ModulateSelfOverride = Color.White.WithAlpha(ConfigManager.GetCVar(CCVars.SpeechBubbleBackgroundOpacity))
|
||||
};
|
||||
|
||||
return panel;
|
||||
@@ -247,21 +247,23 @@ namespace Content.Client.Chat.UI
|
||||
{
|
||||
StyleClasses = { "speechBox", speechStyleClass },
|
||||
Children = { label },
|
||||
ModulateSelfOverride = Color.White.WithAlpha(0.75f)
|
||||
ModulateSelfOverride = Color.White.WithAlpha(ConfigManager.GetCVar(CCVars.SpeechBubbleBackgroundOpacity)),
|
||||
};
|
||||
return unfanciedPanel;
|
||||
}
|
||||
|
||||
var bubbleHeader = new RichTextLabel
|
||||
{
|
||||
Margin = new Thickness(1, 1, 1, 1)
|
||||
ModulateSelfOverride = Color.White.WithAlpha(ConfigManager.GetCVar(CCVars.SpeechBubbleSpeakerOpacity)),
|
||||
Margin = new Thickness(1, 1, 1, 1),
|
||||
};
|
||||
|
||||
var bubbleContent = new RichTextLabel
|
||||
{
|
||||
ModulateSelfOverride = Color.White.WithAlpha(ConfigManager.GetCVar(CCVars.SpeechBubbleTextOpacity)),
|
||||
MaxWidth = SpeechMaxWidth,
|
||||
Margin = new Thickness(2, 6, 2, 2),
|
||||
StyleClasses = { "bubbleContent" }
|
||||
StyleClasses = { "bubbleContent" },
|
||||
};
|
||||
|
||||
//We'll be honest. *Yes* this is hacky. Doing this in a cleaner way would require a bottom-up refactor of how saycode handles sending chat messages. -Myr
|
||||
@@ -273,7 +275,7 @@ namespace Content.Client.Chat.UI
|
||||
{
|
||||
StyleClasses = { "speechBox", speechStyleClass },
|
||||
Children = { bubbleContent },
|
||||
ModulateSelfOverride = Color.White.WithAlpha(0.75f),
|
||||
ModulateSelfOverride = Color.White.WithAlpha(ConfigManager.GetCVar(CCVars.SpeechBubbleBackgroundOpacity)),
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
VerticalAlignment = VAlignment.Bottom,
|
||||
Margin = new Thickness(4, 14, 4, 2)
|
||||
@@ -283,7 +285,7 @@ namespace Content.Client.Chat.UI
|
||||
{
|
||||
StyleClasses = { "speechBox", speechStyleClass },
|
||||
Children = { bubbleHeader },
|
||||
ModulateSelfOverride = Color.White.WithAlpha(ConfigManager.GetCVar(CCVars.ChatFancyNameBackground) ? 0.75f : 0f),
|
||||
ModulateSelfOverride = Color.White.WithAlpha(ConfigManager.GetCVar(CCVars.ChatFancyNameBackground) ? ConfigManager.GetCVar(CCVars.SpeechBubbleBackgroundOpacity) : 0f),
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
VerticalAlignment = VAlignment.Top
|
||||
};
|
||||
|
||||
@@ -94,7 +94,7 @@ public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
|
||||
if (entProto.Abstract || usedNames.Contains(entProto.Name))
|
||||
continue;
|
||||
|
||||
if (!entProto.TryGetComponent<ExtractableComponent>(out var extractableComponent))
|
||||
if (!entProto.TryGetComponent<ExtractableComponent>(out var extractableComponent, EntityManager.ComponentFactory))
|
||||
continue;
|
||||
|
||||
//these bloat the hell out of blood/fat
|
||||
@@ -121,7 +121,7 @@ public sealed class ChemistryGuideDataSystem : SharedChemistryGuideDataSystem
|
||||
|
||||
|
||||
if (extractableComponent.GrindableSolution is { } grindableSolutionId &&
|
||||
entProto.TryGetComponent<SolutionContainerManagerComponent>(out var manager) &&
|
||||
entProto.TryGetComponent<SolutionContainerManagerComponent>(out var manager, EntityManager.ComponentFactory) &&
|
||||
_solutionContainer.TryGetSolution(manager, grindableSolutionId, out var grindableSolution))
|
||||
{
|
||||
var data = new ReagentEntitySourceData(
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace Content.Client.Chemistry.UI
|
||||
_window.CreateBottleButton.OnPressed += _ => SendMessage(
|
||||
new ChemMasterOutputToBottleMessage(
|
||||
(uint) _window.BottleDosage.Value, _window.LabelLine));
|
||||
_window.BufferSortButton.OnPressed += _ => SendMessage(
|
||||
new ChemMasterSortingTypeCycleMessage());
|
||||
|
||||
for (uint i = 0; i < _window.PillTypeButtons.Length; i++)
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
<Label Text="{Loc 'chem-master-window-buffer-text'}" />
|
||||
<Control HorizontalExpand="True" />
|
||||
<Button MinSize="80 0" Name="BufferTransferButton" Access="Public" Text="{Loc 'chem-master-window-transfer-button'}" ToggleMode="True" StyleClasses="OpenRight" />
|
||||
<Button MinSize="80 0" Name="BufferSortButton" Access="Public" Text="{Loc 'chem-master-window-sort-type-none'}" StyleClasses="OpenBoth" />
|
||||
<Button MinSize="80 0" Name="BufferDiscardButton" Access="Public" Text="{Loc 'chem-master-window-discard-button'}" ToggleMode="True" StyleClasses="OpenLeft" />
|
||||
</BoxContainer>
|
||||
|
||||
|
||||
@@ -140,17 +140,17 @@ namespace Content.Client.Chemistry.UI
|
||||
|
||||
// Ensure the Panel Info is updated, including UI elements for Buffer Volume, Output Container and so on
|
||||
UpdatePanelInfo(castState);
|
||||
|
||||
|
||||
BufferCurrentVolume.Text = $" {castState.BufferCurrentVolume?.Int() ?? 0}u";
|
||||
|
||||
|
||||
InputEjectButton.Disabled = castState.InputContainerInfo is null;
|
||||
OutputEjectButton.Disabled = castState.OutputContainerInfo is null;
|
||||
CreateBottleButton.Disabled = castState.OutputContainerInfo?.Reagents == null;
|
||||
CreatePillButton.Disabled = castState.OutputContainerInfo?.Entities == null;
|
||||
|
||||
|
||||
UpdateDosageFields(castState);
|
||||
}
|
||||
|
||||
|
||||
//assign default values for pill and bottle fields.
|
||||
private void UpdateDosageFields(ChemMasterBoundUserInterfaceState castState)
|
||||
{
|
||||
@@ -162,8 +162,9 @@ namespace Content.Client.Chemistry.UI
|
||||
var bufferVolume = castState.BufferCurrentVolume?.Int() ?? 0;
|
||||
|
||||
PillDosage.Value = (int)Math.Min(bufferVolume, castState.PillDosageLimit);
|
||||
|
||||
|
||||
PillTypeButtons[castState.SelectedPillType].Pressed = true;
|
||||
|
||||
PillNumber.IsValid = x => x >= 0 && x <= pillNumberMax;
|
||||
PillDosage.IsValid = x => x > 0 && x <= castState.PillDosageLimit;
|
||||
BottleDosage.IsValid = x => x >= 0 && x <= bottleAmountMax;
|
||||
@@ -213,6 +214,17 @@ namespace Content.Client.Chemistry.UI
|
||||
|
||||
BufferInfo.Children.Clear();
|
||||
|
||||
// This has to happen here due to people possibly
|
||||
// setting sorting before putting any chemicals
|
||||
BufferSortButton.Text = state.SortingType switch
|
||||
{
|
||||
ChemMasterSortingType.Alphabetical => Loc.GetString("chem-master-window-sort-type-alphabetical"),
|
||||
ChemMasterSortingType.Quantity => Loc.GetString("chem-master-window-sort-type-quantity"),
|
||||
ChemMasterSortingType.Latest => Loc.GetString("chem-master-window-sort-type-latest"),
|
||||
_ => Loc.GetString("chem-master-window-sort-type-none")
|
||||
};
|
||||
|
||||
|
||||
if (!state.BufferReagents.Any())
|
||||
{
|
||||
BufferInfo.Children.Add(new Label { Text = Loc.GetString("chem-master-window-buffer-empty-text") });
|
||||
@@ -235,19 +247,48 @@ namespace Content.Client.Chemistry.UI
|
||||
};
|
||||
bufferHBox.AddChild(bufferVol);
|
||||
|
||||
// initialises rowCount to allow for striped rows
|
||||
|
||||
var rowCount = 0;
|
||||
// This sets up the needed data for sorting later in a list
|
||||
// Its done this way to not repeat having to use same code twice (once for sorting
|
||||
// and once for displaying)
|
||||
var reagentList = new List<(ReagentId reagentId, string name, Color color, FixedPoint2 quantity)>();
|
||||
foreach (var (reagent, quantity) in state.BufferReagents)
|
||||
{
|
||||
var reagentId = reagent;
|
||||
_prototypeManager.TryIndex(reagentId.Prototype, out ReagentPrototype? proto);
|
||||
var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
|
||||
var reagentColor = proto?.SubstanceColor ?? default(Color);
|
||||
BufferInfo.Children.Add(BuildReagentRow(reagentColor, rowCount++, name, reagentId, quantity, true, true));
|
||||
reagentList.Add(new (reagentId, name, reagentColor, quantity));
|
||||
}
|
||||
|
||||
// We sort here since we need sorted list to be filled first.
|
||||
// You can easily add any new params you need to it.
|
||||
switch (state.SortingType)
|
||||
{
|
||||
case ChemMasterSortingType.Alphabetical:
|
||||
reagentList = reagentList.OrderBy(x => x.name).ToList();
|
||||
break;
|
||||
|
||||
case ChemMasterSortingType.Quantity:
|
||||
reagentList = reagentList.OrderByDescending(x => x.quantity).ToList();
|
||||
break;
|
||||
case ChemMasterSortingType.Latest:
|
||||
reagentList = Enumerable.Reverse(reagentList).ToList();
|
||||
break;
|
||||
|
||||
case ChemMasterSortingType.None:
|
||||
default:
|
||||
// This case is pointless but it is there for readability
|
||||
break;
|
||||
}
|
||||
|
||||
// initialises rowCount to allow for striped rows
|
||||
var rowCount = 0;
|
||||
foreach (var reagent in reagentList)
|
||||
{
|
||||
BufferInfo.Children.Add(BuildReagentRow(reagent.color, rowCount++, reagent.name, reagent.reagentId, reagent.quantity, true, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void BuildContainerUI(Control control, ContainerInfo? info, bool addReagentButtons)
|
||||
{
|
||||
control.Children.Clear();
|
||||
@@ -295,7 +336,7 @@ namespace Content.Client.Chemistry.UI
|
||||
_prototypeManager.TryIndex(reagent.Reagent.Prototype, out ReagentPrototype? proto);
|
||||
var name = proto?.LocalizedName ?? Loc.GetString("chem-master-window-unknown-reagent-text");
|
||||
var reagentColor = proto?.SubstanceColor ?? default(Color);
|
||||
|
||||
|
||||
control.Children.Add(BuildReagentRow(reagentColor, rowCount++, name, reagent.Reagent, reagent.Quantity, false, addReagentButtons));
|
||||
}
|
||||
}
|
||||
@@ -315,7 +356,7 @@ namespace Content.Client.Chemistry.UI
|
||||
}
|
||||
//this calls the separated button builder, and stores the return to render after labels
|
||||
var reagentButtonConstructors = CreateReagentTransferButtons(reagent, isBuffer, addReagentButtons);
|
||||
|
||||
|
||||
// Create the row layout with the color panel
|
||||
var rowContainer = new BoxContainer
|
||||
{
|
||||
@@ -358,7 +399,7 @@ namespace Content.Client.Chemistry.UI
|
||||
Children = { rowContainer }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public string LabelLine
|
||||
{
|
||||
get => LabelLineEdit.Text;
|
||||
|
||||
@@ -27,7 +27,7 @@ public sealed class FlatpackSystem : SharedFlatpackSystem
|
||||
if (!PrototypeManager.TryIndex<EntityPrototype>(machineBoardId, out var machineBoardPrototype))
|
||||
return;
|
||||
|
||||
if (!machineBoardPrototype.TryGetComponent<SpriteComponent>(out var sprite))
|
||||
if (!machineBoardPrototype.TryGetComponent<SpriteComponent>(out var sprite, EntityManager.ComponentFactory))
|
||||
return;
|
||||
|
||||
Color? color = null;
|
||||
|
||||
@@ -59,13 +59,13 @@ namespace Content.Client.Gameplay
|
||||
|
||||
// Version number watermark.
|
||||
_version = new Label();
|
||||
_version.FontColorOverride = Color.FromHex("#FFFFFF20");
|
||||
_version.Text = _changelog.GetClientVersion();
|
||||
_version.Visible = VersionVisible();
|
||||
UserInterfaceManager.PopupRoot.AddChild(_version);
|
||||
_configurationManager.OnValueChanged(CCVars.HudVersionWatermark, (show) => { _version.Visible = VersionVisible(); });
|
||||
_configurationManager.OnValueChanged(CCVars.ForceClientHudVersionWatermark, (show) => { _version.Visible = VersionVisible(); });
|
||||
_configurationManager.OnValueChanged(CCVars.HudVersionWatermark, (show) => { _version.Visible = VersionVisible(); }, true);
|
||||
_configurationManager.OnValueChanged(CCVars.ForceClientHudVersionWatermark, (show) => { _version.Visible = VersionVisible(); }, true);
|
||||
// TODO make this centered or something
|
||||
LayoutContainer.SetPosition(_version, new Vector2(800, 0));
|
||||
LayoutContainer.SetPosition(_version, new Vector2(70, 0));
|
||||
}
|
||||
|
||||
// This allows servers to force the watermark on clients
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace Content.Client.Ghost
|
||||
private void OnGhostState(EntityUid uid, GhostComponent component, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
if (TryComp<SpriteComponent>(uid, out var sprite))
|
||||
sprite.LayerSetColor(0, component.color);
|
||||
sprite.LayerSetColor(0, component.Color);
|
||||
|
||||
if (uid != _playerManager.LocalEntity)
|
||||
return;
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
using Content.Client.Items;
|
||||
using Content.Shared.Implants;
|
||||
using Content.Shared.Implants.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Implants;
|
||||
|
||||
public sealed class ImplanterSystem : SharedImplanterSystem
|
||||
{
|
||||
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -17,6 +21,18 @@ public sealed class ImplanterSystem : SharedImplanterSystem
|
||||
|
||||
private void OnHandleImplanterState(EntityUid uid, ImplanterComponent component, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
if (_uiSystem.TryGetOpenUi<DeimplantBoundUserInterface>(uid, DeimplantUiKey.Key, out var bui))
|
||||
{
|
||||
Dictionary<string, string> implants = new();
|
||||
foreach (var implant in component.DeimplantWhitelist)
|
||||
{
|
||||
if (_proto.TryIndex(implant, out var proto))
|
||||
implants.Add(proto.ID, proto.Name);
|
||||
}
|
||||
|
||||
bui.UpdateState(implants, component.DeimplantChosen);
|
||||
}
|
||||
|
||||
component.UiUpdateNeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
35
Content.Client/Implants/UI/DeimplantBoundUserInterface.cs
Normal file
35
Content.Client/Implants/UI/DeimplantBoundUserInterface.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Content.Shared.Implants;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Implants.UI;
|
||||
|
||||
public sealed class DeimplantBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _protomanager = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private DeimplantChoiceWindow? _window;
|
||||
|
||||
public DeimplantBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_window = this.CreateWindow<DeimplantChoiceWindow>();
|
||||
|
||||
_window.OnImplantChange += implant => SendMessage(new DeimplantChangeVerbMessage(implant));
|
||||
}
|
||||
|
||||
public void UpdateState(Dictionary<string, string> implantList, string? implant)
|
||||
{
|
||||
if (_window != null)
|
||||
{
|
||||
_window.UpdateImplantList(implantList);
|
||||
_window.UpdateState(implant);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Content.Client/Implants/UI/DeimplantChoiceWindow.xaml
Normal file
12
Content.Client/Implants/UI/DeimplantChoiceWindow.xaml
Normal file
@@ -0,0 +1,12 @@
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc 'implanter-set-draw-window'}"
|
||||
MinSize="5 30">
|
||||
<BoxContainer Orientation="Vertical" Margin="10 5">
|
||||
<Label Text="{Loc 'implanter-set-draw-info'}" Margin="0 0 0 5"/>
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Text="{Loc 'implanter-set-draw-type'}" Margin="0 0 5 0"/>
|
||||
<OptionButton Name="ImplantSelector"/> <!-- Populated in LoadVerbs -->
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</controls:FancyWindow>
|
||||
53
Content.Client/Implants/UI/DeimplantChoiceWindow.xaml.cs
Normal file
53
Content.Client/Implants/UI/DeimplantChoiceWindow.xaml.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Client.Implants.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class DeimplantChoiceWindow : FancyWindow
|
||||
{
|
||||
public Action<string?>? OnImplantChange;
|
||||
|
||||
private Dictionary<string, string> _implants = new();
|
||||
|
||||
private string? _chosenImplant;
|
||||
|
||||
public DeimplantChoiceWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
ImplantSelector.OnItemSelected += args =>
|
||||
{
|
||||
OnImplantChange?.Invoke(_implants.ElementAt(args.Id).Key);
|
||||
ImplantSelector.SelectId(args.Id);
|
||||
};
|
||||
}
|
||||
|
||||
public void UpdateImplantList(Dictionary<string, string> implants)
|
||||
{
|
||||
_implants = implants;
|
||||
int i = 0;
|
||||
ImplantSelector.Clear();
|
||||
foreach (var implantDict in _implants)
|
||||
{
|
||||
ImplantSelector.AddItem(implantDict.Value, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateState(string? implant)
|
||||
{
|
||||
_chosenImplant = implant;
|
||||
|
||||
for (int id = 0; id < ImplantSelector.ItemCount; id++)
|
||||
{
|
||||
if (_implants.ElementAt(id).Key.Equals(_chosenImplant))
|
||||
{
|
||||
ImplantSelector.SelectId(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,17 +4,20 @@ using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Implants.Components;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Implants.UI;
|
||||
|
||||
public sealed class ImplanterStatusControl : Control
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
private readonly ImplanterComponent _parent;
|
||||
private readonly RichTextLabel _label;
|
||||
|
||||
public ImplanterStatusControl(ImplanterComponent parent)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_parent = parent;
|
||||
_label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
|
||||
_label.MaxWidth = 350;
|
||||
@@ -43,12 +46,25 @@ public sealed class ImplanterStatusControl : Control
|
||||
_ => Loc.GetString("injector-invalid-injector-toggle-mode")
|
||||
};
|
||||
|
||||
var implantName = _parent.ImplanterSlot.HasItem
|
||||
? _parent.ImplantData.Item1
|
||||
: Loc.GetString("implanter-empty-text");
|
||||
if (_parent.CurrentMode == ImplanterToggleMode.Draw)
|
||||
{
|
||||
string implantName = _parent.DeimplantChosen != null
|
||||
? (_prototype.TryIndex(_parent.DeimplantChosen.Value, out EntityPrototype? implantProto) ? implantProto.Name : Loc.GetString("implanter-empty-text"))
|
||||
: Loc.GetString("implanter-empty-text");
|
||||
|
||||
_label.SetMarkup(Loc.GetString("implanter-label",
|
||||
("implantName", implantName),
|
||||
("modeString", modeStringLocalized)));
|
||||
_label.SetMarkup(Loc.GetString("implanter-label-draw",
|
||||
("implantName", implantName),
|
||||
("modeString", modeStringLocalized)));
|
||||
}
|
||||
else
|
||||
{
|
||||
var implantName = _parent.ImplanterSlot.HasItem
|
||||
? _parent.ImplantData.Item1
|
||||
: Loc.GetString("implanter-empty-text");
|
||||
|
||||
_label.SetMarkup(Loc.GetString("implanter-label-inject",
|
||||
("implantName", implantName),
|
||||
("modeString", modeStringLocalized)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,8 +94,17 @@ public sealed partial class LatheMenu : DefaultWindow
|
||||
if (!_prototypeManager.TryIndex(recipe, out var proto))
|
||||
continue;
|
||||
|
||||
if (CurrentCategory != null && proto.Category != CurrentCategory)
|
||||
continue;
|
||||
// Category filtering
|
||||
if (CurrentCategory != null)
|
||||
{
|
||||
if (proto.Categories.Count <= 0)
|
||||
continue;
|
||||
|
||||
var validRecipe = proto.Categories.Any(category => category == CurrentCategory);
|
||||
|
||||
if (!validRecipe)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SearchBar.Text.Trim().Length != 0)
|
||||
{
|
||||
@@ -179,18 +188,22 @@ public sealed partial class LatheMenu : DefaultWindow
|
||||
|
||||
public void UpdateCategories()
|
||||
{
|
||||
// Get categories from recipes
|
||||
var currentCategories = new List<ProtoId<LatheCategoryPrototype>>();
|
||||
foreach (var recipeId in Recipes)
|
||||
{
|
||||
var recipe = _prototypeManager.Index(recipeId);
|
||||
|
||||
if (recipe.Category == null)
|
||||
if (recipe.Categories.Count <= 0)
|
||||
continue;
|
||||
|
||||
if (currentCategories.Contains(recipe.Category.Value))
|
||||
continue;
|
||||
foreach (var category in recipe.Categories)
|
||||
{
|
||||
if (currentCategories.Contains(category))
|
||||
continue;
|
||||
|
||||
currentCategories.Add(recipe.Category.Value);
|
||||
currentCategories.Add(category);
|
||||
}
|
||||
}
|
||||
|
||||
if (Categories != null && (Categories.Count == currentCategories.Count || !Categories.All(currentCategories.Contains)))
|
||||
|
||||
@@ -10,7 +10,7 @@ using Robust.Client.Player;
|
||||
|
||||
namespace Content.Client.Movement.Systems;
|
||||
|
||||
public partial class EyeCursorOffsetSystem : EntitySystem
|
||||
public sealed partial class EyeCursorOffsetSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<tabs:KeyRebindTab Name="KeyRebindTab" />
|
||||
<tabs:AudioTab Name="AudioTab" />
|
||||
<tabs:AccessibilityTab Name="AccessibilityTab" />
|
||||
<tabs:AdminOptionsTab Name="AdminOptionsTab" />
|
||||
<!-- CP14-options-menu-start -->
|
||||
<options:CP14OptionsMenuMainTab Name="CP14OptionsMenuTab"/>
|
||||
<!-- CP14-options-menu-end -->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Client.Options.UI.Tabs;
|
||||
using Content.Client.Administration.Managers;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
@@ -8,6 +8,8 @@ namespace Content.Client.Options.UI
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class OptionsMenu : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IClientAdminManager _adminManager = default!;
|
||||
|
||||
public OptionsMenu()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
@@ -18,6 +20,7 @@ namespace Content.Client.Options.UI
|
||||
Tabs.SetTabTitle(2, Loc.GetString("ui-options-tab-controls"));
|
||||
Tabs.SetTabTitle(3, Loc.GetString("ui-options-tab-audio"));
|
||||
Tabs.SetTabTitle(4, Loc.GetString("ui-options-tab-accessibility"));
|
||||
Tabs.SetTabTitle(5, Loc.GetString("ui-options-tab-admin"));
|
||||
|
||||
// CP14-options-menu-start
|
||||
Tabs.SetTabTitle(5, Loc.GetString("cp14-ui-options-tab-main"));
|
||||
@@ -28,10 +31,14 @@ namespace Content.Client.Options.UI
|
||||
|
||||
public void UpdateTabs()
|
||||
{
|
||||
var isAdmin = _adminManager.IsAdmin(true);
|
||||
Tabs.SetTabVisible(5, isAdmin);
|
||||
|
||||
GraphicsTab.Control.ReloadValues();
|
||||
MiscTab.Control.ReloadValues();
|
||||
AccessibilityTab.Control.ReloadValues();
|
||||
AudioTab.Control.ReloadValues();
|
||||
AdminOptionsTab.Control.ReloadValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,11 @@
|
||||
<CheckBox Name="ReducedMotionCheckBox" Text="{Loc 'ui-options-reduced-motion'}" />
|
||||
<CheckBox Name="EnableColorNameCheckBox" Text="{Loc 'ui-options-enable-color-name'}" />
|
||||
<CheckBox Name="ColorblindFriendlyCheckBox" Text="{Loc 'ui-options-colorblind-friendly'}" />
|
||||
<ui:OptionSlider Name="ChatWindowOpacitySlider" Title="{Loc 'ui-options-chat-window-opacity'}" />
|
||||
<ui:OptionSlider Name="ScreenShakeIntensitySlider" Title="{Loc 'ui-options-screen-shake-intensity'}" />
|
||||
<ui:OptionSlider Name="ChatWindowOpacitySlider" Title="{Loc 'ui-options-chat-window-opacity'}" />
|
||||
<ui:OptionSlider Name="SpeechBubbleTextOpacitySlider" Title="{Loc 'ui-options-speech-bubble-text-opacity'}" />
|
||||
<ui:OptionSlider Name="SpeechBubbleSpeakerOpacitySlider" Title="{Loc 'ui-options-speech-bubble-speaker-opacity'}" />
|
||||
<ui:OptionSlider Name="SpeechBubbleBackgroundOpacitySlider" Title="{Loc 'ui-options-speech-bubble-background-opacity'}" />
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
<ui:OptionsTabControlRow Name="Control" Access="Public" />
|
||||
|
||||
@@ -15,8 +15,11 @@ public sealed partial class AccessibilityTab : Control
|
||||
Control.AddOptionCheckBox(CCVars.ChatEnableColorName, EnableColorNameCheckBox);
|
||||
Control.AddOptionCheckBox(CCVars.AccessibilityColorblindFriendly, ColorblindFriendlyCheckBox);
|
||||
Control.AddOptionCheckBox(CCVars.ReducedMotion, ReducedMotionCheckBox);
|
||||
Control.AddOptionPercentSlider(CCVars.ChatWindowOpacity, ChatWindowOpacitySlider);
|
||||
Control.AddOptionPercentSlider(CCVars.ScreenShakeIntensity, ScreenShakeIntensitySlider);
|
||||
Control.AddOptionPercentSlider(CCVars.ChatWindowOpacity, ChatWindowOpacitySlider);
|
||||
Control.AddOptionPercentSlider(CCVars.SpeechBubbleTextOpacity, SpeechBubbleTextOpacitySlider);
|
||||
Control.AddOptionPercentSlider(CCVars.SpeechBubbleSpeakerOpacity, SpeechBubbleSpeakerOpacitySlider);
|
||||
Control.AddOptionPercentSlider(CCVars.SpeechBubbleBackgroundOpacity, SpeechBubbleBackgroundOpacitySlider);
|
||||
|
||||
Control.Initialize();
|
||||
}
|
||||
|
||||
12
Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml
Normal file
12
Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml
Normal file
@@ -0,0 +1,12 @@
|
||||
<Control xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="clr-namespace:Content.Client.Options.UI">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<ScrollContainer VerticalExpand="True" HScrollEnabled="False">
|
||||
<BoxContainer Orientation="Vertical" Margin="8">
|
||||
<CheckBox Name="EnableClassicOverlayCheckBox" Text="{Loc 'ui-options-enable-classic-overlay'}" />
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
<ui:OptionsTabControlRow Name="Control" Access="Public" />
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
20
Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml.cs
Normal file
20
Content.Client/Options/UI/Tabs/AdminOptionsTab.xaml.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Options.UI.Tabs;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class AdminOptionsTab : Control
|
||||
{
|
||||
public AdminOptionsTab()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
Control.AddOptionCheckBox(CCVars.AdminOverlayClassic, EnableClassicOverlayCheckBox);
|
||||
|
||||
Control.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +67,11 @@ public sealed class SubFloorHideSystem : SharedSubFloorHideSystem
|
||||
// allows a t-ray to show wires/pipes above carpets/puddles
|
||||
if (scannerRevealed)
|
||||
{
|
||||
component.OriginalDrawDepth ??= args.Sprite.DrawDepth;
|
||||
args.Sprite.DrawDepth = (int) Shared.DrawDepth.DrawDepth.FloorObjects + 1;
|
||||
if (component.OriginalDrawDepth is not null)
|
||||
return;
|
||||
component.OriginalDrawDepth = args.Sprite.DrawDepth;
|
||||
var drawDepthDifference = Shared.DrawDepth.DrawDepth.ThickPipe - Shared.DrawDepth.DrawDepth.Puddles;
|
||||
args.Sprite.DrawDepth -= drawDepthDifference - 1;
|
||||
}
|
||||
else if (component.OriginalDrawDepth.HasValue)
|
||||
{
|
||||
|
||||
29
Content.Client/SubFloor/TrayScanRevealSystem.cs
Normal file
29
Content.Client/SubFloor/TrayScanRevealSystem.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.SubFloor;
|
||||
using Robust.Shared.Map.Components;
|
||||
|
||||
namespace Content.Client.SubFloor;
|
||||
|
||||
public sealed class TrayScanRevealSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
|
||||
public bool IsUnderRevealingEntity(EntityUid uid)
|
||||
{
|
||||
var gridUid = _transform.GetGrid(uid);
|
||||
if (gridUid is null)
|
||||
return false;
|
||||
|
||||
var gridComp = Comp<MapGridComponent>(gridUid.Value);
|
||||
var position = _transform.GetGridOrMapTilePosition(uid);
|
||||
|
||||
return HasTrayScanReveal(((EntityUid)gridUid, gridComp), position);
|
||||
}
|
||||
|
||||
private bool HasTrayScanReveal(Entity<MapGridComponent> ent, Vector2i position)
|
||||
{
|
||||
var anchoredEnum = _map.GetAnchoredEntities(ent, position);
|
||||
return anchoredEnum.Any(HasComp<TrayScanRevealComponent>);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ public sealed class TrayScannerSystem : SharedTrayScannerSystem
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly TrayScanRevealSystem _trayScanReveal = default!;
|
||||
|
||||
private const string TRayAnimationKey = "trays";
|
||||
private const double AnimationLength = 0.3;
|
||||
@@ -82,7 +83,7 @@ public sealed class TrayScannerSystem : SharedTrayScannerSystem
|
||||
|
||||
foreach (var (uid, comp) in inRange)
|
||||
{
|
||||
if (comp.IsUnderCover)
|
||||
if (comp.IsUnderCover || _trayScanReveal.IsUnderRevealingEntity(uid))
|
||||
EnsureComp<TrayRevealedComponent>(uid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Client.Clothing;
|
||||
using Content.Client.Items.Systems;
|
||||
using Content.Shared.Clothing;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Toggleable;
|
||||
using Robust.Client.GameObjects;
|
||||
@@ -62,7 +63,16 @@ public sealed class ToggleableLightVisualsSystem : VisualizerSystem<ToggleableLi
|
||||
|| !enabled)
|
||||
return;
|
||||
|
||||
if (!component.ClothingVisuals.TryGetValue(args.Slot, out var layers))
|
||||
if (!TryComp(args.Equipee, out InventoryComponent? inventory))
|
||||
return;
|
||||
List<PrototypeLayerData>? layers = null;
|
||||
|
||||
// attempt to get species specific data
|
||||
if (inventory.SpeciesId != null)
|
||||
component.ClothingVisuals.TryGetValue($"{args.Slot}-{inventory.SpeciesId}", out layers);
|
||||
|
||||
// No species specific data. Try to default to generic data.
|
||||
if (layers == null && !component.ClothingVisuals.TryGetValue(args.Slot, out layers))
|
||||
return;
|
||||
|
||||
var modulate = AppearanceSystem.TryGetData<Color>(uid, ToggleableLightVisuals.Color, out var color, appearance);
|
||||
|
||||
@@ -74,7 +74,7 @@ public sealed class CloseRecentWindowUIController : UIController
|
||||
/// internal recentlyInteractedWindows tracking.
|
||||
/// </summary>
|
||||
/// <param name="window"></param>
|
||||
private void SetMostRecentlyInteractedWindow(BaseWindow window)
|
||||
public void SetMostRecentlyInteractedWindow(BaseWindow window)
|
||||
{
|
||||
// Search through the list and see if already added.
|
||||
// (This search is backwards since it's fairly common that the user is clicking the same
|
||||
@@ -134,7 +134,6 @@ public sealed class CloseRecentWindowUIController : UIController
|
||||
if (window.IsOpen)
|
||||
return true;
|
||||
|
||||
recentlyInteractedWindows.RemoveAt(i);
|
||||
// continue going down the list, hoping to find a still-open window
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using Content.Client.Interaction;
|
||||
using Content.Client.Storage;
|
||||
using Content.Client.Storage.Systems;
|
||||
using Content.Client.UserInterface.Systems.Hotbar.Widgets;
|
||||
using Content.Client.UserInterface.Systems.Info;
|
||||
using Content.Client.UserInterface.Systems.Storage.Controls;
|
||||
using Content.Client.Verbs.UI;
|
||||
using Content.Shared.CCVar;
|
||||
@@ -37,6 +38,7 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||
[Dependency] private readonly IInputManager _input = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly CloseRecentWindowUIController _closeRecentWindowUIController = default!;
|
||||
[UISystemDependency] private readonly StorageSystem _storage = default!;
|
||||
[UISystemDependency] private readonly UserInterfaceSystem _ui = default!;
|
||||
|
||||
@@ -98,6 +100,7 @@ public sealed class StorageUIController : UIController, IOnSystemChanged<Storage
|
||||
if (StaticStorageUIEnabled)
|
||||
{
|
||||
UIManager.GetActiveUIWidgetOrNull<HotbarGui>()?.StorageContainer.AddChild(window);
|
||||
_closeRecentWindowUIController.SetMostRecentlyInteractedWindow(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using Content.Shared._CP14.Knowledge;
|
||||
using Content.Shared._CP14.Knowledge.Events;
|
||||
using Content.Shared._CP14.Knowledge.Prototypes;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client._CP14.Knowledge;
|
||||
|
||||
public sealed partial class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
public sealed class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _players = default!;
|
||||
|
||||
@@ -24,7 +25,7 @@ public sealed partial class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSyste
|
||||
if (entity is null)
|
||||
return;
|
||||
|
||||
RaiseNetworkEvent(new RequestKnowledgeInfoEvent(GetNetEntity(entity.Value)));
|
||||
RaiseNetworkEvent(new CP14RequestKnowledgeInfoEvent(GetNetEntity(entity.Value)));
|
||||
}
|
||||
|
||||
private void OnCharacterKnowledgeEvent(CP14KnowledgeInfoEvent msg, EntitySessionEventArgs args)
|
||||
@@ -37,6 +38,6 @@ public sealed partial class ClientCP14KnowledgeSystem : SharedCP14KnowledgeSyste
|
||||
|
||||
public readonly record struct KnowledgeData(
|
||||
EntityUid Entity,
|
||||
HashSet<ProtoId<CP14KnowledgePrototype>> AllKnowledges
|
||||
HashSet<ProtoId<CP14KnowledgePrototype>> AllKnowledge
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
<Control xmlns="https://spacestation14.io">
|
||||
<Button Name="ProductButton" Access="Public">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<EntityPrototypeView Name="EntityView"
|
||||
MinSize="48 48"
|
||||
MaxSize="48 48"
|
||||
Scale="2,2"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Visible="False"/>
|
||||
<TextureRect Name="View"
|
||||
MinSize="48 48"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Stretch="KeepAspectCentered" />
|
||||
Stretch="KeepAspectCentered"
|
||||
Visible="False"/>
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<RichTextLabel Name="SpecialLabel" Text="{Loc 'cp14-store-ui-tab-special'}" VerticalAlignment="Center" Access="Public" Visible="False" />
|
||||
<RichTextLabel Name="ProductName" VerticalAlignment="Center" Access="Public" />
|
||||
|
||||
@@ -3,7 +3,6 @@ using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client._CP14.TravelingStoreShip;
|
||||
|
||||
@@ -26,10 +25,16 @@ public sealed partial class CP14StoreProductControl : Control
|
||||
ProductName.Text = $"[bold]{entry.Name}[/bold]";
|
||||
|
||||
SpecialLabel.Visible = entry.Special;
|
||||
View.Texture = _sprite.Frame0(entry.Icon);
|
||||
}
|
||||
|
||||
private void UpdateView(SpriteSpecifier spriteSpecifier)
|
||||
{
|
||||
if (entry.Icon is not null)
|
||||
{
|
||||
View.Visible = true;
|
||||
View.Texture = _sprite.Frame0(entry.Icon);
|
||||
}
|
||||
else if (entry.EntityView is not null)
|
||||
{
|
||||
EntityView.Visible = true;
|
||||
EntityView.SetPrototype(entry.EntityView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc 'cp14-store-ui-title'}"
|
||||
Name="Window"
|
||||
Title=""
|
||||
MinSize="800 600"
|
||||
SetSize="800 600">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
|
||||
@@ -11,9 +11,6 @@ public sealed partial class CP14StoreWindow : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
private TimeSpan? _nextTravelTime;
|
||||
private bool _onStation;
|
||||
|
||||
public CP14StoreWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
@@ -25,24 +22,8 @@ public sealed partial class CP14StoreWindow : DefaultWindow
|
||||
|
||||
public void UpdateUI(CP14StoreUiState state)
|
||||
{
|
||||
Window.Title = Loc.GetString("cp14-store-ui-title", ("name", state.ShopName));
|
||||
UpdateProducts(state);
|
||||
|
||||
_nextTravelTime = state.NextTravelTime;
|
||||
_onStation = state.OnStation;
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
//Updating time
|
||||
if (_nextTravelTime is not null)
|
||||
{
|
||||
var time = _nextTravelTime.Value - _timing.CurTime;
|
||||
|
||||
TravelTimeLabel.Text =
|
||||
$"{Loc.GetString(_onStation ? "cp14-store-ui-next-travel-out" : "cp14-store-ui-next-travel-in")} {Math.Max(time.Minutes, 0):00}:{Math.Max(time.Seconds, 0):00}";
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateProducts(CP14StoreUiState state)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using Content.Shared._CP14.Vampire;
|
||||
using Content.Shared.Humanoid;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client._CP14.Vampire;
|
||||
|
||||
public sealed class CP14ClientVampireVisualsSystem : CP14SharedVampireVisualsSystem
|
||||
{
|
||||
protected override void OnVampireVisualsInit(Entity<CP14VampireVisualsComponent> vampire, ref ComponentInit args)
|
||||
{
|
||||
base.OnVampireVisualsInit(vampire, ref args);
|
||||
|
||||
if (!EntityManager.TryGetComponent(vampire, out SpriteComponent? sprite))
|
||||
return;
|
||||
|
||||
if (sprite.LayerMapTryGet(vampire.Comp.FangsMap, out var fangsLayerIndex))
|
||||
sprite.LayerSetVisible(fangsLayerIndex, true);
|
||||
|
||||
}
|
||||
|
||||
protected override void OnVampireVisualsShutdown(Entity<CP14VampireVisualsComponent> vampire, ref ComponentShutdown args)
|
||||
{
|
||||
base.OnVampireVisualsShutdown(vampire, ref args);
|
||||
|
||||
if (!EntityManager.TryGetComponent(vampire, out SpriteComponent? sprite))
|
||||
return;
|
||||
|
||||
if (sprite.LayerMapTryGet(vampire.Comp.FangsMap, out var fangsLayerIndex))
|
||||
sprite.LayerSetVisible(fangsLayerIndex, false);
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,8 @@ using Content.Server.Cargo.Systems;
|
||||
using Content.Server.Nutrition.Components;
|
||||
using Content.Server.Nutrition.EntitySystems;
|
||||
using Content.Shared.Cargo.Prototypes;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Prototypes;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
@@ -67,7 +65,7 @@ public sealed class CargoTest
|
||||
var testMap = await pair.CreateTestMap();
|
||||
|
||||
var entManager = server.ResolveDependency<IEntityManager>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var protoManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var cargo = entManager.System<CargoSystem>();
|
||||
|
||||
@@ -93,7 +91,7 @@ public sealed class CargoTest
|
||||
}
|
||||
});
|
||||
|
||||
mapManager.DeleteMap(mapId);
|
||||
mapSystem.DeleteMap(mapId);
|
||||
});
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
@@ -151,6 +149,7 @@ public sealed class CargoTest
|
||||
var testMap = await pair.CreateTestMap();
|
||||
|
||||
var entManager = server.ResolveDependency<IEntityManager>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var protoManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var componentFactory = server.ResolveDependency<IComponentFactory>();
|
||||
@@ -207,7 +206,7 @@ public sealed class CargoTest
|
||||
|
||||
entManager.DeleteEntity(ent);
|
||||
}
|
||||
mapManager.DeleteMap(mapId);
|
||||
mapSystem.DeleteMap(mapId);
|
||||
});
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
|
||||
@@ -59,6 +59,32 @@ namespace Content.IntegrationTests.Tests.Chemistry
|
||||
#pragma warning restore NUnit2045
|
||||
}
|
||||
|
||||
//------------CP14 - improve test for alchemy
|
||||
//Get all possible reactions with the current reagents
|
||||
var possibleReactions = prototypeManager.EnumeratePrototypes<ReactionPrototype>()
|
||||
.Where(x => x.Reactants.All(id => solution.Contents.Any(s => s.Reagent.Prototype == id.Key)))
|
||||
.ToList();
|
||||
|
||||
//Check if the reaction is the first to occur when heated
|
||||
foreach (var possibleReaction in possibleReactions.OrderBy(r => r.MinimumTemperature))
|
||||
{
|
||||
if (possibleReaction.MinimumTemperature < reactionPrototype.MinimumTemperature && possibleReaction.MixingCategories == reactionPrototype.MixingCategories)
|
||||
{
|
||||
Assert.Fail($"The {possibleReaction.ID} reaction may occur before {reactionPrototype.ID} when heated.");
|
||||
}
|
||||
}
|
||||
|
||||
//Check if the reaction is the first to occur when freezing
|
||||
foreach (var possibleReaction in possibleReactions.OrderBy(r => r.MaximumTemperature))
|
||||
{
|
||||
if (possibleReaction.MaximumTemperature > reactionPrototype.MaximumTemperature && possibleReaction.MixingCategories == reactionPrototype.MixingCategories)
|
||||
{
|
||||
Assert.Fail($"The {possibleReaction.ID} reaction may occur before {reactionPrototype.ID} when freezing.");
|
||||
}
|
||||
}
|
||||
|
||||
//Now safe set the temperature and mix the reagents
|
||||
//----------CP14 - improve test for alchemy end
|
||||
solutionContainerSystem.SetTemperature(solutionEnt.Value, reactionPrototype.MinimumTemperature);
|
||||
|
||||
if (reactionPrototype.MixingCategories != null)
|
||||
|
||||
@@ -6,7 +6,6 @@ using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Hands;
|
||||
|
||||
@@ -38,7 +37,7 @@ public sealed class HandTests
|
||||
|
||||
var entMan = server.ResolveDependency<IEntityManager>();
|
||||
var playerMan = server.ResolveDependency<IPlayerManager>();
|
||||
var mapMan = server.ResolveDependency<IMapManager>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var sys = entMan.System<SharedHandsSystem>();
|
||||
var tSys = entMan.System<TransformSystem>();
|
||||
|
||||
@@ -69,7 +68,7 @@ public sealed class HandTests
|
||||
await pair.RunTicksSync(5);
|
||||
Assert.That(hands.ActiveHandEntity, Is.Null);
|
||||
|
||||
await server.WaitPost(() => mapMan.DeleteMap(data.MapId));
|
||||
await server.WaitPost(() => mapSystem.DeleteMap(data.MapId));
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
|
||||
@@ -87,7 +86,7 @@ public sealed class HandTests
|
||||
|
||||
var entMan = server.ResolveDependency<IEntityManager>();
|
||||
var playerMan = server.ResolveDependency<IPlayerManager>();
|
||||
var mapMan = server.ResolveDependency<IMapManager>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var sys = entMan.System<SharedHandsSystem>();
|
||||
var tSys = entMan.System<TransformSystem>();
|
||||
var containerSystem = server.System<SharedContainerSystem>();
|
||||
@@ -134,7 +133,7 @@ public sealed class HandTests
|
||||
Assert.That(hands.ActiveHandEntity, Is.Not.EqualTo(item));
|
||||
Assert.That(containerSystem.IsInSameOrNoContainer((player, xform), (item, itemXform)));
|
||||
|
||||
await server.WaitPost(() => mapMan.DeleteMap(map.MapId));
|
||||
await server.WaitPost(() => mapSystem.DeleteMap(map.MapId));
|
||||
await pair.CleanReturnAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Shared.Inventory;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.IntegrationTests.Tests
|
||||
{
|
||||
@@ -67,7 +66,7 @@ namespace Content.IntegrationTests.Tests
|
||||
EntityUid pocketItem = default;
|
||||
|
||||
InventorySystem invSystem = default!;
|
||||
var mapMan = server.ResolveDependency<IMapManager>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var entityMan = server.ResolveDependency<IEntityManager>();
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
@@ -129,7 +128,7 @@ namespace Content.IntegrationTests.Tests
|
||||
Assert.That(!invSystem.TryGetSlotEntity(human, "pocket1", out _));
|
||||
});
|
||||
|
||||
mapMan.DeleteMap(testMap.MapId);
|
||||
mapSystem.DeleteMap(testMap.MapId);
|
||||
});
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
|
||||
@@ -260,7 +260,7 @@ public abstract partial class InteractionTest
|
||||
[TearDown]
|
||||
public async Task TearDownInternal()
|
||||
{
|
||||
await Server.WaitPost(() => MapMan.DeleteMap(MapId));
|
||||
await Server.WaitPost(() => MapSystem.DeleteMap(MapId));
|
||||
await Pair.CleanReturnAsync();
|
||||
await TearDown();
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ public sealed class MaterialArbitrageTest
|
||||
}
|
||||
});
|
||||
|
||||
await server.WaitPost(() => mapManager.DeleteMap(testMap.MapId));
|
||||
await server.WaitPost(() => mapSystem.DeleteMap(testMap.MapId));
|
||||
await pair.CleanReturnAsync();
|
||||
|
||||
async Task<double> GetSpawnedPrice(Dictionary<string, int> ents)
|
||||
|
||||
@@ -3,7 +3,6 @@ using Content.Server.Stack;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Materials;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Materials
|
||||
@@ -24,7 +23,7 @@ namespace Content.IntegrationTests.Tests.Materials
|
||||
var server = pair.Server;
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
|
||||
@@ -59,7 +58,7 @@ namespace Content.IntegrationTests.Tests.Materials
|
||||
}
|
||||
});
|
||||
|
||||
mapManager.DeleteMap(testMap.MapId);
|
||||
mapSystem.DeleteMap(testMap.MapId);
|
||||
});
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
|
||||
@@ -81,7 +81,7 @@ public sealed partial class MindTests
|
||||
var testMap2 = await pair.CreateTestMap();
|
||||
|
||||
var entMan = server.ResolveDependency<IServerEntityManager>();
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var playerMan = server.ResolveDependency<IPlayerManager>();
|
||||
var player = playerMan.Sessions.Single();
|
||||
|
||||
@@ -101,7 +101,7 @@ public sealed partial class MindTests
|
||||
});
|
||||
|
||||
await pair.RunTicksSync(5);
|
||||
await server.WaitAssertion(() => mapManager.DeleteMap(testMap.MapId));
|
||||
await server.WaitAssertion(() => mapSystem.DeleteMap(testMap.MapId));
|
||||
await pair.RunTicksSync(5);
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Systems;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Maps;
|
||||
using Content.Server.Shuttles.Components;
|
||||
@@ -42,6 +43,7 @@ namespace Content.IntegrationTests.Tests
|
||||
//CrystallEdge Map replacement
|
||||
|
||||
//CrystallEdge Map replacement end
|
||||
AdminTestArenaSystem.ArenaMapPath
|
||||
};
|
||||
|
||||
private static readonly string[] DoNotMapWhitelist =
|
||||
|
||||
@@ -2,7 +2,6 @@ using System.Linq;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Server.Storage.EntitySystems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Collections;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Roles;
|
||||
@@ -19,7 +18,7 @@ public sealed class StartingGearPrototypeStorageTest
|
||||
var settings = new PoolSettings { Connected = true, Dirty = true };
|
||||
await using var pair = await PoolManager.GetServerClient(settings);
|
||||
var server = pair.Server;
|
||||
var mapManager = server.ResolveDependency<IMapManager>();
|
||||
var mapSystem = server.System<SharedMapSystem>();
|
||||
var storageSystem = server.System<StorageSystem>();
|
||||
|
||||
var protos = server.ProtoMan
|
||||
@@ -64,7 +63,7 @@ public sealed class StartingGearPrototypeStorageTest
|
||||
}
|
||||
}
|
||||
|
||||
mapManager.DeleteMap(testMap.MapId);
|
||||
mapSystem.DeleteMap(testMap.MapId);
|
||||
});
|
||||
|
||||
await pair.CleanReturnAsync();
|
||||
|
||||
@@ -55,5 +55,16 @@ namespace Content.Server.Abilities.Mime
|
||||
[DataField]
|
||||
public ProtoId<AlertPrototype> VowBrokenAlert = "VowBroken";
|
||||
|
||||
/// <summary>
|
||||
/// Does this component prevent the mime from writing on paper while their vow is active?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool PreventWriting = false;
|
||||
|
||||
/// <summary>
|
||||
/// What message is displayed when the mime fails to write?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId FailWriteMessage = "paper-component-illiterate-mime";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Content.Shared.Actions.Events;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Coordinates.Helpers;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Paper;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Map;
|
||||
@@ -55,6 +56,13 @@ namespace Content.Server.Abilities.Mime
|
||||
private void OnComponentInit(EntityUid uid, MimePowersComponent component, ComponentInit args)
|
||||
{
|
||||
EnsureComp<MutedComponent>(uid);
|
||||
if (component.PreventWriting)
|
||||
{
|
||||
EnsureComp<BlockWritingComponent>(uid, out var illiterateComponent);
|
||||
illiterateComponent.FailWriteMessage = component.FailWriteMessage;
|
||||
Dirty(uid, illiterateComponent);
|
||||
}
|
||||
|
||||
_alertsSystem.ShowAlert(uid, component.VowAlert);
|
||||
_actionsSystem.AddAction(uid, ref component.InvisibleWallActionEntity, component.InvisibleWallAction, uid);
|
||||
}
|
||||
@@ -123,6 +131,8 @@ namespace Content.Server.Abilities.Mime
|
||||
mimePowers.VowBroken = true;
|
||||
mimePowers.VowRepentTime = _timing.CurTime + mimePowers.VowCooldown;
|
||||
RemComp<MutedComponent>(uid);
|
||||
if (mimePowers.PreventWriting)
|
||||
RemComp<BlockWritingComponent>(uid);
|
||||
_alertsSystem.ClearAlert(uid, mimePowers.VowAlert);
|
||||
_alertsSystem.ShowAlert(uid, mimePowers.VowBrokenAlert);
|
||||
_actionsSystem.RemoveAction(uid, mimePowers.InvisibleWallActionEntity);
|
||||
@@ -146,6 +156,13 @@ namespace Content.Server.Abilities.Mime
|
||||
mimePowers.ReadyToRepent = false;
|
||||
mimePowers.VowBroken = false;
|
||||
AddComp<MutedComponent>(uid);
|
||||
if (mimePowers.PreventWriting)
|
||||
{
|
||||
EnsureComp<BlockWritingComponent>(uid, out var illiterateComponent);
|
||||
illiterateComponent.FailWriteMessage = mimePowers.FailWriteMessage;
|
||||
Dirty(uid, illiterateComponent);
|
||||
}
|
||||
|
||||
_alertsSystem.ClearAlert(uid, mimePowers.VowBrokenAlert);
|
||||
_alertsSystem.ShowAlert(uid, mimePowers.VowAlert);
|
||||
_actionsSystem.AddAction(uid, ref mimePowers.InvisibleWallActionEntity, mimePowers.InvisibleWallAction, uid);
|
||||
|
||||
@@ -74,5 +74,15 @@ namespace Content.Server.Administration.Commands
|
||||
|
||||
mindSystem.TransferTo(mind, eUid, ghostOverride);
|
||||
}
|
||||
|
||||
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
|
||||
{
|
||||
if (args.Length == 2)
|
||||
{
|
||||
return CompletionResult.FromHintOptions(CompletionHelper.SessionNames(), Loc.GetString("cmd-mind-command-hint"));
|
||||
}
|
||||
|
||||
return CompletionResult.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public sealed class AdminTestArenaSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly MapLoaderSystem _loader = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaDataSystem = default!;
|
||||
[Dependency] private readonly SharedMapSystem _maps = default!;
|
||||
|
||||
public const string ArenaMapPath = "/Maps/Test/admin_test_arena.yml";
|
||||
|
||||
@@ -33,17 +34,20 @@ public sealed class AdminTestArenaSystem : EntitySystem
|
||||
}
|
||||
|
||||
var path = new ResPath(ArenaMapPath);
|
||||
if (!_loader.TryLoadMap(path, out var map, out var grids))
|
||||
var mapUid = _maps.CreateMap(out var mapId);
|
||||
|
||||
if (!_loader.TryLoadGrid(mapId, path, out var grid))
|
||||
{
|
||||
QueueDel(mapUid);
|
||||
throw new Exception($"Failed to load admin arena");
|
||||
}
|
||||
|
||||
ArenaMap[admin.UserId] = map.Value.Owner;
|
||||
_metaDataSystem.SetEntityName(map.Value.Owner, $"ATAM-{admin.Name}");
|
||||
ArenaMap[admin.UserId] = mapUid;
|
||||
_metaDataSystem.SetEntityName(mapUid, $"ATAM-{admin.Name}");
|
||||
|
||||
var grid = grids.FirstOrNull();
|
||||
ArenaGrid[admin.UserId] = grid?.Owner;
|
||||
if (grid != null)
|
||||
_metaDataSystem.SetEntityName(grid.Value.Owner, $"ATAG-{admin.Name}");
|
||||
ArenaGrid[admin.UserId] = grid.Value.Owner;
|
||||
_metaDataSystem.SetEntityName(grid.Value.Owner, $"ATAG-{admin.Name}");
|
||||
|
||||
return (map.Value.Owner, grid?.Owner);
|
||||
return (mapUid, grid.Value.Owner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server._CP14.GameTicking.Rules.Components;
|
||||
using Content.Server.Administration.Commands;
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
@@ -36,6 +37,11 @@ public sealed partial class AdminVerbSystem
|
||||
[ValidatePrototypeId<StartingGearPrototype>]
|
||||
private const string PirateGearId = "PirateGear";
|
||||
|
||||
//CP14
|
||||
[ValidatePrototypeId<EntityPrototype>]
|
||||
private const string CP14VampireRule = "CP14Vampire";
|
||||
//CP14 end
|
||||
|
||||
// All antag verbs have names so invokeverb works.
|
||||
private void AddAntagVerbs(GetVerbsEvent<Verb> args)
|
||||
{
|
||||
@@ -52,6 +58,21 @@ public sealed partial class AdminVerbSystem
|
||||
|
||||
var targetPlayer = targetActor.PlayerSession;
|
||||
|
||||
Verb vampire = new()
|
||||
{
|
||||
Text = Loc.GetString("cp14-admin-verb-text-make-vampire"),
|
||||
Category = VerbCategory.Antag,
|
||||
Icon = new SpriteSpecifier.Rsi(new ResPath("/Textures/_CP14/Actions/Spells/vampire.rsi"),
|
||||
"bite"),
|
||||
Act = () =>
|
||||
{
|
||||
_antag.ForceMakeAntag<CP14VampireRuleComponent>(targetPlayer, CP14VampireRule);
|
||||
},
|
||||
Impact = LogImpact.High,
|
||||
Message = Loc.GetString("cp14-admin-verb-make-vampire"),
|
||||
};
|
||||
args.Verbs.Add(vampire);
|
||||
|
||||
/* CP14 disable default antags
|
||||
Verb traitor = new()
|
||||
{
|
||||
|
||||
@@ -759,6 +759,7 @@ namespace Content.Server.Administration.Systems
|
||||
_gameTicker.RoundDuration().ToString("hh\\:mm\\:ss"),
|
||||
_gameTicker.RunLevel,
|
||||
playedSound: playSound,
|
||||
adminOnly: message.AdminOnly,
|
||||
noReceivers: nonAfkAdmins.Count == 0
|
||||
);
|
||||
_messageQueues[msg.UserId].Enqueue(GenerateAHelpMessage(messageParams));
|
||||
@@ -790,7 +791,7 @@ namespace Content.Server.Administration.Systems
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static DiscordRelayedData GenerateAHelpMessage(AHelpMessageParams parameters)
|
||||
private DiscordRelayedData GenerateAHelpMessage(AHelpMessageParams parameters)
|
||||
{
|
||||
var stringbuilder = new StringBuilder();
|
||||
|
||||
@@ -806,7 +807,7 @@ namespace Content.Server.Administration.Systems
|
||||
if (parameters.RoundTime != string.Empty && parameters.RoundState == GameRunLevel.InRound)
|
||||
stringbuilder.Append($" **{parameters.RoundTime}**");
|
||||
if (!parameters.PlayedSound)
|
||||
stringbuilder.Append(" **(S)**");
|
||||
stringbuilder.Append($" **{(parameters.AdminOnly ? Loc.GetString("bwoink-message-admin-only") : Loc.GetString("bwoink-message-silent"))}**");
|
||||
if (parameters.Icon == null)
|
||||
stringbuilder.Append($" **{parameters.Username}:** ");
|
||||
else
|
||||
@@ -869,6 +870,7 @@ namespace Content.Server.Administration.Systems
|
||||
public string RoundTime { get; set; }
|
||||
public GameRunLevel RoundState { get; set; }
|
||||
public bool PlayedSound { get; set; }
|
||||
public readonly bool AdminOnly;
|
||||
public bool NoReceivers { get; set; }
|
||||
public string? Icon { get; set; }
|
||||
|
||||
@@ -879,6 +881,7 @@ namespace Content.Server.Administration.Systems
|
||||
string roundTime,
|
||||
GameRunLevel roundState,
|
||||
bool playedSound,
|
||||
bool adminOnly = false,
|
||||
bool noReceivers = false,
|
||||
string? icon = null)
|
||||
{
|
||||
@@ -888,6 +891,7 @@ namespace Content.Server.Administration.Systems
|
||||
RoundTime = roundTime;
|
||||
RoundState = roundState;
|
||||
PlayedSound = playedSound;
|
||||
AdminOnly = adminOnly;
|
||||
NoReceivers = noReceivers;
|
||||
Icon = icon;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Content.Server.AlertLevel;
|
||||
[Prototype("alertLevels")]
|
||||
public sealed partial class AlertLevelPrototype : IPrototype
|
||||
{
|
||||
[IdDataField] public string ID { get; } = default!;
|
||||
[IdDataField] public string ID { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary of alert levels. Keyed by string - the string key is the most important
|
||||
|
||||
@@ -28,7 +28,7 @@ public sealed partial class AntagRandomObjectivesComponent : Component
|
||||
/// Difficulty is checked over all sets, but each set has its own probability and pick count.
|
||||
/// </summary>
|
||||
[DataRecord]
|
||||
public record struct AntagObjectiveSet()
|
||||
public partial record struct AntagObjectiveSet()
|
||||
{
|
||||
/// <summary>
|
||||
/// The grouping used by the objective system to pick random objectives.
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Content.Server.Bible
|
||||
}
|
||||
summonableComp.AlreadySummoned = false;
|
||||
_popupSystem.PopupEntity(Loc.GetString("bible-summon-respawn-ready", ("book", uid)), uid, PopupType.Medium);
|
||||
_audio.PlayPvs("/Audio/Effects/radpulse9.ogg", uid, AudioParams.Default.WithVolume(-4f));
|
||||
_audio.PlayPvs(summonableComp.SummonSound, uid);
|
||||
// Clean up the accumulator and respawn tracking component
|
||||
summonableComp.Accumulator = 0;
|
||||
_remQueue.Enqueue(uid);
|
||||
@@ -126,7 +126,7 @@ namespace Content.Server.Bible
|
||||
var selfFailMessage = Loc.GetString(component.LocPrefix + "-heal-fail-self", ("target", Identity.Entity(args.Target.Value, EntityManager)), ("bible", uid));
|
||||
_popupSystem.PopupEntity(selfFailMessage, args.User, args.User, PopupType.MediumCaution);
|
||||
|
||||
_audio.PlayPvs("/Audio/Effects/hit_kick.ogg", args.User);
|
||||
_audio.PlayPvs(component.BibleHitSound, args.User);
|
||||
_damageableSystem.TryChangeDamage(args.Target.Value, component.DamageOnFail, true, origin: uid);
|
||||
_delay.TryResetDelay((uid, useDelay));
|
||||
return;
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Bible.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class BibleComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Default sound when bible hits somebody.
|
||||
/// </summary>
|
||||
private static readonly ProtoId<SoundCollectionPrototype> DefaultBibleHit = new("BibleHit");
|
||||
|
||||
/// <summary>
|
||||
/// Sound to play when bible hits somebody.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public SoundSpecifier BibleHitSound = new SoundCollectionSpecifier(DefaultBibleHit, AudioParams.Default.WithVolume(-4f));
|
||||
|
||||
/// <summary>
|
||||
/// Damage that will be healed on a success
|
||||
/// </summary>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
@@ -9,6 +10,17 @@ namespace Content.Server.Bible.Components
|
||||
[RegisterComponent]
|
||||
public sealed partial class SummonableComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Default sound to play when entity is summoned.
|
||||
/// </summary>
|
||||
private static readonly ProtoId<SoundCollectionPrototype> DefaultSummonSound = new("Summon");
|
||||
|
||||
/// <summary>
|
||||
/// Sound to play when entity is summoned.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public SoundSpecifier SummonSound = new SoundCollectionSpecifier(DefaultSummonSound, AudioParams.Default.WithVolume(-4f));
|
||||
|
||||
/// <summary>
|
||||
/// Used for a special item only the Chaplain can summon. Usually a mob, but supports regular items too.
|
||||
/// </summary>
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Content.Server.Botany;
|
||||
[Prototype("seed")]
|
||||
public sealed partial class SeedPrototype : SeedData, IPrototype
|
||||
{
|
||||
[IdDataField] public string ID { get; private init; } = default!;
|
||||
[IdDataField] public string ID { get; private set; } = default!;
|
||||
}
|
||||
|
||||
public enum HarvestType : byte
|
||||
|
||||
@@ -427,6 +427,7 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
|
||||
private void OnUiMessage(EntityUid uid, CartridgeLoaderComponent component, CartridgeUiMessage args)
|
||||
{
|
||||
var cartridgeEvent = args.MessageEvent;
|
||||
cartridgeEvent.User = args.Actor;
|
||||
cartridgeEvent.LoaderUid = GetNetEntity(uid);
|
||||
cartridgeEvent.Actor = args.Actor;
|
||||
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
using Content.Shared.Paper;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Server.CartridgeLoader.Cartridges;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(LogProbeCartridgeSystem))]
|
||||
[RegisterComponent, Access(typeof(LogProbeCartridgeSystem))]
|
||||
[AutoGenerateComponentPause]
|
||||
public sealed partial class LogProbeCartridgeComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the scanned entity, sent to clients when they open the UI.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string EntityName = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The list of pulled access logs
|
||||
/// </summary>
|
||||
@@ -18,4 +27,25 @@ public sealed partial class LogProbeCartridgeComponent : Component
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public SoundSpecifier SoundScan = new SoundPathSpecifier("/Audio/Machines/scan_finish.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// Paper to spawn when printing logs.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntProtoId<PaperComponent> PaperPrototype = "PaperAccessLogs";
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier PrintSound = new SoundPathSpecifier("/Audio/Machines/diagnoser_printing.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// How long you have to wait before printing logs again.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public TimeSpan PrintCooldown = TimeSpan.FromSeconds(5);
|
||||
|
||||
/// <summary>
|
||||
/// When anyone is allowed to spawn another printout.
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
|
||||
public TimeSpan NextPrintAllowed = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,40 @@
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.CartridgeLoader;
|
||||
using Content.Shared.CartridgeLoader.Cartridges;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Labels.EntitySystems;
|
||||
using Content.Shared.Paper;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using System.Text;
|
||||
|
||||
namespace Content.Server.CartridgeLoader.Cartridges;
|
||||
|
||||
public sealed class LogProbeCartridgeSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly CartridgeLoaderSystem _cartridge = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly CartridgeLoaderSystem? _cartridgeLoaderSystem = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedHandsSystem _hands = default!;
|
||||
[Dependency] private readonly SharedLabelSystem _label = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly PaperSystem _paper = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<LogProbeCartridgeComponent, CartridgeUiReadyEvent>(OnUiReady);
|
||||
SubscribeLocalEvent<LogProbeCartridgeComponent, CartridgeAfterInteractEvent>(AfterInteract);
|
||||
SubscribeLocalEvent<LogProbeCartridgeComponent, CartridgeMessageEvent>(OnMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -37,9 +52,10 @@ public sealed class LogProbeCartridgeSystem : EntitySystem
|
||||
return;
|
||||
|
||||
//Play scanning sound with slightly randomized pitch
|
||||
_audioSystem.PlayEntity(ent.Comp.SoundScan, args.InteractEvent.User, target, AudioHelpers.WithVariation(0.25f, _random));
|
||||
_popupSystem.PopupCursor(Loc.GetString("log-probe-scan", ("device", target)), args.InteractEvent.User);
|
||||
_audio.PlayEntity(ent.Comp.SoundScan, args.InteractEvent.User, target, AudioHelpers.WithVariation(0.25f, _random));
|
||||
_popup.PopupCursor(Loc.GetString("log-probe-scan", ("device", target)), args.InteractEvent.User);
|
||||
|
||||
ent.Comp.EntityName = Name(target);
|
||||
ent.Comp.PulledAccessLogs.Clear();
|
||||
|
||||
foreach (var accessRecord in accessReaderComponent.AccessLog)
|
||||
@@ -52,6 +68,9 @@ public sealed class LogProbeCartridgeSystem : EntitySystem
|
||||
ent.Comp.PulledAccessLogs.Add(log);
|
||||
}
|
||||
|
||||
// Reverse the list so the oldest is at the bottom
|
||||
ent.Comp.PulledAccessLogs.Reverse();
|
||||
|
||||
UpdateUiState(ent, args.Loader);
|
||||
}
|
||||
|
||||
@@ -63,9 +82,49 @@ public sealed class LogProbeCartridgeSystem : EntitySystem
|
||||
UpdateUiState(ent, args.Loader);
|
||||
}
|
||||
|
||||
private void OnMessage(Entity<LogProbeCartridgeComponent> ent, ref CartridgeMessageEvent args)
|
||||
{
|
||||
if (args is LogProbePrintMessage cast)
|
||||
PrintLogs(ent, cast.User);
|
||||
}
|
||||
|
||||
private void PrintLogs(Entity<LogProbeCartridgeComponent> ent, EntityUid user)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ent.Comp.EntityName))
|
||||
return;
|
||||
|
||||
if (_timing.CurTime < ent.Comp.NextPrintAllowed)
|
||||
return;
|
||||
|
||||
ent.Comp.NextPrintAllowed = _timing.CurTime + ent.Comp.PrintCooldown;
|
||||
|
||||
var paper = Spawn(ent.Comp.PaperPrototype, _transform.GetMapCoordinates(user));
|
||||
_label.Label(paper, ent.Comp.EntityName); // label it for easy identification
|
||||
|
||||
_audio.PlayEntity(ent.Comp.PrintSound, user, paper);
|
||||
_hands.PickupOrDrop(user, paper, checkActionBlocker: false);
|
||||
|
||||
// generate the actual printout text
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendLine(Loc.GetString("log-probe-printout-device", ("name", ent.Comp.EntityName)));
|
||||
builder.AppendLine(Loc.GetString("log-probe-printout-header"));
|
||||
var number = 1;
|
||||
foreach (var log in ent.Comp.PulledAccessLogs)
|
||||
{
|
||||
var time = TimeSpan.FromSeconds(Math.Truncate(log.Time.TotalSeconds)).ToString();
|
||||
builder.AppendLine(Loc.GetString("log-probe-printout-entry", ("number", number), ("time", time), ("accessor", log.Accessor)));
|
||||
number++;
|
||||
}
|
||||
|
||||
var paperComp = Comp<PaperComponent>(paper);
|
||||
_paper.SetContent((paper, paperComp), builder.ToString());
|
||||
|
||||
_adminLogger.Add(LogType.EntitySpawn, LogImpact.Low, $"{ToPrettyString(user):user} printed out LogProbe logs ({paper}) of {ent.Comp.EntityName}");
|
||||
}
|
||||
|
||||
private void UpdateUiState(Entity<LogProbeCartridgeComponent> ent, EntityUid loaderUid)
|
||||
{
|
||||
var state = new LogProbeUiState(ent.Comp.PulledAccessLogs);
|
||||
_cartridgeLoaderSystem?.UpdateCartridgeUiState(loaderUid, state);
|
||||
var state = new LogProbeUiState(ent.Comp.EntityName, ent.Comp.PulledAccessLogs);
|
||||
_cartridge.UpdateCartridgeUiState(loaderUid, state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ namespace Content.Server.Chemistry.Components
|
||||
[DataField("mode"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public ChemMasterMode Mode = ChemMasterMode.Transfer;
|
||||
|
||||
[DataField]
|
||||
public ChemMasterSortingType SortingType = ChemMasterSortingType.None;
|
||||
|
||||
[DataField("pillDosageLimit", required: true), ViewVariables(VVAccess.ReadWrite)]
|
||||
public uint PillDosageLimit;
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
SubscribeLocalEvent<ChemMasterComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
|
||||
|
||||
SubscribeLocalEvent<ChemMasterComponent, ChemMasterSetModeMessage>(OnSetModeMessage);
|
||||
SubscribeLocalEvent<ChemMasterComponent, ChemMasterSortingTypeCycleMessage>(OnCycleSortingTypeMessage);
|
||||
SubscribeLocalEvent<ChemMasterComponent, ChemMasterSetPillTypeMessage>(OnSetPillTypeMessage);
|
||||
SubscribeLocalEvent<ChemMasterComponent, ChemMasterReagentAmountButtonMessage>(OnReagentButtonMessage);
|
||||
SubscribeLocalEvent<ChemMasterComponent, ChemMasterCreatePillsMessage>(OnCreatePillsMessage);
|
||||
@@ -76,7 +77,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
var bufferCurrentVolume = bufferSolution.Volume;
|
||||
|
||||
var state = new ChemMasterBoundUserInterfaceState(
|
||||
chemMaster.Mode, BuildInputContainerInfo(inputContainer), BuildOutputContainerInfo(outputContainer),
|
||||
chemMaster.Mode, chemMaster.SortingType, BuildInputContainerInfo(inputContainer), BuildOutputContainerInfo(outputContainer),
|
||||
bufferReagents, bufferCurrentVolume, chemMaster.PillType, chemMaster.PillDosageLimit, updateLabel);
|
||||
|
||||
_userInterfaceSystem.SetUiState(owner, ChemMasterUiKey.Key, state);
|
||||
@@ -93,6 +94,15 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
ClickSound(chemMaster);
|
||||
}
|
||||
|
||||
private void OnCycleSortingTypeMessage(Entity<ChemMasterComponent> chemMaster, ref ChemMasterSortingTypeCycleMessage message)
|
||||
{
|
||||
chemMaster.Comp.SortingType++;
|
||||
if (chemMaster.Comp.SortingType > ChemMasterSortingType.Latest)
|
||||
chemMaster.Comp.SortingType = ChemMasterSortingType.None;
|
||||
UpdateUiState(chemMaster);
|
||||
ClickSound(chemMaster);
|
||||
}
|
||||
|
||||
private void OnSetPillTypeMessage(Entity<ChemMasterComponent> chemMaster, ref ChemMasterSetPillTypeMessage message)
|
||||
{
|
||||
// Ensure valid pill type. There are 20 pills selectable, 0-19.
|
||||
|
||||
@@ -18,25 +18,25 @@ namespace Content.Server.Connection.Whitelist;
|
||||
/// If the condition doesn't match, the next condition is checked.
|
||||
/// </summary>
|
||||
[Prototype("playerConnectionWhitelist")]
|
||||
public sealed class PlayerConnectionWhitelistPrototype : IPrototype
|
||||
public sealed partial class PlayerConnectionWhitelistPrototype : IPrototype
|
||||
{
|
||||
[IdDataField]
|
||||
public string ID { get; } = default!;
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum number of players required for this whitelist to be active.
|
||||
/// If there are less players than this, the whitelist will be ignored and the next one in the list will be used.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int MinimumPlayers { get; } = 0;
|
||||
public int MinimumPlayers = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of players allowed for this whitelist to be active.
|
||||
/// If there are more players than this, the whitelist will be ignored and the next one in the list will be used.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int MaximumPlayers { get; } = int.MaxValue;
|
||||
public int MaximumPlayers = int.MaxValue;
|
||||
|
||||
[DataField]
|
||||
public WhitelistCondition[] Conditions { get; } = default!;
|
||||
public WhitelistCondition[] Conditions = default!;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,12 @@ public sealed class ThrowInsertContainerSystem : EntitySystem
|
||||
if (!_containerSystem.CanInsert(args.Thrown, container))
|
||||
return;
|
||||
|
||||
var beforeThrowArgs = new BeforeThrowInsertEvent(args.Thrown);
|
||||
RaiseLocalEvent(ent, ref beforeThrowArgs);
|
||||
|
||||
if (beforeThrowArgs.Cancelled)
|
||||
return;
|
||||
|
||||
if (_random.Prob(ent.Comp.Probability))
|
||||
{
|
||||
_audio.PlayPvs(ent.Comp.MissSound, ent);
|
||||
@@ -46,3 +52,10 @@ public sealed class ThrowInsertContainerSystem : EntitySystem
|
||||
_adminLogger.Add(LogType.Landed, LogImpact.Low, $"{ToPrettyString(args.Thrown)} thrown by {ToPrettyString(args.Component.Thrower.Value):player} landed in {ToPrettyString(ent)}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sent before the insertion is made.
|
||||
/// Allows preventing the insertion if any system on the entity should need to.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct BeforeThrowInsertEvent(EntityUid ThrownEntity, bool Cancelled = false);
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Containers;
|
||||
using Content.Server.Disposal.Tube;
|
||||
using Content.Server.Disposal.Tube.Components;
|
||||
using Content.Server.Disposal.Unit.Components;
|
||||
@@ -85,6 +86,8 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
|
||||
|
||||
SubscribeLocalEvent<DisposalUnitComponent, DisposalDoAfterEvent>(OnDoAfter);
|
||||
|
||||
SubscribeLocalEvent<DisposalUnitComponent, BeforeThrowInsertEvent>(OnThrowInsert);
|
||||
|
||||
SubscribeLocalEvent<DisposalUnitComponent, SharedDisposalUnitComponent.UiButtonPressedMessage>(OnUiButtonPressed);
|
||||
}
|
||||
|
||||
@@ -195,6 +198,12 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnThrowInsert(Entity<DisposalUnitComponent> ent, ref BeforeThrowInsertEvent args)
|
||||
{
|
||||
if (!CanInsert(ent, ent, args.ThrownEntity))
|
||||
args.Cancelled = true;
|
||||
}
|
||||
|
||||
public override void DoInsertDisposalUnit(EntityUid uid, EntityUid toInsert, EntityUid user, SharedDisposalUnitComponent? disposal = null)
|
||||
{
|
||||
if (!ResolveDisposals(uid, ref disposal))
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace Content.Server.Forensics
|
||||
{
|
||||
/// <summary>
|
||||
/// This component is for mobs that leave fingerprints.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class FingerprintComponent : Component
|
||||
{
|
||||
[DataField("fingerprint"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public string? Fingerprint;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace Content.Server.Forensics
|
||||
{
|
||||
/// <summary>
|
||||
/// This component stops the entity from leaving finger prints,
|
||||
/// usually so fibres can be left instead.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class FingerprintMaskComponent : Component
|
||||
{}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using Content.Server.Popups;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Forensics;
|
||||
using Content.Shared.Forensics.Components;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Inventory;
|
||||
|
||||
@@ -63,9 +63,10 @@ namespace Content.Server.Forensics
|
||||
ApplyEvidence(uid, args.Other);
|
||||
}
|
||||
|
||||
private void OnFingerprintInit(EntityUid uid, FingerprintComponent component, MapInitEvent args)
|
||||
private void OnFingerprintInit(Entity<FingerprintComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
component.Fingerprint = GenerateFingerprint();
|
||||
ent.Comp.Fingerprint = GenerateFingerprint();
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void OnDNAInit(EntityUid uid, DnaComponent component, MapInitEvent args)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.Antag;
|
||||
using Content.Server.GameTicking.Rules.Components;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Roles;
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Content.Server.Ghost.Roles.Raffles;
|
||||
/// Allows getting a <see cref="IGhostRoleRaffleDecider"/> as prototype.
|
||||
/// </summary>
|
||||
[Prototype("ghostRoleRaffleDecider")]
|
||||
public sealed class GhostRoleRaffleDeciderPrototype : IPrototype
|
||||
public sealed partial class GhostRoleRaffleDeciderPrototype : IPrototype
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[IdDataField]
|
||||
|
||||
@@ -269,6 +269,7 @@ namespace Content.Server.Guardian
|
||||
component.Host,
|
||||
args.DamageDelta * component.DamageShare,
|
||||
origin: args.Origin,
|
||||
ignoreResistances: true,
|
||||
interruptsDoAfters: false);
|
||||
_popupSystem.PopupEntity(Loc.GetString("guardian-entity-taking-damage"), component.Host.Value, component.Host.Value);
|
||||
|
||||
|
||||
@@ -68,8 +68,6 @@ public sealed partial class ImplanterSystem : SharedImplanterSystem
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to implant someone else.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using Content.Shared.Kitchen;
|
||||
|
||||
namespace Content.Server.Kitchen.Components;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,4 +6,9 @@ namespace Content.Server.Kitchen.Components;
|
||||
[RegisterComponent]
|
||||
public sealed partial class ActivelyMicrowavedComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The microwave this entity is actively being microwaved by.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityUid? Microwave;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Part;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Content.Shared.Construction.EntitySystems;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Destructible;
|
||||
@@ -101,6 +102,7 @@ namespace Content.Server.Kitchen.EntitySystems
|
||||
SubscribeLocalEvent<ActiveMicrowaveComponent, EntRemovedFromContainerMessage>(OnActiveMicrowaveRemove);
|
||||
|
||||
SubscribeLocalEvent<ActivelyMicrowavedComponent, OnConstructionTemperatureEvent>(OnConstructionTemp);
|
||||
SubscribeLocalEvent<ActivelyMicrowavedComponent, SolutionRelayEvent<ReactionAttemptEvent>>(OnReactionAttempt);
|
||||
|
||||
SubscribeLocalEvent<FoodRecipeProviderComponent, GetSecretRecipesEvent>(OnGetSecretRecipes);
|
||||
}
|
||||
@@ -126,7 +128,8 @@ namespace Content.Server.Kitchen.EntitySystems
|
||||
|
||||
private void OnActiveMicrowaveInsert(Entity<ActiveMicrowaveComponent> ent, ref EntInsertedIntoContainerMessage args)
|
||||
{
|
||||
AddComp<ActivelyMicrowavedComponent>(args.Entity);
|
||||
var microwavedComp = AddComp<ActivelyMicrowavedComponent>(args.Entity);
|
||||
microwavedComp.Microwave = ent.Owner;
|
||||
}
|
||||
|
||||
private void OnActiveMicrowaveRemove(Entity<ActiveMicrowaveComponent> ent, ref EntRemovedFromContainerMessage args)
|
||||
@@ -134,10 +137,33 @@ namespace Content.Server.Kitchen.EntitySystems
|
||||
EntityManager.RemoveComponentDeferred<ActivelyMicrowavedComponent>(args.Entity);
|
||||
}
|
||||
|
||||
// Stop items from transforming through constructiongraphs while being microwaved.
|
||||
// They might be reserved for a microwave recipe.
|
||||
private void OnConstructionTemp(Entity<ActivelyMicrowavedComponent> ent, ref OnConstructionTemperatureEvent args)
|
||||
{
|
||||
args.Result = HandleResult.False;
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop reagents from reacting if they are currently reserved for a microwave recipe.
|
||||
// For example Egg would cook into EggCooked, causing it to not being removed once we are done microwaving.
|
||||
private void OnReactionAttempt(Entity<ActivelyMicrowavedComponent> ent, ref SolutionRelayEvent<ReactionAttemptEvent> args)
|
||||
{
|
||||
if (!TryComp<ActiveMicrowaveComponent>(ent.Comp.Microwave, out var activeMicrowaveComp))
|
||||
return;
|
||||
|
||||
if (activeMicrowaveComp.PortionedRecipe.Item1 == null) // no recipe selected
|
||||
return;
|
||||
|
||||
var recipeReagents = activeMicrowaveComp.PortionedRecipe.Item1.IngredientsReagents.Keys;
|
||||
|
||||
foreach (var reagent in recipeReagents)
|
||||
{
|
||||
if (args.Event.Reaction.Reactants.ContainsKey(reagent))
|
||||
{
|
||||
args.Event.Cancelled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -176,33 +202,29 @@ namespace Content.Server.Kitchen.EntitySystems
|
||||
// this is spaghetti ngl
|
||||
foreach (var item in component.Storage.ContainedEntities)
|
||||
{
|
||||
if (!TryComp<SolutionContainerManagerComponent>(item, out var solMan))
|
||||
// use the same reagents as when we selected the recipe
|
||||
if (!_solutionContainer.TryGetDrainableSolution(item, out var solutionEntity, out var solution))
|
||||
continue;
|
||||
|
||||
// go over every solution
|
||||
foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((item, solMan)))
|
||||
foreach (var (reagent, _) in recipe.IngredientsReagents)
|
||||
{
|
||||
var solution = soln.Comp.Solution;
|
||||
foreach (var (reagent, _) in recipe.IngredientsReagents)
|
||||
// removed everything
|
||||
if (!totalReagentsToRemove.ContainsKey(reagent))
|
||||
continue;
|
||||
|
||||
var quant = solution.GetTotalPrototypeQuantity(reagent);
|
||||
|
||||
if (quant >= totalReagentsToRemove[reagent])
|
||||
{
|
||||
// removed everything
|
||||
if (!totalReagentsToRemove.ContainsKey(reagent))
|
||||
continue;
|
||||
|
||||
var quant = solution.GetTotalPrototypeQuantity(reagent);
|
||||
|
||||
if (quant >= totalReagentsToRemove[reagent])
|
||||
{
|
||||
quant = totalReagentsToRemove[reagent];
|
||||
totalReagentsToRemove.Remove(reagent);
|
||||
}
|
||||
else
|
||||
{
|
||||
totalReagentsToRemove[reagent] -= quant;
|
||||
}
|
||||
|
||||
_solutionContainer.RemoveReagent(soln, reagent, quant);
|
||||
quant = totalReagentsToRemove[reagent];
|
||||
totalReagentsToRemove.Remove(reagent);
|
||||
}
|
||||
else
|
||||
{
|
||||
totalReagentsToRemove[reagent] -= quant;
|
||||
}
|
||||
|
||||
_solutionContainer.RemoveReagent(solutionEntity.Value, reagent, quant);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,7 +563,8 @@ namespace Content.Server.Kitchen.EntitySystems
|
||||
continue;
|
||||
}
|
||||
|
||||
AddComp<ActivelyMicrowavedComponent>(item);
|
||||
var microwavedComp = AddComp<ActivelyMicrowavedComponent>(item);
|
||||
microwavedComp.Microwave = uid;
|
||||
|
||||
string? solidID = null;
|
||||
int amountToAdd = 1;
|
||||
@@ -560,33 +583,20 @@ namespace Content.Server.Kitchen.EntitySystems
|
||||
}
|
||||
|
||||
if (solidID is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (solidsDict.ContainsKey(solidID))
|
||||
{
|
||||
if (!solidsDict.TryAdd(solidID, amountToAdd))
|
||||
solidsDict[solidID] += amountToAdd;
|
||||
}
|
||||
else
|
||||
{
|
||||
solidsDict.Add(solidID, amountToAdd);
|
||||
}
|
||||
|
||||
if (!TryComp<SolutionContainerManagerComponent>(item, out var solMan))
|
||||
// only use reagents we have access to
|
||||
// you have to break the eggs before we can use them!
|
||||
if (!_solutionContainer.TryGetDrainableSolution(item, out var _, out var solution))
|
||||
continue;
|
||||
|
||||
foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((item, solMan)))
|
||||
foreach (var (reagent, quantity) in solution.Contents)
|
||||
{
|
||||
var solution = soln.Comp.Solution;
|
||||
foreach (var (reagent, quantity) in solution.Contents)
|
||||
{
|
||||
if (reagentDict.ContainsKey(reagent.Prototype))
|
||||
reagentDict[reagent.Prototype] += quantity;
|
||||
else
|
||||
reagentDict.Add(reagent.Prototype, quantity);
|
||||
}
|
||||
if (!reagentDict.TryAdd(reagent.Prototype, quantity))
|
||||
reagentDict[reagent.Prototype] += quantity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
|
||||
|
||||
if (material.StackEntity != null)
|
||||
{
|
||||
if (!_prototypeManager.Index<EntityPrototype>(material.StackEntity).TryGetComponent<PhysicalCompositionComponent>(out var composition))
|
||||
if (!_prototypeManager.Index<EntityPrototype>(material.StackEntity).TryGetComponent<PhysicalCompositionComponent>(out var composition, EntityManager.ComponentFactory))
|
||||
return;
|
||||
|
||||
var volumePerSheet = composition.MaterialComposition.FirstOrDefault(kvp => kvp.Key == msg.Material).Value;
|
||||
@@ -169,7 +169,7 @@ public sealed class MaterialStorageSystem : SharedMaterialStorageSystem
|
||||
return new List<EntityUid>();
|
||||
|
||||
var entProto = _prototypeManager.Index<EntityPrototype>(materialProto.StackEntity);
|
||||
if (!entProto.TryGetComponent<PhysicalCompositionComponent>(out var composition))
|
||||
if (!entProto.TryGetComponent<PhysicalCompositionComponent>(out var composition, EntityManager.ComponentFactory))
|
||||
return new List<EntityUid>();
|
||||
|
||||
var materialPerStack = composition.MaterialComposition[materialProto.ID];
|
||||
|
||||
@@ -31,6 +31,12 @@ namespace Content.Server.Medical
|
||||
[Dependency] private readonly ForensicsSystem _forensics = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstream = default!;
|
||||
|
||||
[ValidatePrototypeId<SoundCollectionPrototype>]
|
||||
private const string VomitCollection = "Vomit";
|
||||
|
||||
private readonly SoundSpecifier _vomitSound = new SoundCollectionSpecifier(VomitCollection,
|
||||
AudioParams.Default.WithVariation(0.2f).WithVolume(-4f));
|
||||
|
||||
/// <summary>
|
||||
/// Make an entity vomit, if they have a stomach.
|
||||
/// </summary>
|
||||
@@ -94,7 +100,7 @@ namespace Content.Server.Medical
|
||||
}
|
||||
|
||||
// Force sound to play as spill doesn't work if solution is empty.
|
||||
_audio.PlayPvs("/Audio/Effects/Fluids/splat.ogg", uid, AudioParams.Default.WithVariation(0.2f).WithVolume(-4f));
|
||||
_audio.PlayPvs(_vomitSound, uid);
|
||||
_popup.PopupEntity(Loc.GetString("disease-vomit", ("person", Identity.Entity(uid, EntityManager))), uid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Content.Server.NPC.HTN;
|
||||
[Prototype("htnCompound")]
|
||||
public sealed partial class HTNCompoundPrototype : IPrototype
|
||||
{
|
||||
[IdDataField] public string ID { get; } = string.Empty;
|
||||
[IdDataField] public string ID { get; private set; } = string.Empty;
|
||||
|
||||
[DataField("branches", required: true)]
|
||||
public List<HTNBranch> Branches = new();
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Content.Server.NPC.Queries.Curves;
|
||||
[Prototype("utilityCurvePreset")]
|
||||
public sealed partial class UtilityCurvePresetPrototype : IPrototype
|
||||
{
|
||||
[IdDataField] public string ID { get; } = string.Empty;
|
||||
[IdDataField] public string ID { get; private set; } = string.Empty;
|
||||
|
||||
[DataField("curve", required: true)] public IUtilityCurve Curve = default!;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Content.Server.Objectives.Components;
|
||||
|
||||
/// <summary>
|
||||
/// A free greentext, that's it.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class FreeObjectiveComponent : Component;
|
||||
20
Content.Server/Objectives/Systems/FreeObjectiveSystem.cs
Normal file
20
Content.Server/Objectives/Systems/FreeObjectiveSystem.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Content.Server.Objectives.Components;
|
||||
using Content.Shared.Objectives.Components;
|
||||
|
||||
namespace Content.Server.Objectives.Systems;
|
||||
|
||||
public sealed class FreeObjectiveSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<FreeObjectiveComponent, ObjectiveGetProgressEvent>(OnGetProgress);
|
||||
}
|
||||
|
||||
// You automatically greentext, there's not much else to it
|
||||
private void OnGetProgress(Entity<FreeObjectiveComponent> ent, ref ObjectiveGetProgressEvent args)
|
||||
{
|
||||
args.Progress = 1f;
|
||||
}
|
||||
}
|
||||
7
Content.Server/Roles/WizardRoleComponent.cs
Normal file
7
Content.Server/Roles/WizardRoleComponent.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Content.Server.Roles;
|
||||
|
||||
/// <summary>
|
||||
/// Mind role to tag entities that they're a Wizard
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class WizardRoleComponent : Component;
|
||||
@@ -354,7 +354,7 @@ public sealed partial class SalvageSystem
|
||||
if (!TryGetSalvagePlacementLocation(magnet, mapId, attachedBounds, bounds!.Value, worldAngle, out var spawnLocation, out var spawnAngle))
|
||||
{
|
||||
Report(magnet.Owner, MagnetChannel, "salvage-system-announcement-spawn-no-debris-available");
|
||||
_mapManager.DeleteMap(salvMapXform.MapID);
|
||||
_mapSystem.DeleteMap(salvMapXform.MapID);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ public sealed partial class SalvageSystem
|
||||
}
|
||||
|
||||
Report(magnet.Owner, MagnetChannel, "salvage-system-announcement-arrived", ("timeLeft", data.Comp.ActiveTime.TotalSeconds));
|
||||
_mapManager.DeleteMap(salvMapXform.MapID);
|
||||
_mapSystem.DeleteMap(salvMapXform.MapID);
|
||||
|
||||
data.Comp.Announced = false;
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ public interface IGridSpawnGroup
|
||||
}
|
||||
|
||||
[DataRecord]
|
||||
public sealed class DungeonSpawnGroup : IGridSpawnGroup
|
||||
public sealed partial class DungeonSpawnGroup : IGridSpawnGroup
|
||||
{
|
||||
/// <summary>
|
||||
/// Prototypes we can choose from to spawn.
|
||||
@@ -97,7 +97,7 @@ public sealed class DungeonSpawnGroup : IGridSpawnGroup
|
||||
}
|
||||
|
||||
[DataRecord]
|
||||
public sealed class GridSpawnGroup : IGridSpawnGroup
|
||||
public sealed partial class GridSpawnGroup : IGridSpawnGroup
|
||||
{
|
||||
public List<ResPath> Paths = new();
|
||||
|
||||
|
||||
@@ -30,8 +30,10 @@ using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.EntitySerialization;
|
||||
using Robust.Shared.EntitySerialization.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
@@ -46,23 +48,23 @@ namespace Content.Server.Shuttles.Systems;
|
||||
/// </summary>
|
||||
public sealed class ArrivalsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IChatManager _chat = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
||||
[Dependency] private readonly IConsoleHost _console = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly IChatManager _chat = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
[Dependency] private readonly ActorSystem _actor = default!;
|
||||
[Dependency] private readonly BiomeSystem _biomes = default!;
|
||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
|
||||
[Dependency] private readonly GameTicker _ticker = default!;
|
||||
[Dependency] private readonly MapLoaderSystem _loader = default!;
|
||||
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly ShuttleSystem _shuttles = default!;
|
||||
[Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
[Dependency] private readonly ActorSystem _actor = default!;
|
||||
|
||||
private EntityQuery<PendingClockInComponent> _pendingQuery;
|
||||
private EntityQuery<ArrivalsBlacklistComponent> _blacklistQuery;
|
||||
@@ -515,31 +517,31 @@ public sealed class ArrivalsSystem : EntitySystem
|
||||
private void SetupArrivalsStation()
|
||||
{
|
||||
var path = new ResPath(_cfgManager.GetCVar(CCVars.ArrivalsMap));
|
||||
if (!_loader.TryLoadMap(path, out var map, out var grids))
|
||||
_mapSystem.CreateMap(out var mapId, runMapInit: false);
|
||||
var mapUid = _mapSystem.GetMap(mapId);
|
||||
|
||||
if (!_loader.TryLoadGrid(mapId, path, out var grid))
|
||||
return;
|
||||
|
||||
_metaData.SetEntityName(map.Value, Loc.GetString("map-name-terminal"));
|
||||
_metaData.SetEntityName(mapUid, Loc.GetString("map-name-terminal"));
|
||||
|
||||
foreach (var id in grids)
|
||||
{
|
||||
EnsureComp<ArrivalsSourceComponent>(id);
|
||||
EnsureComp<ProtectedGridComponent>(id);
|
||||
EnsureComp<PreventPilotComponent>(id);
|
||||
}
|
||||
EnsureComp<ArrivalsSourceComponent>(grid.Value);
|
||||
EnsureComp<ProtectedGridComponent>(grid.Value);
|
||||
EnsureComp<PreventPilotComponent>(grid.Value);
|
||||
|
||||
// Setup planet arrivals if relevant
|
||||
if (_cfgManager.GetCVar(CCVars.ArrivalsPlanet))
|
||||
{
|
||||
var template = _random.Pick(_arrivalsBiomeOptions);
|
||||
_biomes.EnsurePlanet(map.Value, _protoManager.Index(template));
|
||||
_biomes.EnsurePlanet(mapUid, _protoManager.Index(template));
|
||||
var restricted = new RestrictedRangeComponent
|
||||
{
|
||||
Range = 32f
|
||||
};
|
||||
AddComp(map.Value, restricted);
|
||||
AddComp(mapUid, restricted);
|
||||
}
|
||||
|
||||
_mapSystem.InitializeMap(map.Value.Comp.MapId);
|
||||
_mapSystem.InitializeMap(mapId);
|
||||
|
||||
// Handle roundstart stations.
|
||||
var query = AllEntityQuery<StationArrivalsComponent>();
|
||||
|
||||
@@ -200,11 +200,11 @@ public sealed class IonStormSystem : EntitySystem
|
||||
// i dont think theres a way to do this in fluent
|
||||
var (who, plural) = _robustRandom.Next(0, 5) switch
|
||||
{
|
||||
0 => (Loc.GetString("ion-storm-you"), false),
|
||||
1 => (Loc.GetString("ion-storm-the-station"), true),
|
||||
2 => (Loc.GetString("ion-storm-the-crew"), true),
|
||||
3 => (Loc.GetString("ion-storm-the-job", ("job", crew2)), false),
|
||||
_ => (area, true) // THE SINGULARITY REQUIRES THE HAPPY CLOWNS
|
||||
0 => (Loc.GetString("ion-storm-you"), true),
|
||||
1 => (Loc.GetString("ion-storm-the-station"), false),
|
||||
2 => (Loc.GetString("ion-storm-the-crew"), false),
|
||||
3 => (Loc.GetString("ion-storm-the-job", ("job", crew2)), true),
|
||||
_ => (area, false) // THE SINGULARITY REQUIRES THE HAPPY CLOWNS
|
||||
};
|
||||
var jobChange = _robustRandom.Next(0, 3) switch
|
||||
{
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
using System.Threading;
|
||||
using Content.Server.StationEvents.Events;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.StationEvents.Components;
|
||||
|
||||
[RegisterComponent, Access(typeof(PowerGridCheckRule))]
|
||||
public sealed partial class PowerGridCheckRuleComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Default sound of the announcement when power is back on.
|
||||
/// </summary>
|
||||
private static readonly ProtoId<SoundCollectionPrototype> DefaultPowerOn = new("PowerOn");
|
||||
|
||||
/// <summary>
|
||||
/// Sound of the announcement to play when power is back on.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public SoundSpecifier PowerOnSound = new SoundCollectionSpecifier(DefaultPowerOn, AudioParams.Default.WithVolume(-4f));
|
||||
|
||||
public CancellationTokenSource? AnnounceCancelToken;
|
||||
|
||||
public EntityUid AffectedStation;
|
||||
|
||||
@@ -210,7 +210,7 @@ public sealed class EventManagerSystem : EntitySystem
|
||||
if (prototype.Abstract)
|
||||
continue;
|
||||
|
||||
if (!prototype.TryGetComponent<StationEventComponent>(out var stationEvent))
|
||||
if (!prototype.TryGetComponent<StationEventComponent>(out var stationEvent, EntityManager.ComponentFactory))
|
||||
continue;
|
||||
|
||||
allEvents.Add(prototype, stationEvent);
|
||||
|
||||
@@ -26,7 +26,8 @@ public sealed class ImmovableRodRule : StationEventSystem<ImmovableRodRuleCompon
|
||||
|
||||
var proto = _prototypeManager.Index<EntityPrototype>(protoName);
|
||||
|
||||
if (proto.TryGetComponent<ImmovableRodComponent>(out var rod) && proto.TryGetComponent<TimedDespawnComponent>(out var despawn))
|
||||
if (proto.TryGetComponent<ImmovableRodComponent>(out var rod, EntityManager.ComponentFactory) &&
|
||||
proto.TryGetComponent<TimedDespawnComponent>(out var despawn, EntityManager.ComponentFactory))
|
||||
{
|
||||
if (!TryFindRandomTile(out _, out _, out _, out var targetCoords))
|
||||
return;
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Content.Server.StationEvents.Events
|
||||
component.AnnounceCancelToken = new CancellationTokenSource();
|
||||
Timer.Spawn(3000, () =>
|
||||
{
|
||||
Audio.PlayGlobal("/Audio/Announcements/power_on.ogg", Filter.Broadcast(), true, AudioParams.Default.WithVolume(-4f));
|
||||
Audio.PlayGlobal(component.PowerOnSound, Filter.Broadcast(), true);
|
||||
}, component.AnnounceCancelToken.Token);
|
||||
component.Unpowered.Clear();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using Content.Shared.Roles;
|
||||
using Content.Shared.StationRecords;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.StationRecords.Systems;
|
||||
|
||||
@@ -39,6 +40,7 @@ public sealed class StationRecordsSystem : SharedStationRecordsSystem
|
||||
[Dependency] private readonly StationRecordKeyStorageSystem _keyStorage = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IdCardSystem _idCard = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -232,6 +234,28 @@ public sealed class StationRecordsSystem : SharedStationRecordsSystem
|
||||
return records.Records.TryGetRecordEntry(key.Id, out entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random record from the station's record entries.
|
||||
/// </summary>
|
||||
/// <param name="ent">The EntityId of the station from which you want to get the record.</param>
|
||||
/// <param name="entry">The resulting entry.</param>
|
||||
/// <typeparam name="T">Type to get from the record set.</typeparam>
|
||||
/// <returns>True if a record was obtained. False otherwise.</returns>
|
||||
public bool TryGetRandomRecord<T>(Entity<StationRecordsComponent?> ent, [NotNullWhen(true)] out T? entry)
|
||||
{
|
||||
entry = default;
|
||||
|
||||
if (!Resolve(ent.Owner, ref ent.Comp))
|
||||
return false;
|
||||
|
||||
if (ent.Comp.Records.Keys.Count == 0)
|
||||
return false;
|
||||
|
||||
var key = _random.Pick(ent.Comp.Records.Keys);
|
||||
|
||||
return ent.Comp.Records.TryGetRecordEntry(key, out entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an id if a record with the same name exists.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Store;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -117,7 +118,7 @@ public sealed partial class StoreSystem
|
||||
|
||||
if (listing.Conditions != null)
|
||||
{
|
||||
var args = new ListingConditionArgs(buyer, storeEntity, listing, EntityManager);
|
||||
var args = new ListingConditionArgs(GetBuyerMind(buyer), storeEntity, listing, EntityManager);
|
||||
var conditionsMet = true;
|
||||
|
||||
foreach (var condition in listing.Conditions)
|
||||
@@ -137,6 +138,19 @@ public sealed partial class StoreSystem
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the entity's mind entity, if it has one, to be used for listing conditions.
|
||||
/// If it doesn't have one, or is a mind entity already, it returns itself.
|
||||
/// </summary>
|
||||
/// <param name="buyer">The buying entity.</param>
|
||||
public EntityUid GetBuyerMind(EntityUid buyer)
|
||||
{
|
||||
if (!HasComp<MindComponent>(buyer) && _mind.TryGetMind(buyer, out var buyerMind, out var _))
|
||||
return buyerMind;
|
||||
|
||||
return buyer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a listing appears in a list of given categories
|
||||
/// </summary>
|
||||
|
||||
@@ -146,7 +146,7 @@ public sealed partial class StoreSystem
|
||||
//condition checking because why not
|
||||
if (listing.Conditions != null)
|
||||
{
|
||||
var args = new ListingConditionArgs(component.AccountOwner ?? buyer, uid, listing, EntityManager);
|
||||
var args = new ListingConditionArgs(component.AccountOwner ?? GetBuyerMind(buyer), uid, listing, EntityManager);
|
||||
var conditionsMet = listing.Conditions.All(condition => condition.Condition(args));
|
||||
|
||||
if (!conditionsMet)
|
||||
|
||||
@@ -20,7 +20,7 @@ public sealed partial class WireLayoutPrototype : IPrototype, IInheritingPrototy
|
||||
public string[]? Parents { get; private set; }
|
||||
|
||||
[AbstractDataField]
|
||||
public bool Abstract { get; }
|
||||
public bool Abstract { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many wires in this layout will do
|
||||
|
||||
@@ -14,12 +14,12 @@ public sealed partial class BiomePrototype : IPrototype, IInheritingPrototype
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<EntityPrototype>))]
|
||||
public string[]? Parents { get; }
|
||||
public string[]? Parents { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[NeverPushInheritance]
|
||||
[AbstractDataField]
|
||||
public bool Abstract { get; }
|
||||
public bool Abstract { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[IdDataField]
|
||||
@@ -42,7 +42,7 @@ public sealed partial class BiomePrototype : IPrototype, IInheritingPrototype
|
||||
/// </summary>
|
||||
[DataField("chunkComponents")]
|
||||
[AlwaysPushInheritance]
|
||||
public ComponentRegistry ChunkComponents { get; } = new();
|
||||
public ComponentRegistry ChunkComponents = new();
|
||||
|
||||
//TODO: Get someone to make this a method on componentregistry that does it Correctly.
|
||||
/// <summary>
|
||||
|
||||
@@ -84,12 +84,12 @@ public sealed partial class NoiseChannelPrototype : NoiseChannelConfig, IPrototy
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<EntityPrototype>))]
|
||||
public string[]? Parents { get; }
|
||||
public string[]? Parents { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[NeverPushInheritance]
|
||||
[AbstractDataField]
|
||||
public bool Abstract { get; }
|
||||
public bool Abstract { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[IdDataField]
|
||||
|
||||
55
Content.Server/_CP14/Cargo/CP14CargoSystem.Portals.cs
Normal file
55
Content.Server/_CP14/Cargo/CP14CargoSystem.Portals.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Content.Server.Storage.Components;
|
||||
using Content.Shared._CP14.Cargo;
|
||||
using Content.Shared.Storage.Components;
|
||||
|
||||
namespace Content.Server._CP14.Cargo;
|
||||
|
||||
public sealed partial class CP14CargoSystem
|
||||
{
|
||||
private void InitializePortals()
|
||||
{
|
||||
SubscribeLocalEvent<CP14TradingPortalComponent, MapInitEvent>(OnTradePortalMapInit);
|
||||
|
||||
SubscribeLocalEvent<CP14TradingPortalComponent, StorageAfterCloseEvent>(OnTradePortalClose);
|
||||
SubscribeLocalEvent<CP14TradingPortalComponent, StorageAfterOpenEvent>(OnTradePortalOpen);
|
||||
}
|
||||
|
||||
private void UpdatePortals(float frameTime)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CP14TradingPortalComponent, EntityStorageComponent>();
|
||||
while (query.MoveNext(out var ent, out var portal, out var storage))
|
||||
{
|
||||
if (portal.ProcessFinishTime == TimeSpan.Zero || portal.ProcessFinishTime >= _timing.CurTime)
|
||||
continue;
|
||||
|
||||
portal.ProcessFinishTime = TimeSpan.Zero;
|
||||
|
||||
SellingThings((ent, portal), storage);
|
||||
TopUpBalance((ent, portal), storage);
|
||||
BuyThings((ent, portal), storage);
|
||||
CashOut((ent, portal), storage);
|
||||
ThrowAllItems((ent, portal), storage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTradePortalMapInit(Entity<CP14TradingPortalComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
AddRoundstartTradingPositions(ent);
|
||||
UpdateStaticPositions(ent);
|
||||
|
||||
ent.Comp.CurrentSpecialBuyPositions.Clear();
|
||||
ent.Comp.CurrentSpecialSellPositions.Clear();
|
||||
AddRandomBuySpecialPosition(ent, ent.Comp.SpecialBuyPositionCount);
|
||||
AddRandomSellSpecialPosition(ent, ent.Comp.SpecialSellPositionCount);
|
||||
}
|
||||
|
||||
private void OnTradePortalClose(Entity<CP14TradingPortalComponent> ent, ref StorageAfterCloseEvent args)
|
||||
{
|
||||
ent.Comp.ProcessFinishTime = _timing.CurTime + ent.Comp.Delay;
|
||||
}
|
||||
|
||||
private void OnTradePortalOpen(Entity<CP14TradingPortalComponent> ent, ref StorageAfterOpenEvent args)
|
||||
{
|
||||
ent.Comp.ProcessFinishTime = TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
using System.Numerics;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Server.Shuttles.Events;
|
||||
using Content.Shared._CP14.Cargo;
|
||||
using Content.Shared.Gravity;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._CP14.Cargo;
|
||||
|
||||
public sealed partial class CP14CargoSystem
|
||||
{
|
||||
private void InitializeShuttle()
|
||||
{
|
||||
SubscribeLocalEvent<CP14TravelingStoreShipComponent, FTLCompletedEvent>(OnFTLCompleted);
|
||||
SubscribeLocalEvent<CP14TravelingStoreShipComponent, MapInitEvent>(OnMapInit);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<CP14TravelingStoreShipComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
//TODO: This is shitcode! Because shouldnt related to traveling ship
|
||||
EnsureComp<GravityComponent>(ent, out var gravity);
|
||||
gravity.Enabled = true;
|
||||
gravity.Inherent = true;
|
||||
}
|
||||
|
||||
private void UpdateShuttle()
|
||||
{
|
||||
var query = EntityQueryEnumerator<CP14StationTravelingStoreShipTargetComponent>();
|
||||
while (query.MoveNext(out var uid, out var ship))
|
||||
{
|
||||
if (_timing.CurTime < ship.NextTravelTime || ship.NextTravelTime == TimeSpan.Zero)
|
||||
continue;
|
||||
|
||||
if (ship.Shuttle is null || ship.TradePostMap is null)
|
||||
continue;
|
||||
|
||||
if (Transform(ship.Shuttle.Value).MapUid == Transform(ship.TradePostMap.Value).MapUid)
|
||||
{
|
||||
// if landed on trade post
|
||||
ship.NextTravelTime = _timing.CurTime + ship.StationWaitTime;
|
||||
SendShuttleToStation(ship.Shuttle.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if landed on station
|
||||
ship.NextTravelTime = _timing.CurTime + ship.TradePostWaitTime;
|
||||
SendShuttleToTradepost(ship.Shuttle.Value, ship.TradePostMap.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SendShuttleToStation(EntityUid shuttle, float startupTime = 0f)
|
||||
{
|
||||
var targetPoints = new List<EntityUid>();
|
||||
var targetEnumerator =
|
||||
EntityQueryEnumerator<CP14TravelingStoreShipFTLTargetComponent,
|
||||
TransformComponent>(); //TODO - different method position location
|
||||
while (targetEnumerator.MoveNext(out var uid, out _, out _))
|
||||
{
|
||||
targetPoints.Add(uid);
|
||||
}
|
||||
|
||||
if (targetPoints.Count == 0)
|
||||
return;
|
||||
|
||||
var target = _random.Pick(targetPoints);
|
||||
var targetXform = Transform(target);
|
||||
|
||||
var shuttleComp = Comp<ShuttleComponent>(shuttle);
|
||||
|
||||
_shuttles.FTLToCoordinates(shuttle,
|
||||
shuttleComp,
|
||||
targetXform.Coordinates,
|
||||
targetXform.LocalRotation,
|
||||
hyperspaceTime: 20f,
|
||||
startupTime: startupTime);
|
||||
}
|
||||
|
||||
private void SendShuttleToTradepost(EntityUid shuttle, EntityUid tradePostMap)
|
||||
{
|
||||
var shuttleComp = Comp<ShuttleComponent>(shuttle);
|
||||
|
||||
_shuttles.FTLToCoordinates(shuttle,
|
||||
shuttleComp,
|
||||
new EntityCoordinates(tradePostMap, Vector2.Zero),
|
||||
Angle.Zero,
|
||||
startupTime: 10f,
|
||||
hyperspaceTime: 20f);
|
||||
}
|
||||
|
||||
private void OnFTLCompleted(Entity<CP14TravelingStoreShipComponent> ent, ref FTLCompletedEvent args)
|
||||
{
|
||||
if (!TryComp<CP14StationTravelingStoreShipTargetComponent>(ent.Comp.Station, out var station))
|
||||
return;
|
||||
|
||||
if (station.TradePostMap is not null &&
|
||||
Transform(ent).MapUid == Transform(station.TradePostMap.Value).MapUid) //Landed on tradepost
|
||||
{
|
||||
station.OnStation = false;
|
||||
|
||||
SellingThings((ent.Comp.Station, station)); // +balance
|
||||
TopUpBalance((ent.Comp.Station, station)); //+balance
|
||||
BuyToQueue((ent.Comp.Station, station)); //-balance +buyQueue
|
||||
TrySpawnBuyedThings((ent.Comp.Station, station));
|
||||
UpdateStorePositions((ent.Comp.Station, station));
|
||||
}
|
||||
else //Landed on station
|
||||
{
|
||||
station.OnStation = true;
|
||||
|
||||
CashOut((ent.Comp.Station, station));
|
||||
station.Balance = 0;
|
||||
}
|
||||
|
||||
UpdateAllStores();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user