mirror of
https://github.com/wega-team/ss14-wega.git
synced 2026-02-14 19:30:01 +01:00
Chemmaster Pill Source (#40121)
* Buttons and basic internal data * The buttons DO something * it works?!! * I hate predictions * 5000 monkeys on typewritters * who let the monkeys code? * Localizations * waiter, more commits please * Not going insane (this is a lie) * last one I SWEAR * Some improvements ported from Moff * clean it up a little * one more cleanup * The chemmaster is not a mime * Fix my mistakes + address the other review * Point to what chemmaster is broken, and why it's broken * ChemMasterComponent changes * Margin for packaging source --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
This commit is contained in:
@@ -48,6 +48,10 @@ namespace Content.Client.Chemistry.UI
|
||||
(uint) _window.BottleDosage.Value, _window.LabelLine));
|
||||
_window.BufferSortButton.OnPressed += _ => SendMessage(
|
||||
new ChemMasterSortingTypeCycleMessage());
|
||||
_window.OutputBufferDraw.OnPressed += _ => SendMessage(
|
||||
new ChemMasterOutputDrawSourceMessage(ChemMasterDrawSource.Internal));
|
||||
_window.OutputBeakerDraw.OnPressed += _ => SendMessage(
|
||||
new ChemMasterOutputDrawSourceMessage(ChemMasterDrawSource.External));
|
||||
|
||||
for (uint i = 0; i < _window.PillTypeButtons.Length; i++)
|
||||
{
|
||||
|
||||
@@ -79,10 +79,13 @@
|
||||
|
||||
<!-- Packaging -->
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Text="{Loc 'chem-master-window-packaging-text'}" />
|
||||
<Label Text="{Loc 'chem-master-output-source'}" StyleClasses="LabelSecondaryColor" Margin="0 0 5 0"/>
|
||||
<Button MinSize="80 0" Name="OutputBufferDraw" Access="Public" Text="{Loc 'chem-master-output-buffer-draw'}" ToggleMode="True" StyleClasses="OpenRight" />
|
||||
<Button MinSize="80 0" Name="OutputBeakerDraw" Access="Public" Text="{Loc 'chem-master-output-beaker-draw'}" ToggleMode="True" StyleClasses="OpenLeft" />
|
||||
<Control HorizontalExpand="True"/>
|
||||
<Label Text="{Loc 'chem-master-window-buffer-label'}" />
|
||||
<Label Name="BufferCurrentVolume" StyleClasses="LabelWeak" />
|
||||
<!-- Output Draw Source -->
|
||||
<Label Name="DrawSource"/>
|
||||
<Label Name="BufferCurrentVolume" StyleClasses="LabelSecondaryColor" />
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Wrap the packaging info-->
|
||||
|
||||
@@ -150,7 +150,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";
|
||||
switch (castState.DrawSource)
|
||||
{
|
||||
case ChemMasterDrawSource.Internal:
|
||||
SetBufferText(castState.BufferCurrentVolume, "chem-master-output-buffer-draw");
|
||||
break;
|
||||
case ChemMasterDrawSource.External:
|
||||
SetBufferText(castState.InputContainerInfo?.CurrentVolume, "chem-master-output-beaker-draw");
|
||||
break;
|
||||
default:
|
||||
throw new($"Chemmaster {castState.OutputContainerInfo} draw source is not set");
|
||||
}
|
||||
|
||||
InputEjectButton.Disabled = castState.InputContainerInfo is null;
|
||||
OutputEjectButton.Disabled = castState.OutputContainerInfo is null;
|
||||
@@ -168,9 +178,14 @@ namespace Content.Client.Chemistry.UI
|
||||
var holdsReagents = output?.Reagents != null;
|
||||
var pillNumberMax = holdsReagents ? 0 : remainingCapacity;
|
||||
var bottleAmountMax = holdsReagents ? remainingCapacity : 0;
|
||||
var bufferVolume = castState.BufferCurrentVolume?.Int() ?? 0;
|
||||
var outputVolume = castState.DrawSource switch
|
||||
{
|
||||
ChemMasterDrawSource.Internal => castState.BufferCurrentVolume?.Int() ?? 0,
|
||||
ChemMasterDrawSource.External => castState.InputContainerInfo?.CurrentVolume.Int() ?? 0,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
PillDosage.Value = (int)Math.Min(bufferVolume, castState.PillDosageLimit);
|
||||
PillDosage.Value = (int)Math.Min(outputVolume, castState.PillDosageLimit);
|
||||
|
||||
PillTypeButtons[castState.SelectedPillType].Pressed = true;
|
||||
|
||||
@@ -186,25 +201,35 @@ namespace Content.Client.Chemistry.UI
|
||||
// Avoid division by zero
|
||||
if (PillDosage.Value > 0)
|
||||
{
|
||||
PillNumber.Value = Math.Min(bufferVolume / PillDosage.Value, pillNumberMax);
|
||||
PillNumber.Value = Math.Min(outputVolume / PillDosage.Value, pillNumberMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
PillNumber.Value = 0;
|
||||
}
|
||||
|
||||
BottleDosage.Value = Math.Min(bottleAmountMax, bufferVolume);
|
||||
BottleDosage.Value = Math.Min(bottleAmountMax, outputVolume);
|
||||
}
|
||||
/// <summary>
|
||||
/// Generate a product label based on reagents in the buffer.
|
||||
/// Generate a product label based on reagents in the buffer or beaker.
|
||||
/// </summary>
|
||||
/// <param name="state">State data sent by the server.</param>
|
||||
private string GenerateLabel(ChemMasterBoundUserInterfaceState state)
|
||||
{
|
||||
if (state.BufferCurrentVolume == 0)
|
||||
if (
|
||||
state.BufferCurrentVolume == 0 && state.DrawSource == ChemMasterDrawSource.Internal ||
|
||||
state.InputContainerInfo?.CurrentVolume == 0 && state.DrawSource == ChemMasterDrawSource.External ||
|
||||
state.InputContainerInfo?.Reagents == null
|
||||
)
|
||||
return "";
|
||||
|
||||
var reagent = state.BufferReagents.OrderBy(r => r.Quantity).First().Reagent;
|
||||
var reagent = (state.DrawSource switch
|
||||
{
|
||||
ChemMasterDrawSource.Internal => state.BufferReagents,
|
||||
ChemMasterDrawSource.External => state.InputContainerInfo.Reagents ?? [],
|
||||
_ => throw new($"Chemmaster {state.OutputContainerInfo} draw source is not set"),
|
||||
}).MinBy(r => r.Quantity)
|
||||
.Reagent;
|
||||
_prototypeManager.TryIndex(reagent.Prototype, out ReagentPrototype? proto);
|
||||
return proto?.LocalizedName ?? "";
|
||||
}
|
||||
@@ -233,6 +258,8 @@ namespace Content.Client.Chemistry.UI
|
||||
_ => Loc.GetString("chem-master-window-sort-type-none")
|
||||
};
|
||||
|
||||
OutputBufferDraw.Pressed = state.DrawSource == ChemMasterDrawSource.Internal;
|
||||
OutputBeakerDraw.Pressed = state.DrawSource == ChemMasterDrawSource.External;
|
||||
|
||||
if (!state.BufferReagents.Any())
|
||||
{
|
||||
@@ -414,6 +441,12 @@ namespace Content.Client.Chemistry.UI
|
||||
get => LabelLineEdit.Text;
|
||||
set => LabelLineEdit.Text = value;
|
||||
}
|
||||
|
||||
private void SetBufferText(FixedPoint2? volume, string text)
|
||||
{
|
||||
BufferCurrentVolume.Text = $" {volume ?? FixedPoint2.Zero}u";
|
||||
DrawSource.Text = Loc.GetString(text);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ReagentButton : Button
|
||||
|
||||
@@ -26,5 +26,11 @@ namespace Content.Server.Chemistry.Components
|
||||
|
||||
[DataField("clickSound"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// Which source the chem master should draw from when making pills/bottles.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ChemMasterDrawSource DrawSource = ChemMasterDrawSource.Internal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
SubscribeLocalEvent<ChemMasterComponent, ChemMasterReagentAmountButtonMessage>(OnReagentButtonMessage);
|
||||
SubscribeLocalEvent<ChemMasterComponent, ChemMasterCreatePillsMessage>(OnCreatePillsMessage);
|
||||
SubscribeLocalEvent<ChemMasterComponent, ChemMasterOutputToBottleMessage>(OnOutputToBottleMessage);
|
||||
SubscribeLocalEvent<ChemMasterComponent, ChemMasterOutputDrawSourceMessage>(OnSetDrawSourceMessage);
|
||||
}
|
||||
|
||||
private void SubscribeUpdateUiState<T>(Entity<ChemMasterComponent> ent, ref T ev)
|
||||
@@ -77,7 +78,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
|
||||
var state = new ChemMasterBoundUserInterfaceState(
|
||||
chemMaster.Mode, chemMaster.SortingType, BuildInputContainerInfo(inputContainer), BuildOutputContainerInfo(outputContainer),
|
||||
bufferReagents, bufferCurrentVolume, chemMaster.PillType, chemMaster.PillDosageLimit, updateLabel);
|
||||
bufferReagents, bufferCurrentVolume, chemMaster.PillType, chemMaster.PillDosageLimit, updateLabel, chemMaster.DrawSource);
|
||||
|
||||
_userInterfaceSystem.SetUiState(owner, ChemMasterUiKey.Key, state);
|
||||
}
|
||||
@@ -135,6 +136,17 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
ClickSound(chemMaster);
|
||||
}
|
||||
|
||||
private void OnSetDrawSourceMessage(Entity<ChemMasterComponent> chemMaster, ref ChemMasterOutputDrawSourceMessage message)
|
||||
{
|
||||
//Ensure draw source is valid, either from the internal buffer or the inserted beaker
|
||||
if (!Enum.IsDefined(message.DrawSource))
|
||||
return;
|
||||
|
||||
chemMaster.Comp.DrawSource = message.DrawSource;
|
||||
UpdateUiState(chemMaster);
|
||||
ClickSound(chemMaster);
|
||||
}
|
||||
|
||||
private void TransferReagents(Entity<ChemMasterComponent> chemMaster, ReagentId id, FixedPoint2 amount, bool fromBuffer)
|
||||
{
|
||||
var container = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.InputSlotName);
|
||||
@@ -208,9 +220,9 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return;
|
||||
|
||||
var needed = message.Dosage * message.Number;
|
||||
if (!WithdrawFromBuffer(chemMaster, needed, user, out var withdrawal))
|
||||
return;
|
||||
|
||||
if (!WithdrawFromSource(chemMaster, needed, user, out var withdrawal))
|
||||
return;
|
||||
_labelSystem.Label(container, message.Label);
|
||||
|
||||
for (var i = 0; i < message.Number; i++)
|
||||
@@ -219,7 +231,10 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
_storageSystem.Insert(container, item, out _, user: user, storage);
|
||||
_labelSystem.Label(item, message.Label);
|
||||
|
||||
_solutionContainerSystem.EnsureSolutionEntity(item, SharedChemMaster.PillSolutionName,out var itemSolution ,message.Dosage);
|
||||
_solutionContainerSystem.EnsureSolutionEntity(item,
|
||||
SharedChemMaster.PillSolutionName,
|
||||
out var itemSolution,
|
||||
message.Dosage);
|
||||
if (!itemSolution.HasValue)
|
||||
return;
|
||||
|
||||
@@ -256,7 +271,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
if (message.Label.Length > SharedChemMaster.LabelMaxLength)
|
||||
return;
|
||||
|
||||
if (!WithdrawFromBuffer(chemMaster, message.Dosage, user, out var withdrawal))
|
||||
if (!WithdrawFromSource(chemMaster, message.Dosage, user, out var withdrawal))
|
||||
return;
|
||||
|
||||
_labelSystem.Label(container, message.Label);
|
||||
@@ -270,34 +285,77 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
ClickSound(chemMaster);
|
||||
}
|
||||
|
||||
private bool WithdrawFromBuffer(
|
||||
private bool WithdrawFromSource(
|
||||
Entity<ChemMasterComponent> chemMaster,
|
||||
FixedPoint2 neededVolume, EntityUid? user,
|
||||
FixedPoint2 neededVolume,
|
||||
EntityUid? user,
|
||||
[NotNullWhen(returnValue: true)] out Solution? outputSolution)
|
||||
{
|
||||
outputSolution = null;
|
||||
|
||||
if (!_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var solution))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Solution? solution;
|
||||
Entity<SolutionComponent>? soln = null;
|
||||
|
||||
if (solution.Volume == 0)
|
||||
switch (chemMaster.Comp.DrawSource)
|
||||
{
|
||||
if (user.HasValue)
|
||||
_popupSystem.PopupCursor(Loc.GetString("chem-master-window-buffer-empty-text"), user.Value);
|
||||
return false;
|
||||
}
|
||||
case ChemMasterDrawSource.Internal:
|
||||
if (!_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out solution))
|
||||
return false;
|
||||
|
||||
// ReSharper disable once InvertIf
|
||||
if (neededVolume > solution.Volume)
|
||||
{
|
||||
if (user.HasValue)
|
||||
_popupSystem.PopupCursor(Loc.GetString("chem-master-window-buffer-low-text"), user.Value);
|
||||
return false;
|
||||
if (solution.Volume == 0)
|
||||
{
|
||||
if (user is { } uid)
|
||||
_popupSystem.PopupCursor(Loc.GetString("chem-master-window-buffer-empty-text"), uid);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (neededVolume > solution.Volume)
|
||||
{
|
||||
if (user is { } uid)
|
||||
_popupSystem.PopupCursor(Loc.GetString("chem-master-window-buffer-low-text"), uid);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ChemMasterDrawSource.External:
|
||||
if (_itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.InputSlotName) is not {} container)
|
||||
{
|
||||
if (user.HasValue)
|
||||
_popupSystem.PopupCursor(Loc.GetString("chem-master-window-no-beaker-text"), user.Value);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_solutionContainerSystem.TryGetFitsInDispenser(container, out soln, out solution))
|
||||
return false;
|
||||
|
||||
if (solution.Volume == 0)
|
||||
{
|
||||
if (user is { } uid)
|
||||
_popupSystem.PopupCursor(Loc.GetString("chem-master-window-beaker-empty-text"), uid);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (neededVolume > solution.Volume)
|
||||
{
|
||||
if (user is { } uid)
|
||||
_popupSystem.PopupCursor(Loc.GetString("chem-master-window-beaker-low-text"), uid);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
outputSolution = solution.SplitSolution(neededVolume);
|
||||
|
||||
if (soln.HasValue)
|
||||
_solutionContainerSystem.UpdateChemicals(soln.Value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,12 @@ namespace Content.Shared.Chemistry
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ChemMasterOutputDrawSourceMessage(ChemMasterDrawSource drawSource) : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly ChemMasterDrawSource DrawSource = drawSource;
|
||||
}
|
||||
|
||||
public enum ChemMasterMode
|
||||
{
|
||||
Transfer,
|
||||
@@ -115,6 +121,12 @@ namespace Content.Shared.Chemistry
|
||||
All,
|
||||
}
|
||||
|
||||
public enum ChemMasterDrawSource
|
||||
{
|
||||
Internal,
|
||||
External,
|
||||
}
|
||||
|
||||
public static class ChemMasterReagentAmountToFixedPoint
|
||||
{
|
||||
public static FixedPoint2 GetFixedPoint(this ChemMasterReagentAmount amount)
|
||||
@@ -184,10 +196,12 @@ namespace Content.Shared.Chemistry
|
||||
|
||||
public readonly bool UpdateLabel;
|
||||
|
||||
public readonly ChemMasterDrawSource DrawSource;
|
||||
|
||||
public ChemMasterBoundUserInterfaceState(
|
||||
ChemMasterMode mode, ChemMasterSortingType sortingType, ContainerInfo? inputContainerInfo, ContainerInfo? outputContainerInfo,
|
||||
IReadOnlyList<ReagentQuantity> bufferReagents, FixedPoint2 bufferCurrentVolume,
|
||||
uint selectedPillType, uint pillDosageLimit, bool updateLabel)
|
||||
uint selectedPillType, uint pillDosageLimit, bool updateLabel, ChemMasterDrawSource drawSource)
|
||||
{
|
||||
InputContainerInfo = inputContainerInfo;
|
||||
OutputContainerInfo = outputContainerInfo;
|
||||
@@ -198,6 +212,7 @@ namespace Content.Shared.Chemistry
|
||||
SelectedPillType = selectedPillType;
|
||||
PillDosageLimit = pillDosageLimit;
|
||||
UpdateLabel = updateLabel;
|
||||
DrawSource = drawSource;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,3 +33,10 @@ chem-master-window-sort-type-none = Sort by: Oldest First
|
||||
chem-master-window-sort-type-alphabetical = Sort by: Alphabetical
|
||||
chem-master-window-sort-type-quantity = Sort by: Quantity
|
||||
chem-master-window-sort-type-latest = Sort by: Recent First
|
||||
chem-master-output-buffer-draw = Buffer
|
||||
chem-master-output-beaker-draw = Beaker
|
||||
chem-master-window-no-beaker-text = No beaker loaded
|
||||
chem-master-window-beaker-empty-text = Beaker Empty
|
||||
chem-master-window-beaker-low-text = Not enough solution in beaker
|
||||
chem-master-output-source = Packaging source:
|
||||
chem-master-no-source = No Source
|
||||
|
||||
Reference in New Issue
Block a user