]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Sliceable doAfter (#30824)
authorEd <96445749+TheShuEd@users.noreply.github.com>
Tue, 13 Aug 2024 10:53:59 +0000 (13:53 +0300)
committerGitHub <noreply@github.com>
Tue, 13 Aug 2024 10:53:59 +0000 (13:53 +0300)
* init

* wtf git

Content.Server/Nutrition/Components/SliceableFoodComponent.cs
Content.Server/Nutrition/EntitySystems/SliceableFoodSystem.cs
Content.Shared/Nutrition/Events.cs

index 2b74d0c67ec645e3c37a4e775ddd8c55bc6b90f1..7877e91d0310d74a3f27ccbef7b41b92c6528c46 100644 (file)
@@ -11,21 +11,27 @@ public sealed partial class SliceableFoodComponent : Component
     /// Prototype to spawn after slicing.
     /// If null then it can't be sliced.
     /// </summary>
-    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    [DataField]
     public EntProtoId? Slice;
 
-    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    [DataField]
     public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Items/Culinary/chop.ogg");
 
     /// <summary>
     /// Number of slices the food starts with.
     /// </summary>
-    [DataField("count"), ViewVariables(VVAccess.ReadWrite)]
+    [DataField("count")]
     public ushort TotalCount = 5;
 
     /// <summary>
-    /// Number of slices left.
+    /// how long it takes for this food to be sliced
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite)]
-    public ushort Count;
+    [DataField]
+    public float SliceTime = 1f;
+
+    /// <summary>
+    /// all the pieces will be shifted in random directions.
+    /// </summary>
+    [DataField]
+    public float SpawnOffset = 0.5f;
 }
index 946a789b36d6f3103b276fc2fbe4da60dbca23ae..a865a2212141208c31742cd5e2d95031f01bcd88 100644 (file)
 using Content.Server.Chemistry.Containers.EntitySystems;
+using Content.Server.DoAfter;
 using Content.Server.Nutrition.Components;
 using Content.Shared.Nutrition;
 using Content.Shared.Nutrition.Components;
 using Content.Shared.Chemistry.Components;
-using Content.Shared.Examine;
+using Content.Shared.DoAfter;
 using Content.Shared.FixedPoint;
 using Content.Shared.Interaction;
 using Robust.Server.GameObjects;
 using Robust.Shared.Audio;
 using Robust.Shared.Audio.Systems;
-using Robust.Shared.Containers;
 
-namespace Content.Server.Nutrition.EntitySystems
+namespace Content.Server.Nutrition.EntitySystems;
+
+public sealed class SliceableFoodSystem : EntitySystem
 {
-    public sealed class SliceableFoodSystem : EntitySystem
+    [Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+    [Dependency] private readonly TransformSystem _transform = default!;
+    [Dependency] private readonly DoAfterSystem _doAfter = default!;
+
+    public override void Initialize()
     {
-        [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
-        [Dependency] private readonly SharedAudioSystem _audio = default!;
-        [Dependency] private readonly TransformSystem _xformSystem = default!;
+        base.Initialize();
 
-        public override void Initialize()
+        SubscribeLocalEvent<SliceableFoodComponent, InteractUsingEvent>(OnInteractUsing);
+        SubscribeLocalEvent<SliceableFoodComponent, SliceFoodDoAfterEvent>(OnSlicedoAfter);
+        SubscribeLocalEvent<SliceableFoodComponent, ComponentStartup>(OnComponentStartup);
+    }
+
+    private void OnInteractUsing(Entity<SliceableFoodComponent> entity, ref InteractUsingEvent args)
+    {
+        if (args.Handled)
+            return;
+
+        var doAfterArgs = new DoAfterArgs(EntityManager,
+            args.User,
+            entity.Comp.SliceTime,
+            new SliceFoodDoAfterEvent(),
+            entity,
+            entity,
+            args.Used)
         {
-            base.Initialize();
+            BreakOnDamage = true,
+            BreakOnMove = true,
+            NeedHand = true,
+        };
+        _doAfter.TryStartDoAfter(doAfterArgs);
+    }
 
-            SubscribeLocalEvent<SliceableFoodComponent, ExaminedEvent>(OnExamined);
-            SubscribeLocalEvent<SliceableFoodComponent, InteractUsingEvent>(OnInteractUsing);
-            SubscribeLocalEvent<SliceableFoodComponent, ComponentStartup>(OnComponentStartup);
-        }
+    private void OnSlicedoAfter(Entity<SliceableFoodComponent> entity, ref SliceFoodDoAfterEvent args)
+    {
+        if (args.Cancelled || args.Handled || args.Args.Target == null)
+            return;
 
-        private void OnInteractUsing(Entity<SliceableFoodComponent> entity, ref InteractUsingEvent args)
-        {
-            if (args.Handled)
-                return;
+        if (TrySliceFood(entity, args.User, args.Used, entity.Comp))
+            args.Handled = true;
+    }
 
-            if (TrySliceFood(entity, args.User, args.Used, entity.Comp))
-                args.Handled = true;
-        }
+    private bool TrySliceFood(EntityUid uid,
+        EntityUid user,
+        EntityUid? usedItem,
+        SliceableFoodComponent? component = null,
+        FoodComponent? food = null,
+        TransformComponent? transform = null)
+    {
+        if (!Resolve(uid, ref component, ref food, ref transform) ||
+            string.IsNullOrEmpty(component.Slice))
+            return false;
 
-        private bool TrySliceFood(EntityUid uid, EntityUid user, EntityUid usedItem,
-            SliceableFoodComponent? component = null, FoodComponent? food = null, TransformComponent? transform = null)
-        {
-            if (!Resolve(uid, ref component, ref food, ref transform) ||
-                string.IsNullOrEmpty(component.Slice))
-            {
-                return false;
-            }
-
-            if (!_solutionContainerSystem.TryGetSolution(uid, food.Solution, out var soln, out var solution))
-            {
-                return false;
-            }
-
-            if (!TryComp<UtensilComponent>(usedItem, out var utensil) || (utensil.Types & UtensilType.Knife) == 0)
-            {
-                return false;
-            }
+        if (!_solutionContainer.TryGetSolution(uid, food.Solution, out var soln, out var solution))
+            return false;
 
+        if (!TryComp<UtensilComponent>(usedItem, out var utensil) || (utensil.Types & UtensilType.Knife) == 0)
+            return false;
+
+        var sliceVolume = solution.Volume / FixedPoint2.New(component.TotalCount);
+        for (int i = 0; i < component.TotalCount; i++)
+        {
             var sliceUid = Slice(uid, user, component, transform);
 
-            var lostSolution = _solutionContainerSystem.SplitSolution(soln.Value, solution.Volume / FixedPoint2.New(component.Count));
+            var lostSolution =
+                _solutionContainer.SplitSolution(soln.Value, sliceVolume);
 
             // Fill new slice
             FillSlice(sliceUid, lostSolution);
+        }
 
-            _audio.PlayPvs(component.Sound, transform.Coordinates, AudioParams.Default.WithVolume(-2));
-            var ev = new SliceFoodEvent();
-            RaiseLocalEvent(uid, ref ev);
-
-            // Decrease size of item based on count - Could implement in the future
-            // Bug with this currently is the size in a container is not updated
-            // if (TryComp(uid, out ItemComponent? itemComp) && TryComp(sliceUid, out ItemComponent? sliceComp))
-            // {
-            //     itemComp.Size -= sliceComp.Size;
-            // }
-
-            component.Count--;
+        _audio.PlayPvs(component.Sound, transform.Coordinates, AudioParams.Default.WithVolume(-2));
+        var ev = new SliceFoodEvent();
+        RaiseLocalEvent(uid, ref ev);
 
-            // If someone makes food proto with 1 slice...
-            if (component.Count < 1)
-            {
-                DeleteFood(uid, user, food);
-                return true;
-            }
+        DeleteFood(uid, user, food);
+        return true;
+    }
 
-            // Split last slice
-            if (component.Count > 1)
-                return true;
+    /// <summary>
+    /// Create a new slice in the world and returns its entity.
+    /// The solutions must be set afterwards.
+    /// </summary>
+    public EntityUid Slice(EntityUid uid,
+        EntityUid user,
+        SliceableFoodComponent? comp = null,
+        TransformComponent? transform = null)
+    {
+        if (!Resolve(uid, ref comp, ref transform))
+            return EntityUid.Invalid;
 
-            sliceUid = Slice(uid, user, component, transform);
+        var sliceUid = Spawn(comp.Slice, _transform.GetMapCoordinates(uid));
 
-            // Fill last slice with the rest of the solution
-            FillSlice(sliceUid, solution);
+        // try putting the slice into the container if the food being sliced is in a container!
+        // this lets you do things like slice a pizza up inside of a hot food cart without making a food-everywhere mess
+        _transform.DropNextTo(sliceUid, (uid, transform));
+        _transform.SetLocalRotation(sliceUid, 0);
 
-            DeleteFood(uid, user, food);
-            return true;
-        }
+        return sliceUid;
+    }
 
-        /// <summary>
-        /// Create a new slice in the world and returns its entity.
-        /// The solutions must be set afterwards.
-        /// </summary>
-        public EntityUid Slice(EntityUid uid, EntityUid user, SliceableFoodComponent? comp = null, TransformComponent? transform = null)
+    private void DeleteFood(EntityUid uid, EntityUid user, FoodComponent foodComp)
+    {
+        var ev = new BeforeFullySlicedEvent
         {
-            if (!Resolve(uid, ref comp, ref transform))
-                return EntityUid.Invalid;
-
-            var sliceUid = Spawn(comp.Slice, _xformSystem.GetMapCoordinates(uid));
-
-            // try putting the slice into the container if the food being sliced is in a container!
-            // this lets you do things like slice a pizza up inside of a hot food cart without making a food-everywhere mess
-            _xformSystem.DropNextTo(sliceUid, (uid, transform));
-            _xformSystem.SetLocalRotation(sliceUid, 0);
-
-            return sliceUid;
-        }
-
-        private void DeleteFood(EntityUid uid, EntityUid user, FoodComponent foodComp)
+            User = user
+        };
+        RaiseLocalEvent(uid, ev);
+        if (ev.Cancelled)
+            return;
+
+        // Locate the sliced food and spawn its trash
+        foreach (var trash in foodComp.Trash)
         {
-            var ev = new BeforeFullySlicedEvent
-            {
-                User = user
-            };
-            RaiseLocalEvent(uid, ev);
-            if (ev.Cancelled)
-                return;
-
-            if (foodComp.Trash.Count == 0)
-            {
-                QueueDel(uid);
-                return;
-            }
-
-            // Locate the sliced food and spawn its trash
-            foreach (var trash in foodComp.Trash)
-            {
-                var trashUid = Spawn(trash, _xformSystem.GetMapCoordinates(uid));
-
-                // try putting the trash in the food's container too, to be consistent with slice spawning?
-                _xformSystem.DropNextTo(trashUid, uid);
-                _xformSystem.SetLocalRotation(trashUid, 0);
-            }
-
-            QueueDel(uid);
-        }
+            var trashUid = Spawn(trash, _transform.GetMapCoordinates(uid));
 
-        private void FillSlice(EntityUid sliceUid, Solution solution)
-        {
-            // Replace all reagents on prototype not just copying poisons (example: slices of eaten pizza should have less nutrition)
-            if (TryComp<FoodComponent>(sliceUid, out var sliceFoodComp) &&
-                _solutionContainerSystem.TryGetSolution(sliceUid, sliceFoodComp.Solution, out var itsSoln, out var itsSolution))
-            {
-                _solutionContainerSystem.RemoveAllSolution(itsSoln.Value);
-
-                var lostSolutionPart = solution.SplitSolution(itsSolution.AvailableVolume);
-                _solutionContainerSystem.TryAddSolution(itsSoln.Value, lostSolutionPart);
-            }
+            // try putting the trash in the food's container too, to be consistent with slice spawning?
+            _transform.DropNextTo(trashUid, uid);
+            _transform.SetLocalRotation(trashUid, 0);
         }
 
-        private void OnComponentStartup(Entity<SliceableFoodComponent> entity, ref ComponentStartup args)
+        QueueDel(uid);
+    }
+
+    private void FillSlice(EntityUid sliceUid, Solution solution)
+    {
+        // Replace all reagents on prototype not just copying poisons (example: slices of eaten pizza should have less nutrition)
+        if (TryComp<FoodComponent>(sliceUid, out var sliceFoodComp) &&
+            _solutionContainer.TryGetSolution(sliceUid, sliceFoodComp.Solution, out var itsSoln, out var itsSolution))
         {
-            entity.Comp.Count = entity.Comp.TotalCount;
+            _solutionContainer.RemoveAllSolution(itsSoln.Value);
 
-            var foodComp = EnsureComp<FoodComponent>(entity);
-            _solutionContainerSystem.EnsureSolution(entity.Owner, foodComp.Solution);
+            var lostSolutionPart = solution.SplitSolution(itsSolution.AvailableVolume);
+            _solutionContainer.TryAddSolution(itsSoln.Value, lostSolutionPart);
         }
+    }
 
-        private void OnExamined(Entity<SliceableFoodComponent> entity, ref ExaminedEvent args)
-        {
-            args.PushMarkup(Loc.GetString("sliceable-food-component-on-examine-remaining-slices-text", ("remainingCount", entity.Comp.Count)));
-        }
+    private void OnComponentStartup(Entity<SliceableFoodComponent> entity, ref ComponentStartup args)
+    {
+        var foodComp = EnsureComp<FoodComponent>(entity);
+        _solutionContainer.EnsureSolution(entity.Owner, foodComp.Solution);
     }
 }
+
index f2936d603d9bca9584abd79fa998db8841697270..abba2583ba46a4c5c35cffce9f5693f0b1565d0e 100644 (file)
@@ -59,3 +59,11 @@ public sealed partial class VapeDoAfterEvent : DoAfterEvent
 /// </summary>
 [ByRefEvent]
 public record struct SliceFoodEvent();
+
+/// <summary>
+/// is called after a successful attempt at slicing food.
+/// </summary>
+[Serializable, NetSerializable]
+public sealed partial class SliceFoodDoAfterEvent : SimpleDoAfterEvent
+{
+}