]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
add fuel costs back to finishing welding (#27030)
authorNemanja <98561806+EmoGarbage404@users.noreply.github.com>
Fri, 19 Apr 2024 23:20:30 +0000 (19:20 -0400)
committerGitHub <noreply@github.com>
Fri, 19 Apr 2024 23:20:30 +0000 (19:20 -0400)
* add fuel costs back to welding

* ack

* meh

* eek!

26 files changed:
Content.Client/Tools/Components/WelderComponent.cs [deleted file]
Content.Client/Tools/ToolSystem.cs
Content.Client/Tools/UI/WelderStatusControl.cs
Content.IntegrationTests/Tests/DoAfter/DoAfterCancellationTests.cs
Content.Server/Chemistry/Components/ReagentTankComponent.cs [deleted file]
Content.Server/Construction/Components/WelderRefinableComponent.cs
Content.Server/Construction/ConstructionSystem.Interactions.cs
Content.Server/Construction/RefiningSystem.cs
Content.Server/Damage/Systems/DamageOnToolInteractSystem.cs
Content.Server/Repairable/RepairableComponent.cs
Content.Server/Repairable/RepairableSystem.cs
Content.Server/Tools/Components/WelderComponent.cs [deleted file]
Content.Server/Tools/ToolSystem.Welder.cs [deleted file]
Content.Server/Tools/ToolSystem.cs
Content.Shared/Chemistry/Components/ReagentTankComponent.cs [new file with mode: 0644]
Content.Shared/Tools/Components/SharedWelderComponent.cs [deleted file]
Content.Shared/Tools/Components/WeldableComponent.cs [moved from Content.Shared/Tools/Components/SharedWeldable.cs with 55% similarity]
Content.Shared/Tools/Components/WelderComponent.cs [new file with mode: 0644]
Content.Shared/Tools/Systems/SharedToolSystem.Welder.cs [new file with mode: 0644]
Content.Shared/Tools/Systems/SharedToolSystem.cs
Content.Shared/Tools/Systems/WeldableSystem.cs
Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
Resources/Prototypes/Entities/Objects/Tools/cowtools.yml
Resources/Prototypes/Entities/Structures/Doors/Airlocks/base_structureairlocks.yml
Resources/Prototypes/Entities/Structures/Doors/Airlocks/highsec.yml
Resources/Prototypes/Entities/Structures/Doors/Firelocks/firelock.yml

diff --git a/Content.Client/Tools/Components/WelderComponent.cs b/Content.Client/Tools/Components/WelderComponent.cs
deleted file mode 100644 (file)
index a83a78a..0000000
+++ /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; }
-    }
-}
index 6811d58460d314963476df25b11748d18b125a54..3eb2cc45cbbe4821c2727fbd494205f130872ef2 100644 (file)
@@ -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<WelderComponent, ComponentHandleState>(OnWelderHandleState);
             Subs.ItemStatus<WelderComponent>(ent => new WelderStatusControl(ent));
             Subs.ItemStatus<MultipleToolComponent>(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<WelderComponent>(uid);
-        }
     }
 }
index af81a28f620b897ca045f660abf2d8f5f630fa12..dae742efc37f81a241248690650c2108ce4c652d 100644 (file)
@@ -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<WelderComponent> _parent;
     private readonly RichTextLabel _label;
 
     public WelderStatusControl(Entity<WelderComponent> parent)
     {
+        IoCManager.InjectDependencies(this);
+
         _parent = parent;
-        _entMan = IoCManager.Resolve<IEntityManager>();
-        if (_entMan.TryGetComponent<ItemToggleComponent>(parent, out var itemToggle))
-            _toggleComponent = itemToggle;
+        var entMan = IoCManager.Resolve<IEntityManager>();
+        _tool = entMan.System<ToolSystem>();
+
         _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"))));
     }
index d47eb13273f998b0137def379ef4c4bb7c47252d..0ebd17d8879b4bf285f4732dea2e58ea9cfc6335 100644 (file)
@@ -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 (file)
index cc0d265..0000000
+++ /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
-    }
-}
index 9d8958f76147e948205a5638128222dc64a6862a..ed37d6f74b83a74de6dda8b1354332980929d4c9 100644 (file)
@@ -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;
+
+/// <summary>
+/// Used for something that can be refined by welder.
+/// For example, glass shard can be refined to glass sheet.
+/// </summary>
+[RegisterComponent]
+public sealed partial class WelderRefinableComponent : Component
 {
-    /// <summary>
-    /// Used for something that can be refined by welder.
-    /// For example, glass shard can be refined to glass sheet.
-    /// </summary>
-    [RegisterComponent]
-    public sealed partial class WelderRefinableComponent : Component
-    {
-        [DataField("refineResult")]
-        public HashSet<string>? RefineResult = new();
+    [DataField]
+    public HashSet<EntProtoId>? RefineResult = new();
+
+    [DataField]
+    public float RefineTime = 2f;
 
-        [DataField("refineTime")]
-        public float RefineTime = 2f;
+    [DataField]
+    public float RefineFuel;
 
-        [DataField("qualityNeeded", customTypeSerializer:typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
-        public string QualityNeeded = "Welding";
-    }
+    [DataField]
+    public ProtoId<ToolQualityPrototype> QualityNeeded = "Welding";
 }
index 59a5fd6af512a5a67a0084ce37e37b7bbc1d7494..ad7b2a11b0edb2c00b1401ce6ee4dd29a608b226 100644 (file)
@@ -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;
                 }
index b9d80c7170a7e2635809c82bee66c719ac7fbdfd..53cfb14528edb6c3943e6082270a77e065049ff2 100644 (file)
@@ -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.
index 264ec4a8ec4b4bf5e55270dd4eb74e8239176396..42676c1891cd96a688159100e3743e532cab3a0a 100644 (file)
@@ -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;
index c436386110cad2cdeccc13f2709bb637b0811a21..bab70f66b5670bcd8b80eee86203297a72543206 100644 (file)
@@ -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.
         /// </remarks>
-        [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<ToolQualityPrototype>))]
-        public string QualityNeeded = "Welding";
+        [DataField]
+        public ProtoId<ToolQualityPrototype> QualityNeeded = "Welding";
 
-        [ViewVariables(VVAccess.ReadWrite)] [DataField("doAfterDelay")]
+        [DataField]
         public int DoAfterDelay = 1;
 
         /// <summary>
         /// A multiplier that will be applied to the above if an entity is repairing themselves.
         /// </summary>
-        [ViewVariables(VVAccess.ReadWrite)] [DataField("selfRepairPenalty")]
+        [DataField]
         public float SelfRepairPenalty = 3f;
 
         /// <summary>
         /// Whether or not an entity is allowed to repair itself.
         /// </summary>
-        [DataField("allowSelfRepair")]
+        [DataField]
         public bool AllowSelfRepair = true;
     }
 }
index 5bd580756daeab32cfbd6cc70a5328b18b6a6aa6..ec24cd819750e907f1ec95c03af48f503e0a4485 100644 (file)
@@ -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 (file)
index b0db2c5..0000000
+++ /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
-    {
-        /// <summary>
-        ///     Name of <see cref="FuelSolution"/>.
-        /// </summary>
-        [DataField("fuelSolution"), ViewVariables(VVAccess.ReadWrite)]
-        public string FuelSolutionName = "Welder";
-
-        /// <summary>
-        ///     Solution on the entity that contains the fuel.
-        /// </summary>
-        [DataField("fuelSolutionRef")]
-        public Entity<SolutionComponent>? FuelSolution = null;
-
-        /// <summary>
-        ///     Reagent that will be used as fuel for welding.
-        /// </summary>
-        [DataField, ViewVariables(VVAccess.ReadWrite)]
-        public ProtoId<ReagentPrototype> FuelReagent = "WeldingFuel";
-
-        /// <summary>
-        ///     Fuel consumption per second while the welder is active.
-        /// </summary>
-        [DataField, ViewVariables(VVAccess.ReadWrite)]
-        public FixedPoint2 FuelConsumption = FixedPoint2.New(2.0f);
-
-        /// <summary>
-        ///     A fuel amount to be consumed when the welder goes from being unlit to being lit.
-        /// </summary>
-        [DataField, ViewVariables(VVAccess.ReadWrite)]
-        public FixedPoint2 FuelLitCost = FixedPoint2.New(0.5f);
-
-        /// <summary>
-        ///     Sound played when refilling the welder.
-        /// </summary>
-        [DataField]
-        public SoundSpecifier WelderRefill = new SoundPathSpecifier("/Audio/Effects/refill.ogg");
-
-        /// <summary>
-        ///     Whether the item is safe to refill while lit without exploding the tank.
-        /// </summary>
-        [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 (file)
index 727526b..0000000
+++ /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<EntityUid> _activeWelders = new();
-
-        private const float WelderUpdateTimer = 1f;
-        private float _welderTimer;
-
-        public void InitializeWelders()
-        {
-            SubscribeLocalEvent<WelderComponent, ExaminedEvent>(OnWelderExamine);
-            SubscribeLocalEvent<WelderComponent, AfterInteractEvent>(OnWelderAfterInteract);
-            SubscribeLocalEvent<WelderComponent, DoAfterAttemptEvent<ToolDoAfterEvent>>(OnWelderToolUseAttempt);
-            SubscribeLocalEvent<WelderComponent, ComponentShutdown>(OnWelderShutdown);
-            SubscribeLocalEvent<WelderComponent, ComponentGetState>(OnWelderGetState);
-            SubscribeLocalEvent<WelderComponent, ItemToggledEvent>(OnToggle);
-            SubscribeLocalEvent<WelderComponent, ItemToggleActivateAttemptEvent>(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<WelderComponent> entity, ref ItemToggledEvent args)
-        {
-            if (args.Activated)
-                TurnOn(entity, args.User);
-            else
-                TurnOff(entity, args.User);
-        }
-
-        private void OnActivateAttempt(Entity<WelderComponent> 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<WelderComponent> 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<WelderComponent> 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<WelderComponent> 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<WelderComponent> 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<WelderComponent> entity, ref DoAfterAttemptEvent<ToolDoAfterEvent> 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<WelderComponent> entity, ref ComponentShutdown args)
-        {
-            _activeWelders.Remove(entity);
-        }
-
-        private void OnWelderGetState(Entity<WelderComponent> 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;
-        }
-    }
-}
index 7bae177892336da5d23f1ed9d9029f79a16eef95..7b2de57efcbae86b3891d754cf3e52e909b34420 100644 (file)
@@ -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 PopupSystem _popup = default!;
-        [Dependency] private readonly SharedAudioSystem _audio = default!;
-        [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
-        [Dependency] private readonly TransformSystem _transformSystem = default!;
+    [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
+    [Dependency] private readonly TransformSystem _transformSystem = default!;
 
-        public override void Initialize()
+    public override void TurnOn(Entity<WelderComponent> entity, EntityUid? user)
+    {
+        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)
-        {
-            base.Update(frameTime);
+    public override void Update(float frameTime)
+    {
+        base.Update(frameTime);
 
-            UpdateWelders(frameTime);
-        }
+        UpdateWelders(frameTime);
+    }
 
-        protected override bool IsWelder(EntityUid uid)
+    //todo move to shared once you can remove reagents from shared without it freaking out.
+    private void UpdateWelders(float frameTime)
+    {
+        var query = EntityQueryEnumerator<WelderComponent, SolutionContainerManagerComponent>();
+        while (query.MoveNext(out var uid, out var welder, out var solutionContainer))
         {
-            return HasComp<WelderComponent>(uid);
+            if (!welder.Enabled)
+                continue;
+
+            welder.WelderTimer += frameTime;
+
+            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 (file)
index 0000000..3aa1756
--- /dev/null
@@ -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 (file)
index 78c1cde..0000000
+++ /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;
-        }
-    }
-}
similarity index 55%
rename from Content.Shared/Tools/Components/SharedWeldable.cs
rename to Content.Shared/Tools/Components/WeldableComponent.cs
index 701bd4d8da553bdf42a5d4a9c6fde1dff6d4f90e..e491b5f6a7312cc5660085ae0045d5f7afc6969e 100644 (file)
@@ -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
     /// <summary>
     ///     Tool quality for welding.
     /// </summary>
-    [DataField("weldingQuality", customTypeSerializer: typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
-    [ViewVariables(VVAccess.ReadWrite)]
-    public string WeldingQuality = "Welding";
+    [DataField]
+    public ProtoId<ToolQualityPrototype> WeldingQuality = "Welding";
 
     /// <summary>
     ///     How much time does it take to weld/unweld entity.
     /// </summary>
-    [DataField("time")]
-    [ViewVariables(VVAccess.ReadWrite)]
-    [AutoNetworkedField]
-    public TimeSpan WeldingTime = TimeSpan.FromSeconds(1f);
+    [DataField, AutoNetworkedField]
+    public TimeSpan Time = TimeSpan.FromSeconds(1f);
+
+    /// <summary>
+    ///     How much fuel does it take to weld/unweld entity.
+    /// </summary>
+    [DataField]
+    public float Fuel = 3f;
 
     /// <summary>
     ///     Shown when welded entity is examined.
     /// </summary>
-    [DataField("weldedExamineMessage")]
-    [ViewVariables(VVAccess.ReadWrite)]
-    public string? WeldedExamineMessage = "weldable-component-examine-is-welded";
+    [DataField]
+    public LocId? WeldedExamineMessage = "weldable-component-examine-is-welded";
 
     /// <summary>
     ///     Is this entity currently welded shut?
     /// </summary>
-    [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 (file)
index 0000000..f133be6
--- /dev/null
@@ -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;
+
+    /// <summary>
+    ///     Name of <see cref="FuelSolution"/>.
+    /// </summary>
+    [DataField]
+    public string FuelSolutionName = "Welder";
+
+    /// <summary>
+    ///     Solution on the entity that contains the fuel.
+    /// </summary>
+    [ViewVariables(VVAccess.ReadWrite)]
+    public Entity<SolutionComponent>? FuelSolution;
+
+    /// <summary>
+    ///     Reagent that will be used as fuel for welding.
+    /// </summary>
+    [DataField]
+    public ProtoId<ReagentPrototype> FuelReagent = "WeldingFuel";
+
+    /// <summary>
+    ///     Fuel consumption per second while the welder is active.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public FixedPoint2 FuelConsumption = FixedPoint2.New(1.0f);
+
+    /// <summary>
+    ///     A fuel amount to be consumed when the welder goes from being unlit to being lit.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public FixedPoint2 FuelLitCost = FixedPoint2.New(0.5f);
+
+    /// <summary>
+    ///     Sound played when refilling the welder.
+    /// </summary>
+    [DataField]
+    public SoundSpecifier WelderRefill = new SoundPathSpecifier("/Audio/Effects/refill.ogg");
+
+    /// <summary>
+    ///     Whether the item is safe to refill while lit without exploding the tank.
+    /// </summary>
+    [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 (file)
index 0000000..6bab296
--- /dev/null
@@ -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<WelderComponent, ExaminedEvent>(OnWelderExamine);
+        SubscribeLocalEvent<WelderComponent, AfterInteractEvent>(OnWelderAfterInteract);
+        SubscribeLocalEvent<WelderComponent, DoAfterAttemptEvent<ToolDoAfterEvent>>(OnWelderToolUseAttempt);
+        SubscribeLocalEvent<WelderComponent, ToolDoAfterEvent>(OnWelderDoAfter);
+        SubscribeLocalEvent<WelderComponent, ItemToggledEvent>(OnToggle);
+        SubscribeLocalEvent<WelderComponent, ItemToggleActivateAttemptEvent>(OnActivateAttempt);
+    }
+
+    public virtual void TurnOn(Entity<WelderComponent> 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<WelderComponent> 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<WelderComponent> 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<WelderComponent> 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<WelderComponent> entity, ref DoAfterAttemptEvent<ToolDoAfterEvent> 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<WelderComponent> 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<WelderComponent> entity, ref ItemToggledEvent args)
+    {
+        if (args.Activated)
+            TurnOn(entity, args.User);
+        else
+            TurnOff(entity, args.User);
+    }
+
+    private void OnActivateAttempt(Entity<WelderComponent> 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;
+        }
+    }
+}
index 4204d7547e0bad2db2cc5d740c2f01b5c74072aa..362f4f768345424de682522d0f38302ad09c16d1 100644 (file)
@@ -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<ToolComponent, ToolDoAfterEvent>(OnDoAfter);
     }
 
@@ -66,6 +74,7 @@ public abstract partial class SharedToolSystem : EntitySystem
     /// <param name="toolQualitiesNeeded">The qualities needed for this tool to work.</param>
     /// <param name="doAfterEv">The event that will be raised when the tool has finished (including cancellation). Event
     /// will be directed at the tool target.</param>
+    /// <param name="fuel">Amount of fuel that should be taken from the tool.</param>
     /// <param name="toolComponent">The tool component.</param>
     /// <returns>Returns true if any interaction takes place.</returns>
     public bool UseTool(
@@ -75,6 +84,7 @@ public abstract partial class SharedToolSystem : EntitySystem
         float doAfterDelay,
         IEnumerable<string> 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.</param>
     /// <param name="id">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</param>
+    /// <param name="fuel">Amount of fuel that should be taken from the tool.</param>
     /// <param name="toolComponent">The tool component.</param>
     /// <returns>Returns true if any interaction takes place.</returns>
     public bool UseTool(
@@ -111,31 +123,30 @@ public abstract partial class SharedToolSystem : EntitySystem
         IEnumerable<string> 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);
-
     /// <summary>
     ///     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
     /// <param name="toolQualityNeeded">The quality needed for this tool to work.</param>
     /// <param name="doAfterEv">The event that will be raised when the tool has finished (including cancellation). Event
     /// will be directed at the tool target.</param>
+    /// <param name="fuel">Amount of fuel that should be taken from the tool.</param>
     /// <param name="toolComponent">The tool component.</param>
     /// <returns>Returns true if any interaction takes place.</returns>
     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
     /// <summary>
     ///     Whether a tool entity has all specified qualities or not.
     /// </summary>
+    [PublicAPI]
     public bool HasAllQualities(EntityUid uid, IEnumerable<string> qualities, ToolComponent? tool = null)
     {
         return Resolve(uid, ref tool, false) && tool.Qualities.ContainsAll(qualities);
     }
 
-    private bool CanStartToolUse(EntityUid tool, EntityUid user, EntityUid? target, IEnumerable<string> toolQualitiesNeeded, ToolComponent? toolComponent = null)
+    private bool CanStartToolUse(EntityUid tool, EntityUid user, EntityUid? target, float fuel, IEnumerable<string> 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;
+
         /// <summary>
         ///     Entity that the wrapped do after event will get directed at. If null, event will be broadcast.
         /// </summary>
@@ -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<NetSerializableAttribute>(), "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
 
index b0ea68f713fc69fb1fd0c68f38575ee8866db858..c6c47d539e0951db1779d6464f6863125cd8ae2f 100644 (file)
@@ -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);
     }
 }
index 9489fda5f0bcac3ec4a385e7a4c0aeab8ffcedac..9a4d4ec3aae6cd0d69a58971fb1c250d7cb84a85 100644 (file)
@@ -61,6 +61,7 @@
     group: GenericNumber
   - type: Repairable
     doAfterDelay: 8
+    fuelCost: 15
   - type: Pullable
   - type: Tag
     tags:
index 977a8a931b5144097aa9e7b8fa24ade0ceb7ae7a..295412debc81ada7af95f6272fee07d3c1ed9a61 100644 (file)
     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
index 4ca7df6482efaef57ab5b68d67861e06021fe45b..8b2ce8ab5634fa90c055b49155c59b18e5c929bd 100644 (file)
@@ -64,6 +64,7 @@
     containers:
       board: !type:Container
   - type: Weldable
+    fuel: 5
     time: 3
   - type: Airlock
   - type: NavMapDoor
   - type: RCDDeconstructable
     cost: 6
     delay: 8
-    fx: EffectRCDDeconstruct8    
+    fx: EffectRCDDeconstruct8
   - type: Destructible
     thresholds:
     - trigger:
   - type: BlockWeather
   placement:
     mode: SnapgridCenter
+
 - type: entity
   id: AirlockRCDResistant
   parent: Airlock
   - 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
index e9ea05a1c3f04db9ab566ce719073ac72a4f1d58..2a8cc0c5261bd39ea2278a39e6ad96c9c78ce969 100644 (file)
@@ -55,6 +55,7 @@
     denySound:
       path: /Audio/Machines/airlock_deny.ogg
   - type: Weldable
+    fuel: 10
     time: 10
   - type: Airlock
   - type: NavMapDoor
index 1ba867773bc717b796881184ba08dcaf694f2bd8..a5b8a8dc74d7885aa27a57ddd16a247ba44ce5ea 100644 (file)
@@ -82,6 +82,7 @@
       openingAnimationTime: 0.6
       closingAnimationTime: 0.6
     - type: Weldable
+      fuel: 5
       time: 3
     - type: Firelock
     - type: Appearance