From a47c5561a9632b6577abdc252f712d7f2da823e6 Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Fri, 19 Apr 2024 19:20:30 -0400 Subject: [PATCH] add fuel costs back to finishing welding (#27030) * add fuel costs back to welding * ack * meh * eek! --- .../Tools/Components/WelderComponent.cs | 18 -- Content.Client/Tools/ToolSystem.cs | 18 -- .../Tools/UI/WelderStatusControl.cs | 37 ++- .../Tests/DoAfter/DoAfterCancellationTests.cs | 2 - .../Components/ReagentTankComponent.cs | 23 -- .../Components/WelderRefinableComponent.cs | 34 +-- .../ConstructionSystem.Interactions.cs | 5 +- Content.Server/Construction/RefiningSystem.cs | 7 +- .../Systems/DamageOnToolInteractSystem.cs | 2 - .../Repairable/RepairableComponent.cs | 15 +- Content.Server/Repairable/RepairableSystem.cs | 3 +- .../Tools/Components/WelderComponent.cs | 56 ----- Content.Server/Tools/ToolSystem.Welder.cs | 211 ------------------ Content.Server/Tools/ToolSystem.cs | 71 ++++-- .../Components/ReagentTankComponent.cs | 22 ++ .../Tools/Components/SharedWelderComponent.cs | 21 -- ...SharedWeldable.cs => WeldableComponent.cs} | 26 ++- .../Tools/Components/WelderComponent.cs | 64 ++++++ .../Tools/Systems/SharedToolSystem.Welder.cs | 170 ++++++++++++++ .../Tools/Systems/SharedToolSystem.cs | 43 ++-- .../Tools/Systems/WeldableSystem.cs | 6 +- .../Prototypes/Entities/Mobs/NPCs/silicon.yml | 1 + .../Entities/Objects/Tools/cowtools.yml | 5 - .../Doors/Airlocks/base_structureairlocks.yml | 7 +- .../Structures/Doors/Airlocks/highsec.yml | 1 + .../Structures/Doors/Firelocks/firelock.yml | 1 + 26 files changed, 403 insertions(+), 466 deletions(-) delete mode 100644 Content.Client/Tools/Components/WelderComponent.cs delete mode 100644 Content.Server/Chemistry/Components/ReagentTankComponent.cs delete mode 100644 Content.Server/Tools/Components/WelderComponent.cs delete mode 100644 Content.Server/Tools/ToolSystem.Welder.cs create mode 100644 Content.Shared/Chemistry/Components/ReagentTankComponent.cs delete mode 100644 Content.Shared/Tools/Components/SharedWelderComponent.cs rename Content.Shared/Tools/Components/{SharedWeldable.cs => WeldableComponent.cs} (55%) create mode 100644 Content.Shared/Tools/Components/WelderComponent.cs create mode 100644 Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs diff --git a/Content.Client/Tools/Components/WelderComponent.cs b/Content.Client/Tools/Components/WelderComponent.cs deleted file mode 100644 index a83a78a5a4..0000000000 --- a/Content.Client/Tools/Components/WelderComponent.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Content.Client.Tools.UI; -using Content.Shared.Tools.Components; - -namespace Content.Client.Tools.Components -{ - [RegisterComponent, Access(typeof(ToolSystem), typeof(WelderStatusControl))] - public sealed partial class WelderComponent : SharedWelderComponent - { - [ViewVariables(VVAccess.ReadWrite)] - public bool UiUpdateNeeded { get; set; } - - [ViewVariables] - public float FuelCapacity { get; set; } - - [ViewVariables] - public float Fuel { get; set; } - } -} diff --git a/Content.Client/Tools/ToolSystem.cs b/Content.Client/Tools/ToolSystem.cs index 6811d58460..3eb2cc45cb 100644 --- a/Content.Client/Tools/ToolSystem.cs +++ b/Content.Client/Tools/ToolSystem.cs @@ -1,10 +1,8 @@ using Content.Client.Items; using Content.Client.Tools.Components; using Content.Client.Tools.UI; -using Content.Shared.Item; using Content.Shared.Tools.Components; using Robust.Client.GameObjects; -using Robust.Shared.GameStates; using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Client.Tools @@ -15,7 +13,6 @@ namespace Content.Client.Tools { base.Initialize(); - SubscribeLocalEvent(OnWelderHandleState); Subs.ItemStatus(ent => new WelderStatusControl(ent)); Subs.ItemStatus(ent => new MultipleToolStatusControl(ent)); } @@ -42,20 +39,5 @@ namespace Content.Client.Tools sprite.LayerSetSprite(0, current.Sprite); } } - - private void OnWelderHandleState(EntityUid uid, WelderComponent welder, ref ComponentHandleState args) - { - if (args.Current is not WelderComponentState state) - return; - - welder.FuelCapacity = state.FuelCapacity; - welder.Fuel = state.Fuel; - welder.UiUpdateNeeded = true; - } - - protected override bool IsWelder(EntityUid uid) - { - return HasComp(uid); - } } } diff --git a/Content.Client/Tools/UI/WelderStatusControl.cs b/Content.Client/Tools/UI/WelderStatusControl.cs index af81a28f62..dae742efc3 100644 --- a/Content.Client/Tools/UI/WelderStatusControl.cs +++ b/Content.Client/Tools/UI/WelderStatusControl.cs @@ -1,28 +1,29 @@ using Content.Client.Message; using Content.Client.Stylesheets; -using Content.Client.Tools.Components; -using Content.Shared.Item; +using Content.Shared.Tools.Components; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Timing; -using ItemToggleComponent = Content.Shared.Item.ItemToggle.Components.ItemToggleComponent; namespace Content.Client.Tools.UI; public sealed class WelderStatusControl : Control { - [Dependency] private readonly IEntityManager _entMan = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; - private readonly WelderComponent _parent; - private readonly ItemToggleComponent? _toggleComponent; + private readonly ToolSystem _tool; + + private readonly Entity _parent; private readonly RichTextLabel _label; public WelderStatusControl(Entity parent) { + IoCManager.InjectDependencies(this); + _parent = parent; - _entMan = IoCManager.Resolve(); - if (_entMan.TryGetComponent(parent, out var itemToggle)) - _toggleComponent = itemToggle; + var entMan = IoCManager.Resolve(); + _tool = entMan.System(); + _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } }; AddChild(_label); @@ -34,28 +35,20 @@ public sealed class WelderStatusControl : Control { base.FrameUpdate(args); - if (!_parent.UiUpdateNeeded) - { - return; - } Update(); } public void Update() { - _parent.UiUpdateNeeded = false; + if (!_gameTiming.IsFirstTimePredicted) + return; - var fuelCap = _parent.FuelCapacity; - var fuel = _parent.Fuel; - var lit = false; - if (_toggleComponent != null) - { - lit = _toggleComponent.Activated; - } + var (fuel, fuelCap) = _tool.GetWelderFuelAndCapacity(_parent, _parent); + var lit = _parent.Comp.Enabled; _label.SetMarkup(Loc.GetString("welder-component-on-examine-detailed-message", ("colorName", fuel < fuelCap / 4f ? "darkorange" : "orange"), - ("fuelLeft", Math.Round(fuel, 1)), + ("fuelLeft", Math.Round(fuel.Float(), 1)), ("fuelCapacity", fuelCap), ("status", Loc.GetString(lit ? "welder-component-on-examine-welder-lit-message" : "welder-component-on-examine-welder-not-lit-message")))); } diff --git a/Content.IntegrationTests/Tests/DoAfter/DoAfterCancellationTests.cs b/Content.IntegrationTests/Tests/DoAfter/DoAfterCancellationTests.cs index d47eb13273..0ebd17d887 100644 --- a/Content.IntegrationTests/Tests/DoAfter/DoAfterCancellationTests.cs +++ b/Content.IntegrationTests/Tests/DoAfter/DoAfterCancellationTests.cs @@ -3,8 +3,6 @@ using Content.IntegrationTests.Tests.Construction.Interaction; using Content.IntegrationTests.Tests.Interaction; using Content.IntegrationTests.Tests.Weldable; using Content.Shared.Tools.Components; -using Content.Server.Tools.Components; -using Content.Shared.DoAfter; namespace Content.IntegrationTests.Tests.DoAfter; diff --git a/Content.Server/Chemistry/Components/ReagentTankComponent.cs b/Content.Server/Chemistry/Components/ReagentTankComponent.cs deleted file mode 100644 index cc0d2657d7..0000000000 --- a/Content.Server/Chemistry/Components/ReagentTankComponent.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Content.Shared.FixedPoint; - - -namespace Content.Server.Chemistry.Components -{ - [RegisterComponent] - public sealed partial class ReagentTankComponent : Component - { - [DataField("transferAmount")] - [ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2 TransferAmount { get; set; } = FixedPoint2.New(10); - - [DataField("tankType")] - [ViewVariables(VVAccess.ReadWrite)] - public ReagentTankType TankType { get; set; } = ReagentTankType.Unspecified; - } - - public enum ReagentTankType : byte - { - Unspecified, - Fuel - } -} diff --git a/Content.Server/Construction/Components/WelderRefinableComponent.cs b/Content.Server/Construction/Components/WelderRefinableComponent.cs index 9d8958f761..ed37d6f74b 100644 --- a/Content.Server/Construction/Components/WelderRefinableComponent.cs +++ b/Content.Server/Construction/Components/WelderRefinableComponent.cs @@ -1,22 +1,24 @@ using Content.Shared.Tools; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Prototypes; -namespace Content.Server.Construction.Components +namespace Content.Server.Construction.Components; + +/// +/// Used for something that can be refined by welder. +/// For example, glass shard can be refined to glass sheet. +/// +[RegisterComponent] +public sealed partial class WelderRefinableComponent : Component { - /// - /// Used for something that can be refined by welder. - /// For example, glass shard can be refined to glass sheet. - /// - [RegisterComponent] - public sealed partial class WelderRefinableComponent : Component - { - [DataField("refineResult")] - public HashSet? RefineResult = new(); + [DataField] + public HashSet? RefineResult = new(); - [DataField("refineTime")] - public float RefineTime = 2f; + [DataField] + public float RefineTime = 2f; - [DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer))] - public string QualityNeeded = "Welding"; - } + [DataField] + public float RefineFuel; + + [DataField] + public ProtoId QualityNeeded = "Welding"; } diff --git a/Content.Server/Construction/ConstructionSystem.Interactions.cs b/Content.Server/Construction/ConstructionSystem.Interactions.cs index 59a5fd6af5..ad7b2a11b0 100644 --- a/Content.Server/Construction/ConstructionSystem.Interactions.cs +++ b/Content.Server/Construction/ConstructionSystem.Interactions.cs @@ -11,10 +11,8 @@ using Content.Shared.DoAfter; using Content.Shared.Interaction; using Content.Shared.Prying.Systems; using Content.Shared.Radio.EntitySystems; -using Content.Shared.Tools.Components; using Content.Shared.Tools.Systems; using Robust.Shared.Containers; -using Robust.Shared.Map; using Robust.Shared.Utility; #if EXCEPTION_TOLERANCE // ReSharper disable once RedundantUsingDirective @@ -369,7 +367,8 @@ namespace Content.Server.Construction TimeSpan.FromSeconds(toolInsertStep.DoAfter), new [] { toolInsertStep.Tool }, new ConstructionInteractDoAfterEvent(EntityManager, interactUsing), - out var doAfter); + out var doAfter, + toolInsertStep.Fuel); return result && doAfter != null ? HandleResult.DoAfter : HandleResult.False; } diff --git a/Content.Server/Construction/RefiningSystem.cs b/Content.Server/Construction/RefiningSystem.cs index b9d80c7170..53cfb14528 100644 --- a/Content.Server/Construction/RefiningSystem.cs +++ b/Content.Server/Construction/RefiningSystem.cs @@ -1,11 +1,8 @@ using Content.Server.Construction.Components; using Content.Server.Stack; using Content.Shared.Construction; -using Content.Shared.DoAfter; using Content.Shared.Interaction; using Content.Shared.Stacks; -using Content.Shared.Tools; -using Robust.Shared.Serialization; using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Construction @@ -26,7 +23,7 @@ namespace Content.Server.Construction if (args.Handled) return; - args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, component.RefineTime, component.QualityNeeded, new WelderRefineDoAfterEvent()); + args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, component.RefineTime, component.QualityNeeded, new WelderRefineDoAfterEvent(), fuel: component.RefineFuel); } private void OnDoAfter(EntityUid uid, WelderRefinableComponent component, WelderRefineDoAfterEvent args) @@ -41,7 +38,7 @@ namespace Content.Server.Construction // spawn each result after refine foreach (var result in component.RefineResult!) { - var droppedEnt = EntityManager.SpawnEntity(result, resultPosition); + var droppedEnt = Spawn(result, resultPosition); // TODO: If something has a stack... Just use a prototype with a single thing in the stack. // This is not a good way to do it. diff --git a/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs b/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs index 264ec4a8ec..42676c1891 100644 --- a/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs +++ b/Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs @@ -1,7 +1,5 @@ using Content.Server.Administration.Logs; using Content.Server.Damage.Components; -using Content.Server.Tools.Components; -using Content.Shared.Item; using Content.Shared.Damage; using Content.Shared.Database; using Content.Shared.Interaction; diff --git a/Content.Server/Repairable/RepairableComponent.cs b/Content.Server/Repairable/RepairableComponent.cs index c436386110..bab70f66b5 100644 --- a/Content.Server/Repairable/RepairableComponent.cs +++ b/Content.Server/Repairable/RepairableComponent.cs @@ -1,5 +1,6 @@ using Content.Shared.Damage; using Content.Shared.Tools; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Repairable @@ -14,28 +15,28 @@ namespace Content.Server.Repairable /// If this data-field is specified, it will change damage by this amount instead of setting all damage to 0. /// in order to heal/repair the damage values have to be negative. /// - [ViewVariables(VVAccess.ReadWrite)] [DataField("damage")] + [DataField] public DamageSpecifier? Damage; - [ViewVariables(VVAccess.ReadWrite)] [DataField("fuelCost")] + [DataField] public int FuelCost = 5; - [ViewVariables(VVAccess.ReadWrite)] [DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer))] - public string QualityNeeded = "Welding"; + [DataField] + public ProtoId QualityNeeded = "Welding"; - [ViewVariables(VVAccess.ReadWrite)] [DataField("doAfterDelay")] + [DataField] public int DoAfterDelay = 1; /// /// A multiplier that will be applied to the above if an entity is repairing themselves. /// - [ViewVariables(VVAccess.ReadWrite)] [DataField("selfRepairPenalty")] + [DataField] public float SelfRepairPenalty = 3f; /// /// Whether or not an entity is allowed to repair itself. /// - [DataField("allowSelfRepair")] + [DataField] public bool AllowSelfRepair = true; } } diff --git a/Content.Server/Repairable/RepairableSystem.cs b/Content.Server/Repairable/RepairableSystem.cs index 5bd580756d..ec24cd8197 100644 --- a/Content.Server/Repairable/RepairableSystem.cs +++ b/Content.Server/Repairable/RepairableSystem.cs @@ -4,7 +4,6 @@ using Content.Shared.Database; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.Repairable; -using Content.Shared.Tools; using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; namespace Content.Server.Repairable @@ -70,7 +69,7 @@ namespace Content.Server.Repairable } // Run the repairing doafter - args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, delay, component.QualityNeeded, new RepairFinishedEvent()); + args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, delay, component.QualityNeeded, new RepairFinishedEvent(), component.FuelCost); } } } diff --git a/Content.Server/Tools/Components/WelderComponent.cs b/Content.Server/Tools/Components/WelderComponent.cs deleted file mode 100644 index b0db2c58e8..0000000000 --- a/Content.Server/Tools/Components/WelderComponent.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Content.Shared.Chemistry.Components; -using Content.Shared.Chemistry.Reagent; -using Content.Shared.FixedPoint; -using Content.Shared.Tools.Components; -using Robust.Shared.Audio; -using Robust.Shared.Prototypes; - -namespace Content.Server.Tools.Components -{ - [RegisterComponent] - public sealed partial class WelderComponent : SharedWelderComponent - { - /// - /// Name of . - /// - [DataField("fuelSolution"), ViewVariables(VVAccess.ReadWrite)] - public string FuelSolutionName = "Welder"; - - /// - /// Solution on the entity that contains the fuel. - /// - [DataField("fuelSolutionRef")] - public Entity? FuelSolution = null; - - /// - /// Reagent that will be used as fuel for welding. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public ProtoId FuelReagent = "WeldingFuel"; - - /// - /// Fuel consumption per second while the welder is active. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2 FuelConsumption = FixedPoint2.New(2.0f); - - /// - /// A fuel amount to be consumed when the welder goes from being unlit to being lit. - /// - [DataField, ViewVariables(VVAccess.ReadWrite)] - public FixedPoint2 FuelLitCost = FixedPoint2.New(0.5f); - - /// - /// Sound played when refilling the welder. - /// - [DataField] - public SoundSpecifier WelderRefill = new SoundPathSpecifier("/Audio/Effects/refill.ogg"); - - /// - /// Whether the item is safe to refill while lit without exploding the tank. - /// - [DataField] - public bool TankSafe = false; //I have no idea what I'm doing - - } -} diff --git a/Content.Server/Tools/ToolSystem.Welder.cs b/Content.Server/Tools/ToolSystem.Welder.cs deleted file mode 100644 index 727526b398..0000000000 --- a/Content.Server/Tools/ToolSystem.Welder.cs +++ /dev/null @@ -1,211 +0,0 @@ -using Content.Server.Chemistry.Components; -using Content.Server.IgnitionSource; -using Content.Server.Tools.Components; -using Content.Shared.Chemistry.Components.SolutionManager; -using Content.Shared.Database; -using Content.Shared.DoAfter; -using Content.Shared.Examine; -using Content.Shared.FixedPoint; -using Content.Shared.Interaction; -using Content.Shared.Item.ItemToggle; -using Content.Shared.Tools.Components; -using Robust.Shared.GameStates; -using System.Linq; -using Content.Shared.Item.ItemToggle.Components; - -namespace Content.Server.Tools -{ - public sealed partial class ToolSystem - { - [Dependency] private readonly SharedItemToggleSystem _itemToggle = default!; - [Dependency] private readonly IgnitionSourceSystem _ignitionSource = default!; - private readonly HashSet _activeWelders = new(); - - private const float WelderUpdateTimer = 1f; - private float _welderTimer; - - public void InitializeWelders() - { - SubscribeLocalEvent(OnWelderExamine); - SubscribeLocalEvent(OnWelderAfterInteract); - SubscribeLocalEvent>(OnWelderToolUseAttempt); - SubscribeLocalEvent(OnWelderShutdown); - SubscribeLocalEvent(OnWelderGetState); - SubscribeLocalEvent(OnToggle); - SubscribeLocalEvent(OnActivateAttempt); - } - - public (FixedPoint2 fuel, FixedPoint2 capacity) GetWelderFuelAndCapacity(EntityUid uid, WelderComponent? welder = null, SolutionContainerManagerComponent? solutionContainer = null) - { - if (!Resolve(uid, ref welder, ref solutionContainer) - || !_solutionContainer.ResolveSolution((uid, solutionContainer), welder.FuelSolutionName, ref welder.FuelSolution, out var fuelSolution)) - return (FixedPoint2.Zero, FixedPoint2.Zero); - - return (fuelSolution.GetTotalPrototypeQuantity(welder.FuelReagent), fuelSolution.MaxVolume); - } - - private void OnToggle(Entity entity, ref ItemToggledEvent args) - { - if (args.Activated) - TurnOn(entity, args.User); - else - TurnOff(entity, args.User); - } - - private void OnActivateAttempt(Entity entity, ref ItemToggleActivateAttemptEvent args) - { - if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution, out var solution)) - { - args.Cancelled = true; - args.Popup = Loc.GetString("welder-component-no-fuel-message"); - return; - } - - var fuel = solution.GetTotalPrototypeQuantity(entity.Comp.FuelReagent); - if (fuel == FixedPoint2.Zero || fuel < entity.Comp.FuelLitCost) - { - args.Popup = Loc.GetString("welder-component-no-fuel-message"); - args.Cancelled = true; - } - } - - public void TurnOn(Entity entity, EntityUid? user) - { - if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution)) - return; - - _solutionContainer.RemoveReagent(entity.Comp.FuelSolution.Value, entity.Comp.FuelReagent, entity.Comp.FuelLitCost); - AdminLogger.Add(LogType.InteractActivate, LogImpact.Low, - $"{ToPrettyString(user):user} toggled {ToPrettyString(entity.Owner):welder} on"); - - var xform = Transform(entity); - if (xform.GridUid is { } gridUid) - { - var position = _transformSystem.GetGridOrMapTilePosition(entity.Owner, xform); - _atmosphereSystem.HotspotExpose(gridUid, position, 700, 50, entity.Owner, true); - } - - _activeWelders.Add(entity); - } - - public void TurnOff(Entity entity, EntityUid? user) - { - AdminLogger.Add(LogType.InteractActivate, LogImpact.Low, - $"{ToPrettyString(user):user} toggled {ToPrettyString(entity.Owner):welder} off"); - _activeWelders.Remove(entity); - } - - private void OnWelderExamine(Entity entity, ref ExaminedEvent args) - { - using (args.PushGroup(nameof(WelderComponent))) - { - if (_itemToggle.IsActivated(entity.Owner)) - { - args.PushMarkup(Loc.GetString("welder-component-on-examine-welder-lit-message")); - } - else - { - args.PushMarkup(Loc.GetString("welder-component-on-examine-welder-not-lit-message")); - } - - if (args.IsInDetailsRange) - { - var (fuel, capacity) = GetWelderFuelAndCapacity(entity.Owner, entity.Comp); - - args.PushMarkup(Loc.GetString("welder-component-on-examine-detailed-message", - ("colorName", fuel < capacity / FixedPoint2.New(4f) ? "darkorange" : "orange"), - ("fuelLeft", fuel), - ("fuelCapacity", capacity), - ("status", string.Empty))); // Lit status is handled above - } - } - } - - private void OnWelderAfterInteract(Entity entity, ref AfterInteractEvent args) - { - if (args.Handled) - return; - - if (args.Target is not { Valid: true } target || !args.CanReach) - return; - - if (TryComp(target, out ReagentTankComponent? tank) - && tank.TankType == ReagentTankType.Fuel - && _solutionContainer.TryGetDrainableSolution(target, out var targetSoln, out var targetSolution) - && _solutionContainer.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution, out var welderSolution)) - { - var trans = FixedPoint2.Min(welderSolution.AvailableVolume, targetSolution.Volume); - if (trans > 0) - { - var drained = _solutionContainer.Drain(target, targetSoln.Value, trans); - _solutionContainer.TryAddSolution(entity.Comp.FuelSolution.Value, drained); - _audio.PlayPvs(entity.Comp.WelderRefill, entity); - _popup.PopupEntity(Loc.GetString("welder-component-after-interact-refueled-message"), entity, args.User); - } - else if (welderSolution.AvailableVolume <= 0) - { - _popup.PopupEntity(Loc.GetString("welder-component-already-full"), entity, args.User); - } - else - { - _popup.PopupEntity(Loc.GetString("welder-component-no-fuel-in-tank", ("owner", args.Target)), entity, args.User); - } - - args.Handled = true; - } - } - - private void OnWelderToolUseAttempt(Entity entity, ref DoAfterAttemptEvent args) - { - var user = args.DoAfter.Args.User; - - if (!_itemToggle.IsActivated(entity.Owner)) - { - _popup.PopupEntity(Loc.GetString("welder-component-welder-not-lit-message"), entity, user); - args.Cancel(); - } - } - - private void OnWelderShutdown(Entity entity, ref ComponentShutdown args) - { - _activeWelders.Remove(entity); - } - - private void OnWelderGetState(Entity entity, ref ComponentGetState args) - { - var (fuel, capacity) = GetWelderFuelAndCapacity(entity.Owner, entity.Comp); - args.State = new WelderComponentState(capacity.Float(), fuel.Float()); - } - - private void UpdateWelders(float frameTime) - { - _welderTimer += frameTime; - - if (_welderTimer < WelderUpdateTimer) - return; - - // TODO Serialization. _activeWelders is not serialized. - // Need to use some "active" component, and EntityQuery over that. - // Probably best to generalize it to a "ToggleableFuelDrain" component. - foreach (var tool in _activeWelders.ToArray()) - { - if (!TryComp(tool, out WelderComponent? welder) - || !TryComp(tool, out SolutionContainerManagerComponent? solutionContainer)) - continue; - - if (!_solutionContainer.ResolveSolution((tool, solutionContainer), welder.FuelSolutionName, ref welder.FuelSolution, out var solution)) - continue; - - _solutionContainer.RemoveReagent(welder.FuelSolution.Value, welder.FuelReagent, welder.FuelConsumption * _welderTimer); - - if (solution.GetTotalPrototypeQuantity(welder.FuelReagent) <= FixedPoint2.Zero) - { - _itemToggle.Toggle(tool, predicted: false); - } - - Dirty(tool, welder); - } - _welderTimer -= WelderUpdateTimer; - } - } -} diff --git a/Content.Server/Tools/ToolSystem.cs b/Content.Server/Tools/ToolSystem.cs index 7bae177892..7b2de57efc 100644 --- a/Content.Server/Tools/ToolSystem.cs +++ b/Content.Server/Tools/ToolSystem.cs @@ -1,40 +1,63 @@ using Content.Server.Atmos.EntitySystems; -using Content.Server.Chemistry.Containers.EntitySystems; -using Content.Server.Popups; -using Content.Server.Tools.Components; +using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.FixedPoint; +using Content.Shared.Tools.Components; using Robust.Server.GameObjects; -using Robust.Shared.Audio.Systems; using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; -namespace Content.Server.Tools +namespace Content.Server.Tools; + +public sealed class ToolSystem : SharedToolSystem { - // TODO move tool system to shared, and make it a friend of Tool Component. - public sealed partial class ToolSystem : SharedToolSystem + [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; + [Dependency] private readonly TransformSystem _transformSystem = default!; + + public override void TurnOn(Entity entity, EntityUid? user) { - [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; - [Dependency] private readonly PopupSystem _popup = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!; - [Dependency] private readonly TransformSystem _transformSystem = default!; - - public override void Initialize() + base.TurnOn(entity, user); + var xform = Transform(entity); + if (xform.GridUid is { } gridUid) { - base.Initialize(); - - InitializeWelders(); + var position = _transformSystem.GetGridOrMapTilePosition(entity.Owner, xform); + _atmosphereSystem.HotspotExpose(gridUid, position, 700, 50, entity.Owner, true); } + } - public override void Update(float frameTime) + public override void Update(float frameTime) + { + base.Update(frameTime); + + UpdateWelders(frameTime); + } + + //todo move to shared once you can remove reagents from shared without it freaking out. + private void UpdateWelders(float frameTime) + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var welder, out var solutionContainer)) { - base.Update(frameTime); + if (!welder.Enabled) + continue; - UpdateWelders(frameTime); - } + welder.WelderTimer += frameTime; - protected override bool IsWelder(EntityUid uid) - { - return HasComp(uid); + if (welder.WelderTimer < welder.WelderUpdateTimer) + continue; + + if (!SolutionContainerSystem.ResolveSolution((uid, solutionContainer), welder.FuelSolutionName, ref welder.FuelSolution, out var solution)) + continue; + + SolutionContainerSystem.RemoveReagent(welder.FuelSolution.Value, welder.FuelReagent, welder.FuelConsumption * welder.WelderTimer); + + if (solution.GetTotalPrototypeQuantity(welder.FuelReagent) <= FixedPoint2.Zero) + { + ItemToggle.Toggle(uid, predicted: false); + } + + Dirty(uid, welder); + welder.WelderTimer -= welder.WelderUpdateTimer; } } } + diff --git a/Content.Shared/Chemistry/Components/ReagentTankComponent.cs b/Content.Shared/Chemistry/Components/ReagentTankComponent.cs new file mode 100644 index 0000000000..3aa1756cf9 --- /dev/null +++ b/Content.Shared/Chemistry/Components/ReagentTankComponent.cs @@ -0,0 +1,22 @@ +using Content.Shared.FixedPoint; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Chemistry.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class ReagentTankComponent : Component +{ + [DataField, ViewVariables(VVAccess.ReadWrite)] + public FixedPoint2 TransferAmount { get; set; } = FixedPoint2.New(10); + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public ReagentTankType TankType { get; set; } = ReagentTankType.Unspecified; +} + +[Serializable, NetSerializable] +public enum ReagentTankType : byte +{ + Unspecified, + Fuel +} diff --git a/Content.Shared/Tools/Components/SharedWelderComponent.cs b/Content.Shared/Tools/Components/SharedWelderComponent.cs deleted file mode 100644 index 78c1cde201..0000000000 --- a/Content.Shared/Tools/Components/SharedWelderComponent.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Robust.Shared.GameStates; -using Robust.Shared.Serialization; - -namespace Content.Shared.Tools.Components -{ - [NetworkedComponent] - public abstract partial class SharedWelderComponent : Component { } - - [NetSerializable, Serializable] - public sealed class WelderComponentState : ComponentState - { - public float FuelCapacity { get; } - public float Fuel { get; } - - public WelderComponentState(float fuelCapacity, float fuel) - { - FuelCapacity = fuelCapacity; - Fuel = fuel; - } - } -} diff --git a/Content.Shared/Tools/Components/SharedWeldable.cs b/Content.Shared/Tools/Components/WeldableComponent.cs similarity index 55% rename from Content.Shared/Tools/Components/SharedWeldable.cs rename to Content.Shared/Tools/Components/WeldableComponent.cs index 701bd4d8da..e491b5f6a7 100644 --- a/Content.Shared/Tools/Components/SharedWeldable.cs +++ b/Content.Shared/Tools/Components/WeldableComponent.cs @@ -1,6 +1,6 @@ using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Shared.Tools.Components; @@ -10,29 +10,31 @@ public sealed partial class WeldableComponent : Component /// /// Tool quality for welding. /// - [DataField("weldingQuality", customTypeSerializer: typeof(PrototypeIdSerializer))] - [ViewVariables(VVAccess.ReadWrite)] - public string WeldingQuality = "Welding"; + [DataField] + public ProtoId WeldingQuality = "Welding"; /// /// How much time does it take to weld/unweld entity. /// - [DataField("time")] - [ViewVariables(VVAccess.ReadWrite)] - [AutoNetworkedField] - public TimeSpan WeldingTime = TimeSpan.FromSeconds(1f); + [DataField, AutoNetworkedField] + public TimeSpan Time = TimeSpan.FromSeconds(1f); + + /// + /// How much fuel does it take to weld/unweld entity. + /// + [DataField] + public float Fuel = 3f; /// /// Shown when welded entity is examined. /// - [DataField("weldedExamineMessage")] - [ViewVariables(VVAccess.ReadWrite)] - public string? WeldedExamineMessage = "weldable-component-examine-is-welded"; + [DataField] + public LocId? WeldedExamineMessage = "weldable-component-examine-is-welded"; /// /// Is this entity currently welded shut? /// - [DataField("isWelded"), AutoNetworkedField] + [DataField, AutoNetworkedField] public bool IsWelded; } diff --git a/Content.Shared/Tools/Components/WelderComponent.cs b/Content.Shared/Tools/Components/WelderComponent.cs new file mode 100644 index 0000000000..f133be675d --- /dev/null +++ b/Content.Shared/Tools/Components/WelderComponent.cs @@ -0,0 +1,64 @@ +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using Content.Shared.Tools.Systems; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Tools.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), Access(typeof(SharedToolSystem))] +public sealed partial class WelderComponent : Component +{ + [DataField, AutoNetworkedField] + public bool Enabled; + + [DataField] + public float WelderTimer; + + /// + /// Name of . + /// + [DataField] + public string FuelSolutionName = "Welder"; + + /// + /// Solution on the entity that contains the fuel. + /// + [ViewVariables(VVAccess.ReadWrite)] + public Entity? FuelSolution; + + /// + /// Reagent that will be used as fuel for welding. + /// + [DataField] + public ProtoId FuelReagent = "WeldingFuel"; + + /// + /// Fuel consumption per second while the welder is active. + /// + [DataField, AutoNetworkedField] + public FixedPoint2 FuelConsumption = FixedPoint2.New(1.0f); + + /// + /// A fuel amount to be consumed when the welder goes from being unlit to being lit. + /// + [DataField, AutoNetworkedField] + public FixedPoint2 FuelLitCost = FixedPoint2.New(0.5f); + + /// + /// Sound played when refilling the welder. + /// + [DataField] + public SoundSpecifier WelderRefill = new SoundPathSpecifier("/Audio/Effects/refill.ogg"); + + /// + /// Whether the item is safe to refill while lit without exploding the tank. + /// + [DataField] + public bool TankSafe; + + [DataField] + public float WelderUpdateTimer = 1f; +} diff --git a/Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs b/Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs new file mode 100644 index 0000000000..6bab296db5 --- /dev/null +++ b/Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs @@ -0,0 +1,170 @@ +using Content.Shared.Chemistry.Components; +using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Database; +using Content.Shared.DoAfter; +using Content.Shared.Examine; +using Content.Shared.FixedPoint; +using Content.Shared.Interaction; +using Content.Shared.Item.ItemToggle.Components; +using Content.Shared.Tools.Components; + +namespace Content.Shared.Tools.Systems; + +public abstract partial class SharedToolSystem +{ + public void InitializeWelder() + { + SubscribeLocalEvent(OnWelderExamine); + SubscribeLocalEvent(OnWelderAfterInteract); + SubscribeLocalEvent>(OnWelderToolUseAttempt); + SubscribeLocalEvent(OnWelderDoAfter); + SubscribeLocalEvent(OnToggle); + SubscribeLocalEvent(OnActivateAttempt); + } + + public virtual void TurnOn(Entity entity, EntityUid? user) + { + if (!SolutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution)) + return; + + SolutionContainerSystem.RemoveReagent(entity.Comp.FuelSolution.Value, entity.Comp.FuelReagent, entity.Comp.FuelLitCost); + AdminLogger.Add(LogType.InteractActivate, LogImpact.Low, + $"{ToPrettyString(user):user} toggled {ToPrettyString(entity.Owner):welder} on"); + + entity.Comp.Enabled = true; + Dirty(entity, entity.Comp); + } + + public void TurnOff(Entity entity, EntityUid? user) + { + AdminLogger.Add(LogType.InteractActivate, LogImpact.Low, + $"{ToPrettyString(user):user} toggled {ToPrettyString(entity.Owner):welder} off"); + entity.Comp.Enabled = false; + Dirty(entity, entity.Comp); + } + + public (FixedPoint2 fuel, FixedPoint2 capacity) GetWelderFuelAndCapacity(EntityUid uid, WelderComponent? welder = null, SolutionContainerManagerComponent? solutionContainer = null) + { + if (!Resolve(uid, ref welder, ref solutionContainer) + || !SolutionContainerSystem.ResolveSolution((uid, solutionContainer), welder.FuelSolutionName, ref welder.FuelSolution, out var fuelSolution)) + return (FixedPoint2.Zero, FixedPoint2.Zero); + + return (fuelSolution.GetTotalPrototypeQuantity(welder.FuelReagent), fuelSolution.MaxVolume); + } + + private void OnWelderExamine(Entity entity, ref ExaminedEvent args) + { + using (args.PushGroup(nameof(WelderComponent))) + { + if (ItemToggle.IsActivated(entity.Owner)) + { + args.PushMarkup(Loc.GetString("welder-component-on-examine-welder-lit-message")); + } + else + { + args.PushMarkup(Loc.GetString("welder-component-on-examine-welder-not-lit-message")); + } + + if (args.IsInDetailsRange) + { + var (fuel, capacity) = GetWelderFuelAndCapacity(entity.Owner, entity.Comp); + + args.PushMarkup(Loc.GetString("welder-component-on-examine-detailed-message", + ("colorName", fuel < capacity / FixedPoint2.New(4f) ? "darkorange" : "orange"), + ("fuelLeft", fuel), + ("fuelCapacity", capacity), + ("status", string.Empty))); // Lit status is handled above + } + } + } + + private void OnWelderAfterInteract(Entity entity, ref AfterInteractEvent args) + { + if (args.Handled) + return; + + if (args.Target is not { Valid: true } target || !args.CanReach) + return; + + if (TryComp(target, out ReagentTankComponent? tank) + && tank.TankType == ReagentTankType.Fuel + && SolutionContainerSystem.TryGetDrainableSolution(target, out var targetSoln, out var targetSolution) + && SolutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution, out var welderSolution)) + { + var trans = FixedPoint2.Min(welderSolution.AvailableVolume, targetSolution.Volume); + if (trans > 0) + { + var drained = SolutionContainerSystem.Drain(target, targetSoln.Value, trans); + SolutionContainerSystem.TryAddSolution(entity.Comp.FuelSolution.Value, drained); + _audioSystem.PlayPredicted(entity.Comp.WelderRefill, entity, user: args.User); + _popup.PopupClient(Loc.GetString("welder-component-after-interact-refueled-message"), entity, args.User); + } + else if (welderSolution.AvailableVolume <= 0) + { + _popup.PopupClient(Loc.GetString("welder-component-already-full"), entity, args.User); + } + else + { + _popup.PopupClient(Loc.GetString("welder-component-no-fuel-in-tank", ("owner", args.Target)), entity, args.User); + } + + args.Handled = true; + } + } + + private void OnWelderToolUseAttempt(Entity entity, ref DoAfterAttemptEvent args) + { + var user = args.DoAfter.Args.User; + + if (!ItemToggle.IsActivated(entity.Owner)) + { + _popup.PopupClient(Loc.GetString("welder-component-welder-not-lit-message"), entity, user); + args.Cancel(); + return; + } + + var (fuel, _) = GetWelderFuelAndCapacity(entity); + + if (args.Event.Fuel > fuel) + { + _popup.PopupClient(Loc.GetString("welder-component-cannot-weld-message"), entity, user); + args.Cancel(); + } + } + + private void OnWelderDoAfter(Entity ent, ref ToolDoAfterEvent args) + { + if (args.Cancelled) + return; + + if (!SolutionContainerSystem.TryGetSolution(ent.Owner, ent.Comp.FuelSolutionName, out var solution)) + return; + + SolutionContainerSystem.RemoveReagent(solution.Value, ent.Comp.FuelReagent, FixedPoint2.New(args.Fuel)); + } + + private void OnToggle(Entity entity, ref ItemToggledEvent args) + { + if (args.Activated) + TurnOn(entity, args.User); + else + TurnOff(entity, args.User); + } + + private void OnActivateAttempt(Entity entity, ref ItemToggleActivateAttemptEvent args) + { + if (!SolutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.FuelSolutionName, ref entity.Comp.FuelSolution, out var solution)) + { + args.Cancelled = true; + args.Popup = Loc.GetString("welder-component-no-fuel-message"); + return; + } + + var fuel = solution.GetTotalPrototypeQuantity(entity.Comp.FuelReagent); + if (fuel == FixedPoint2.Zero || fuel < entity.Comp.FuelLitCost) + { + args.Popup = Loc.GetString("welder-component-no-fuel-message"); + args.Cancelled = true; + } + } +} diff --git a/Content.Shared/Tools/Systems/SharedToolSystem.cs b/Content.Shared/Tools/Systems/SharedToolSystem.cs index 4204d7547e..362f4f7683 100644 --- a/Content.Shared/Tools/Systems/SharedToolSystem.cs +++ b/Content.Shared/Tools/Systems/SharedToolSystem.cs @@ -1,8 +1,12 @@ using Content.Shared.Administration.Logs; +using Content.Shared.Chemistry.EntitySystems; using Content.Shared.DoAfter; using Content.Shared.Interaction; +using Content.Shared.Item.ItemToggle; using Content.Shared.Maps; +using Content.Shared.Popups; using Content.Shared.Tools.Components; +using JetBrains.Annotations; using Robust.Shared.Audio.Systems; using Robust.Shared.Map; using Robust.Shared.Prototypes; @@ -15,12 +19,15 @@ public abstract partial class SharedToolSystem : EntitySystem { [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IPrototypeManager _protoMan = default!; - [Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!; + [Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!; [Dependency] private readonly ITileDefinitionManager _tileDefManager = default!; [Dependency] private readonly SharedAudioSystem _audioSystem = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; [Dependency] protected readonly SharedInteractionSystem InteractionSystem = default!; + [Dependency] protected readonly SharedItemToggleSystem ItemToggle = default!; [Dependency] private readonly SharedMapSystem _maps = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] protected readonly SharedSolutionContainerSystem SolutionContainerSystem = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; [Dependency] private readonly TileSystem _tiles = default!; [Dependency] private readonly TurfSystem _turfs = default!; @@ -29,6 +36,7 @@ public abstract partial class SharedToolSystem : EntitySystem { InitializeMultipleTool(); InitializeTile(); + InitializeWelder(); SubscribeLocalEvent(OnDoAfter); } @@ -66,6 +74,7 @@ public abstract partial class SharedToolSystem : EntitySystem /// The qualities needed for this tool to work. /// The event that will be raised when the tool has finished (including cancellation). Event /// will be directed at the tool target. + /// Amount of fuel that should be taken from the tool. /// The tool component. /// Returns true if any interaction takes place. public bool UseTool( @@ -75,6 +84,7 @@ public abstract partial class SharedToolSystem : EntitySystem float doAfterDelay, IEnumerable toolQualitiesNeeded, DoAfterEvent doAfterEv, + float fuel = 0, ToolComponent? toolComponent = null) { return UseTool(tool, @@ -84,6 +94,7 @@ public abstract partial class SharedToolSystem : EntitySystem toolQualitiesNeeded, doAfterEv, out _, + fuel, toolComponent); } @@ -101,6 +112,7 @@ public abstract partial class SharedToolSystem : EntitySystem /// will be directed at the tool target. /// The id of the DoAfter that was created. This may be null even if the function returns true in /// the event that this tool-use cancelled an existing DoAfter + /// Amount of fuel that should be taken from the tool. /// The tool component. /// Returns true if any interaction takes place. public bool UseTool( @@ -111,31 +123,30 @@ public abstract partial class SharedToolSystem : EntitySystem IEnumerable toolQualitiesNeeded, DoAfterEvent doAfterEv, out DoAfterId? id, + float fuel = 0, ToolComponent? toolComponent = null) { id = null; if (!Resolve(tool, ref toolComponent, false)) return false; - if (!CanStartToolUse(tool, user, target, toolQualitiesNeeded, toolComponent)) + if (!CanStartToolUse(tool, user, target, fuel, toolQualitiesNeeded, toolComponent)) return false; - var toolEvent = new ToolDoAfterEvent(doAfterEv, GetNetEntity(target)); + var toolEvent = new ToolDoAfterEvent(fuel, doAfterEv, GetNetEntity(target)); var doAfterArgs = new DoAfterArgs(EntityManager, user, delay / toolComponent.SpeedModifier, toolEvent, tool, target: target, used: tool) { BreakOnDamage = true, BreakOnMove = true, BreakOnWeightlessMove = false, NeedHand = tool != user, - AttemptFrequency = IsWelder(tool) ? AttemptFrequency.EveryTick : AttemptFrequency.Never + AttemptFrequency = fuel > 0 ? AttemptFrequency.EveryTick : AttemptFrequency.Never }; _doAfterSystem.TryStartDoAfter(doAfterArgs, out id); return true; } - protected abstract bool IsWelder(EntityUid uid); - /// /// Attempts to use a tool on some entity, which will start a DoAfter. Returns true if an interaction occurred. /// Note that this does not mean the interaction was successful, you need to listen for the DoAfter event. @@ -148,6 +159,7 @@ public abstract partial class SharedToolSystem : EntitySystem /// The quality needed for this tool to work. /// The event that will be raised when the tool has finished (including cancellation). Event /// will be directed at the tool target. + /// Amount of fuel that should be taken from the tool. /// The tool component. /// Returns true if any interaction takes place. public bool UseTool( @@ -157,6 +169,7 @@ public abstract partial class SharedToolSystem : EntitySystem float doAfterDelay, string toolQualityNeeded, DoAfterEvent doAfterEv, + float fuel = 0, ToolComponent? toolComponent = null) { return UseTool(tool, @@ -166,6 +179,7 @@ public abstract partial class SharedToolSystem : EntitySystem new[] { toolQualityNeeded }, doAfterEv, out _, + fuel, toolComponent); } @@ -180,12 +194,13 @@ public abstract partial class SharedToolSystem : EntitySystem /// /// Whether a tool entity has all specified qualities or not. /// + [PublicAPI] public bool HasAllQualities(EntityUid uid, IEnumerable qualities, ToolComponent? tool = null) { return Resolve(uid, ref tool, false) && tool.Qualities.ContainsAll(qualities); } - private bool CanStartToolUse(EntityUid tool, EntityUid user, EntityUid? target, IEnumerable toolQualitiesNeeded, ToolComponent? toolComponent = null) + private bool CanStartToolUse(EntityUid tool, EntityUid user, EntityUid? target, float fuel, IEnumerable toolQualitiesNeeded, ToolComponent? toolComponent = null) { if (!Resolve(tool, ref toolComponent)) return false; @@ -220,6 +235,9 @@ public abstract partial class SharedToolSystem : EntitySystem [Serializable, NetSerializable] protected sealed partial class ToolDoAfterEvent : DoAfterEvent { + [DataField] + public float Fuel; + /// /// Entity that the wrapped do after event will get directed at. If null, event will be broadcast. /// @@ -233,10 +251,11 @@ public abstract partial class SharedToolSystem : EntitySystem { } - public ToolDoAfterEvent(DoAfterEvent wrappedEvent, NetEntity? originalTarget) + public ToolDoAfterEvent(float fuel, DoAfterEvent wrappedEvent, NetEntity? originalTarget) { DebugTools.Assert(wrappedEvent.GetType().HasCustomAttribute(), "Tool event is not serializable"); + Fuel = fuel; WrappedEvent = wrappedEvent; OriginalTarget = originalTarget; } @@ -249,14 +268,14 @@ public abstract partial class SharedToolSystem : EntitySystem if (evClone == WrappedEvent) return this; - return new ToolDoAfterEvent(evClone, OriginalTarget); + return new ToolDoAfterEvent(Fuel, evClone, OriginalTarget); } } [Serializable, NetSerializable] protected sealed partial class LatticeCuttingCompleteEvent : DoAfterEvent { - [DataField("coordinates", required:true)] + [DataField(required:true)] public NetCoordinates Coordinates; private LatticeCuttingCompleteEvent() @@ -273,9 +292,7 @@ public abstract partial class SharedToolSystem : EntitySystem } [Serializable, NetSerializable] -public sealed partial class CableCuttingFinishedEvent : SimpleDoAfterEvent -{ -} +public sealed partial class CableCuttingFinishedEvent : SimpleDoAfterEvent; #endregion diff --git a/Content.Shared/Tools/Systems/WeldableSystem.cs b/Content.Shared/Tools/Systems/WeldableSystem.cs index b0ea68f713..c6c47d539e 100644 --- a/Content.Shared/Tools/Systems/WeldableSystem.cs +++ b/Content.Shared/Tools/Systems/WeldableSystem.cs @@ -69,7 +69,7 @@ public sealed class WeldableSystem : EntitySystem if (!CanWeld(uid, tool, user, component)) return false; - if (!_toolSystem.UseTool(tool, user, uid, component.WeldingTime.Seconds, component.WeldingQuality, new WeldFinishedEvent())) + if (!_toolSystem.UseTool(tool, user, uid, component.Time.Seconds, component.WeldingQuality, new WeldFinishedEvent(), component.Fuel)) return false; // Log attempt @@ -140,10 +140,10 @@ public sealed class WeldableSystem : EntitySystem if (!_query.Resolve(uid, ref component)) return; - if (component.WeldingTime.Equals(time)) + if (component.Time.Equals(time)) return; - component.WeldingTime = time; + component.Time = time; Dirty(uid, component); } } diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index 9489fda5f0..9a4d4ec3aa 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -61,6 +61,7 @@ group: GenericNumber - type: Repairable doAfterDelay: 8 + fuelCost: 15 - type: Pullable - type: Tag tags: diff --git a/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml b/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml index 977a8a931b..295412debc 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/cowtools.yml @@ -128,11 +128,6 @@ sprite: Objects/Tools/Cowtools/cowelder.rsi - type: Tool speed: 0.05 - - type: Welder - litMeleeDamageBonus: - types: # When lit, negate standard melee damage and replace with heat - Heat: 0.5 - Blunt: -5 - type: entity name: milkalyzer diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml index 4ca7df6482..8b2ce8ab56 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml @@ -64,6 +64,7 @@ containers: board: !type:Container - type: Weldable + fuel: 5 time: 3 - type: Airlock - type: NavMapDoor @@ -116,7 +117,7 @@ - type: RCDDeconstructable cost: 6 delay: 8 - fx: EffectRCDDeconstruct8 + fx: EffectRCDDeconstruct8 - type: Destructible thresholds: - trigger: @@ -154,7 +155,7 @@ - type: BlockWeather placement: mode: SnapgridCenter - + - type: entity id: AirlockRCDResistant parent: Airlock @@ -203,4 +204,4 @@ - type: Tag tags: - GlassAirlock - # This tag is used to nagivate the Airlock construction graph. It's needed because the construction graph is shared between Airlock, AirlockGlass, and HighSecDoor \ No newline at end of file + # This tag is used to nagivate the Airlock construction graph. It's needed because the construction graph is shared between Airlock, AirlockGlass, and HighSecDoor diff --git a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml index e9ea05a1c3..2a8cc0c526 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml @@ -55,6 +55,7 @@ denySound: path: /Audio/Machines/airlock_deny.ogg - type: Weldable + fuel: 10 time: 10 - type: Airlock - type: NavMapDoor diff --git a/Resources/Prototypes/Entities/Structures/Doors/Firelocks/firelock.yml b/Resources/Prototypes/Entities/Structures/Doors/Firelocks/firelock.yml index 1ba867773b..a5b8a8dc74 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Firelocks/firelock.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Firelocks/firelock.yml @@ -82,6 +82,7 @@ openingAnimationTime: 0.6 closingAnimationTime: 0.6 - type: Weldable + fuel: 5 time: 3 - type: Firelock - type: Appearance