reagent grinder machine upgrade (#12422)

* reagent grinder machine upgrade

* grinder storage upgrades
This commit is contained in:
Nemanja
2022-11-08 15:15:49 -05:00
committed by GitHub
parent e9ebba33e8
commit bd77f5cced
5 changed files with 73 additions and 22 deletions

View File

@@ -1,6 +1,8 @@
using Content.Shared.Kitchen; using Content.Shared.Kitchen;
using Content.Server.Kitchen.EntitySystems; using Content.Server.Kitchen.EntitySystems;
using Content.Shared.Construction.Prototypes;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Kitchen.Components namespace Content.Server.Kitchen.Components
{ {
@@ -13,13 +15,30 @@ namespace Content.Server.Kitchen.Components
[Access(typeof(ReagentGrinderSystem)), RegisterComponent] [Access(typeof(ReagentGrinderSystem)), RegisterComponent]
public sealed class ReagentGrinderComponent : Component public sealed class ReagentGrinderComponent : Component
{ {
//YAML serialization vars [ViewVariables(VVAccess.ReadWrite)]
[DataField("storageMaxEntities"), ViewVariables(VVAccess.ReadWrite)] public int StorageMaxEntities = 6;
public int StorageMaxEntities = 16;
[DataField("baseStorageMaxEntities"), ViewVariables(VVAccess.ReadWrite)]
public int BaseStorageMaxEntities = 4;
[DataField("machinePartStorageMax", customTypeSerializer: typeof(PrototypeIdSerializer<MachinePartPrototype>))]
public string MachinePartStorageMax = "MatterBin";
[DataField("storagePerPartRating")]
public int StoragePerPartRating = 4;
[DataField("workTime"), ViewVariables(VVAccess.ReadWrite)] [DataField("workTime"), ViewVariables(VVAccess.ReadWrite)]
public TimeSpan WorkTime = TimeSpan.FromSeconds(3.5); // Roughly matches the grind/juice sounds. public TimeSpan WorkTime = TimeSpan.FromSeconds(3.5); // Roughly matches the grind/juice sounds.
[ViewVariables(VVAccess.ReadWrite)]
public float WorkTimeMultiplier = 1;
[DataField("machinePartWorkTime", customTypeSerializer: typeof(PrototypeIdSerializer<MachinePartPrototype>))]
public string MachinePartWorkTime = "Manipulator";
[DataField("partRatingWorkTimeMultiplier")]
public float PartRatingWorkTimerMulitplier = 0.6f;
[DataField("clickSound"), ViewVariables(VVAccess.ReadWrite)] [DataField("clickSound"), ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier ClickSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"); public SoundSpecifier ClickSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg");
@@ -28,6 +47,8 @@ namespace Content.Server.Kitchen.Components
[DataField("juiceSound"), ViewVariables(VVAccess.ReadWrite)] [DataField("juiceSound"), ViewVariables(VVAccess.ReadWrite)]
public SoundSpecifier JuiceSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/juicer.ogg"); public SoundSpecifier JuiceSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/juicer.ogg");
public IPlayingAudioStream? AudioStream;
} }
[Access(typeof(ReagentGrinderSystem)), RegisterComponent] [Access(typeof(ReagentGrinderSystem)), RegisterComponent]
@@ -37,7 +58,7 @@ namespace Content.Server.Kitchen.Components
/// Remaining time until the grinder finishes grinding/juicing. /// Remaining time until the grinder finishes grinding/juicing.
/// </summary> /// </summary>
[ViewVariables] [ViewVariables]
public float WorkTimer; public TimeSpan EndTime;
[ViewVariables] [ViewVariables]
public GrinderProgram Program; public GrinderProgram Program;

View File

@@ -1,5 +1,6 @@
using System.Linq; using System.Linq;
using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.EntitySystems;
using Content.Server.Construction;
using Content.Server.Kitchen.Components; using Content.Server.Kitchen.Components;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems; using Content.Server.Power.EntitySystems;
@@ -16,13 +17,14 @@ using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Player; using Robust.Shared.Player;
using Robust.Shared.Utility; using Robust.Shared.Timing;
namespace Content.Server.Kitchen.EntitySystems namespace Content.Server.Kitchen.EntitySystems
{ {
[UsedImplicitly] [UsedImplicitly]
internal sealed class ReagentGrinderSystem : EntitySystem internal sealed class ReagentGrinderSystem : EntitySystem
{ {
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!; [Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
@@ -36,10 +38,11 @@ namespace Content.Server.Kitchen.EntitySystems
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<ReagentGrinderComponent, ComponentStartup>((uid, component, _) => UpdateUiState(uid, component)); SubscribeLocalEvent<ReagentGrinderComponent, ComponentStartup>((uid, _, _) => UpdateUiState(uid));
SubscribeLocalEvent<ReagentGrinderComponent, PowerChangedEvent>( SubscribeLocalEvent((EntityUid uid, ReagentGrinderComponent _, ref PowerChangedEvent _) => UpdateUiState(uid));
(EntityUid uid, ReagentGrinderComponent component, ref PowerChangedEvent _) => UpdateUiState(uid, component));
SubscribeLocalEvent<ReagentGrinderComponent, InteractUsingEvent>(OnInteractUsing); SubscribeLocalEvent<ReagentGrinderComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<ReagentGrinderComponent, RefreshPartsEvent>(OnRefreshParts);
SubscribeLocalEvent<ReagentGrinderComponent, UpgradeExamineEvent>(OnUpgradeExamine);
SubscribeLocalEvent<ReagentGrinderComponent, EntInsertedIntoContainerMessage>(OnContainerModified); SubscribeLocalEvent<ReagentGrinderComponent, EntInsertedIntoContainerMessage>(OnContainerModified);
SubscribeLocalEvent<ReagentGrinderComponent, EntRemovedFromContainerMessage>(OnContainerModified); SubscribeLocalEvent<ReagentGrinderComponent, EntRemovedFromContainerMessage>(OnContainerModified);
@@ -57,11 +60,11 @@ namespace Content.Server.Kitchen.EntitySystems
foreach (var (active, reagentGrinder) in EntityQuery<ActiveReagentGrinderComponent, ReagentGrinderComponent>()) foreach (var (active, reagentGrinder) in EntityQuery<ActiveReagentGrinderComponent, ReagentGrinderComponent>())
{ {
var uid = reagentGrinder.Owner; var uid = reagentGrinder.Owner;
active.WorkTimer -= frameTime;
if (active.WorkTimer > 0) if (active.EndTime > _timing.CurTime)
continue; continue;
reagentGrinder.AudioStream?.Stop();
RemCompDeferred<ActiveReagentGrinderComponent>(uid); RemCompDeferred<ActiveReagentGrinderComponent>(uid);
var inputContainer = _containerSystem.EnsureContainer<Container>(uid, SharedReagentGrinder.InputContainerId); var inputContainer = _containerSystem.EnsureContainer<Container>(uid, SharedReagentGrinder.InputContainerId);
@@ -110,7 +113,7 @@ namespace Content.Server.Kitchen.EntitySystems
_userInterfaceSystem.TrySendUiMessage(uid, ReagentGrinderUiKey.Key, _userInterfaceSystem.TrySendUiMessage(uid, ReagentGrinderUiKey.Key,
new ReagentGrinderWorkCompleteMessage()); new ReagentGrinderWorkCompleteMessage());
UpdateUiState(uid, reagentGrinder); UpdateUiState(uid);
} }
} }
@@ -122,7 +125,7 @@ namespace Content.Server.Kitchen.EntitySystems
private void OnContainerModified(EntityUid uid, ReagentGrinderComponent reagentGrinder, ContainerModifiedMessage args) private void OnContainerModified(EntityUid uid, ReagentGrinderComponent reagentGrinder, ContainerModifiedMessage args)
{ {
UpdateUiState(uid, reagentGrinder); UpdateUiState(uid);
var outputContainer = _itemSlotsSystem.GetItemOrNull(uid, SharedReagentGrinder.BeakerSlotId); var outputContainer = _itemSlotsSystem.GetItemOrNull(uid, SharedReagentGrinder.BeakerSlotId);
_appearanceSystem.SetData(uid, ReagentGrinderVisualState.BeakerAttached, outputContainer.HasValue); _appearanceSystem.SetData(uid, ReagentGrinderVisualState.BeakerAttached, outputContainer.HasValue);
@@ -161,7 +164,25 @@ namespace Content.Server.Kitchen.EntitySystems
args.Handled = true; args.Handled = true;
} }
private void UpdateUiState(EntityUid uid, ReagentGrinderComponent reagentGrinder) /// <remarks>
/// Gotta be efficient, you know? you're saving a whole extra second here and everything.
/// </remarks>
private void OnRefreshParts(EntityUid uid, ReagentGrinderComponent component, RefreshPartsEvent args)
{
var ratingWorkTime = args.PartRatings[component.MachinePartWorkTime];
var ratingStorage = args.PartRatings[component.MachinePartStorageMax];
component.WorkTimeMultiplier = MathF.Pow(component.PartRatingWorkTimerMulitplier, ratingWorkTime - 1);
component.StorageMaxEntities = component.BaseStorageMaxEntities + (int) (component.StoragePerPartRating * (ratingStorage - 1));
}
private void OnUpgradeExamine(EntityUid uid, ReagentGrinderComponent component, UpgradeExamineEvent args)
{
args.AddPercentageUpgrade("reagent-grinder-component-upgrade-work-time", component.WorkTimeMultiplier);
args.AddNumberUpgrade("reagent-grinder-component-upgrade-storage", component.StorageMaxEntities - component.BaseStorageMaxEntities);
}
private void UpdateUiState(EntityUid uid)
{ {
var inputContainer = _containerSystem.EnsureContainer<Container>(uid, SharedReagentGrinder.InputContainerId); var inputContainer = _containerSystem.EnsureContainer<Container>(uid, SharedReagentGrinder.InputContainerId);
var outputContainer = _itemSlotsSystem.GetItemOrNull(uid, SharedReagentGrinder.BeakerSlotId); var outputContainer = _itemSlotsSystem.GetItemOrNull(uid, SharedReagentGrinder.BeakerSlotId);
@@ -195,7 +216,7 @@ namespace Content.Server.Kitchen.EntitySystems
if (!this.IsPowered(uid, EntityManager) || HasComp<ActiveReagentGrinderComponent>(uid)) if (!this.IsPowered(uid, EntityManager) || HasComp<ActiveReagentGrinderComponent>(uid))
return; return;
DoWork(uid, reagentGrinder, message.Session.AttachedEntity, message.Program); DoWork(uid, reagentGrinder, message.Program);
} }
private void OnEjectChamberAllMessage(EntityUid uid, ReagentGrinderComponent reagentGrinder, ReagentGrinderEjectChamberAllMessage message) private void OnEjectChamberAllMessage(EntityUid uid, ReagentGrinderComponent reagentGrinder, ReagentGrinderEjectChamberAllMessage message)
@@ -211,7 +232,7 @@ namespace Content.Server.Kitchen.EntitySystems
inputContainer.Remove(entity); inputContainer.Remove(entity);
entity.RandomOffset(0.4f); entity.RandomOffset(0.4f);
} }
UpdateUiState(uid, reagentGrinder); UpdateUiState(uid);
} }
private void OnEjectChamberContentMessage(EntityUid uid, ReagentGrinderComponent reagentGrinder, ReagentGrinderEjectChamberContentMessage message) private void OnEjectChamberContentMessage(EntityUid uid, ReagentGrinderComponent reagentGrinder, ReagentGrinderEjectChamberContentMessage message)
@@ -225,15 +246,17 @@ namespace Content.Server.Kitchen.EntitySystems
{ {
message.EntityId.RandomOffset(0.4f); message.EntityId.RandomOffset(0.4f);
ClickSound(uid, reagentGrinder); ClickSound(uid, reagentGrinder);
UpdateUiState(uid, reagentGrinder); UpdateUiState(uid);
} }
} }
/// <summary> /// <summary>
/// The wzhzhzh of the grinder. Processes the contents of the grinder and puts the output in the beaker. /// The wzhzhzh of the grinder. Processes the contents of the grinder and puts the output in the beaker.
/// </summary> /// </summary>
/// <param name="uid">The grinder itself</param>
/// <param name="reagentGrinder"></param>
/// <param name="program">Which program, such as grind or juice</param> /// <param name="program">Which program, such as grind or juice</param>
private void DoWork(EntityUid uid, ReagentGrinderComponent reagentGrinder, EntityUid? user, GrinderProgram program) private void DoWork(EntityUid uid, ReagentGrinderComponent reagentGrinder, GrinderProgram program)
{ {
var inputContainer = _containerSystem.EnsureContainer<Container>(uid, SharedReagentGrinder.InputContainerId); var inputContainer = _containerSystem.EnsureContainer<Container>(uid, SharedReagentGrinder.InputContainerId);
var outputContainer = _itemSlotsSystem.GetItemOrNull(uid, SharedReagentGrinder.BeakerSlotId); var outputContainer = _itemSlotsSystem.GetItemOrNull(uid, SharedReagentGrinder.BeakerSlotId);
@@ -242,7 +265,7 @@ namespace Content.Server.Kitchen.EntitySystems
if (inputContainer.ContainedEntities.Count <= 0 || !HasComp<FitsInDispenserComponent>(outputContainer)) if (inputContainer.ContainedEntities.Count <= 0 || !HasComp<FitsInDispenserComponent>(outputContainer))
return; return;
SoundSpecifier? sound = null; SoundSpecifier? sound;
switch (program) switch (program)
{ {
case GrinderProgram.Grind when inputContainer.ContainedEntities.All(CanGrind): case GrinderProgram.Grind when inputContainer.ContainedEntities.All(CanGrind):
@@ -256,10 +279,11 @@ namespace Content.Server.Kitchen.EntitySystems
} }
var active = AddComp<ActiveReagentGrinderComponent>(uid); var active = AddComp<ActiveReagentGrinderComponent>(uid);
active.WorkTimer = (float) reagentGrinder.WorkTime.TotalSeconds; active.EndTime = _timing.CurTime + reagentGrinder.WorkTime * reagentGrinder.WorkTimeMultiplier;
active.Program = program; active.Program = program;
_audioSystem.PlayPvs(sound, uid); reagentGrinder.AudioStream = _audioSystem.PlayPvs(sound, uid,
AudioParams.Default.WithPitchScale(1 / reagentGrinder.WorkTimeMultiplier)); //slightly higher pitched
_userInterfaceSystem.TrySendUiMessage(uid, ReagentGrinderUiKey.Key, _userInterfaceSystem.TrySendUiMessage(uid, ReagentGrinderUiKey.Key,
new ReagentGrinderWorkStartedMessage(program)); new ReagentGrinderWorkStartedMessage(program));
} }

View File

@@ -4,6 +4,9 @@ reagent-grinder-bound-user-interface-instant-button = INSTANT
reagent-grinder-bound-user-interface-cook-time-label = COOK TIME reagent-grinder-bound-user-interface-cook-time-label = COOK TIME
reagent-grinder-component-cannot-put-entity-message = You can't put this in the reagent grinder! reagent-grinder-component-cannot-put-entity-message = You can't put this in the reagent grinder!
reagent-grinder-component-upgrade-work-time = Work time
reagent-grinder-component-upgrade-storage = Storage
grinder-menu-title = All-In-One Grinder 3000 grinder-menu-title = All-In-One Grinder 3000
grinder-menu-grind-button = Grind grinder-menu-grind-button = Grind
grinder-menu-juice-button = Juice grinder-menu-juice-button = Juice

View File

@@ -441,9 +441,9 @@
- type: MachineBoard - type: MachineBoard
prototype: KitchenReagentGrinder prototype: KitchenReagentGrinder
requirements: requirements:
Laser: 1 Capacitor: 1
ScanningModule: 1
MatterBin: 2 MatterBin: 2
Manipulator: 2
tagRequirements: tagRequirements:
GlassBeaker: GlassBeaker:
Amount: 1 Amount: 1

View File

@@ -35,6 +35,9 @@
snapCardinals: true snapCardinals: true
- type: ApcPowerReceiver - type: ApcPowerReceiver
powerLoad: 300 powerLoad: 300
- type: UpgradePowerDraw
powerDrawMultiplier: 0.75
scaling: Exponential
- type: ItemSlots - type: ItemSlots
slots: slots:
beakerSlot: beakerSlot: