]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Action, Action Container, and Action Upgrade changes (#24005)
authorkeronshb <54602815+keronshb@users.noreply.github.com>
Mon, 15 Jan 2024 06:37:38 +0000 (01:37 -0500)
committerGitHub <noreply@github.com>
Mon, 15 Jan 2024 06:37:38 +0000 (23:37 -0700)
* Added TransferActionWithNewAttached and TransferAllActionsWithNewAttached and OnActionAdded event method to ActionContainerSystem. These are needed where the action needs to have a different attached entity for usage.  Fixed a bug with not being able to upgrade actions between levels.  Added a way to grant and remove a singular action.

* adds an action container component to mind on action added to fix tests

* Swaps trycomp for hascomp

* Maybe this will fix the thests

* Grants action container to performer as well

* Wait that makes no sense, removing that

* fixes mind action grant logic

* Changes ent check back to netent check

* Reverts unintended container changes

Content.Server/Commands/ActionCommands.cs
Content.Shared/Actions/ActionContainerSystem.cs
Content.Shared/Actions/ActionUpgradeComponent.cs
Content.Shared/Actions/ActionUpgradeSystem.cs
Content.Shared/Actions/SharedActionsSystem.cs

index 5ce29b6d8ecb8198edbbd426bf1f446b9b9048cf..fb50cfb3a35ff276d54cb6b512e65763f48a1123 100644 (file)
@@ -51,7 +51,7 @@ internal sealed class UpgradeActionCommand : IConsoleCommand
 
         if (args.Length == 1)
         {
-            if (!actionUpgrade.TryUpgradeAction(uid, actionUpgradeComponent))
+            if (!actionUpgrade.TryUpgradeAction(uid, out _, actionUpgradeComponent))
             {
                 shell.WriteLine(Loc.GetString("upgradeaction-command-cannot-level-up"));
                 return;
@@ -74,7 +74,7 @@ internal sealed class UpgradeActionCommand : IConsoleCommand
                 return;
             }
 
-            if (!actionUpgrade.TryUpgradeAction(uid, actionUpgradeComponent, level))
+            if (!actionUpgrade.TryUpgradeAction(uid, out _, actionUpgradeComponent, level))
                 shell.WriteLine(Loc.GetString("upgradeaction-command-cannot-level-up"));
         }
     }
index 0fe2b83b1153fe74ce7d3f43856a5dfd464a356c..17bcf11bff1eec0f36cccac2eab2ef671801f58a 100644 (file)
@@ -30,6 +30,7 @@ public sealed class ActionContainerSystem : EntitySystem
         SubscribeLocalEvent<ActionsContainerComponent, ComponentShutdown>(OnShutdown);
         SubscribeLocalEvent<ActionsContainerComponent, EntRemovedFromContainerMessage>(OnEntityRemoved);
         SubscribeLocalEvent<ActionsContainerComponent, EntInsertedIntoContainerMessage>(OnEntityInserted);
+        SubscribeLocalEvent<ActionsContainerComponent, ActionAddedEvent>(OnActionAdded);
         SubscribeLocalEvent<ActionsContainerComponent, MindAddedMessage>(OnMindAdded);
         SubscribeLocalEvent<ActionsContainerComponent, MindRemovedMessage>(OnMindRemoved);
     }
@@ -38,7 +39,6 @@ public sealed class ActionContainerSystem : EntitySystem
     {
         if(!_mind.TryGetMind(uid, out var mindId, out _))
             return;
-
         if (!TryComp<ActionsContainerComponent>(mindId, out var mindActionContainerComp))
             return;
 
@@ -174,6 +174,61 @@ public sealed class ActionContainerSystem : EntitySystem
         DebugTools.AssertEqual(oldContainer.Container.Count, 0);
     }
 
+    /// <summary>
+    /// Transfers an actions from one container to another, while changing the attached entity.
+    /// </summary>
+    /// <remarks>
+    /// This will actually remove and then re-grant the action.
+    /// Useful where you need to transfer from one container to another but also change the attached entity (ie spellbook > mind > user)
+    /// </remarks>
+    public void TransferActionWithNewAttached(
+        EntityUid actionId,
+        EntityUid newContainer,
+        EntityUid newAttached,
+        BaseActionComponent? action = null,
+        ActionsContainerComponent? container = null)
+    {
+        if (!_actions.ResolveActionData(actionId, ref action))
+            return;
+
+        if (action.Container == newContainer)
+            return;
+
+        var attached = newAttached;
+        if (!AddAction(newContainer, actionId, action, container))
+            return;
+
+        DebugTools.AssertEqual(action.Container, newContainer);
+        _actions.AddActionDirect(newAttached, actionId, action: action);
+
+        DebugTools.AssertEqual(action.AttachedEntity, attached);
+    }
+
+    /// <summary>
+    /// Transfers all actions from one container to another, while changing the attached entity.
+    /// </summary>
+    /// <remarks>
+    /// This will actually remove and then re-grant the action.
+    /// Useful where you need to transfer from one container to another but also change the attached entity (ie spellbook > mind > user)
+    /// </remarks>
+    public void TransferAllActionsWithNewAttached(
+        EntityUid from,
+        EntityUid to,
+        EntityUid newAttached,
+        ActionsContainerComponent? oldContainer = null,
+        ActionsContainerComponent? newContainer = null)
+    {
+        if (!Resolve(from, ref oldContainer) || !Resolve(to, ref newContainer))
+            return;
+
+        foreach (var action in oldContainer.Container.ContainedEntities.ToArray())
+        {
+            TransferActionWithNewAttached(action, to, newAttached, container: newContainer);
+        }
+
+        DebugTools.AssertEqual(oldContainer.Container.Count, 0);
+    }
+
     /// <summary>
     /// Adds a pre-existing action to an action container. If the action is already in some container it will first remove it.
     /// </summary>
@@ -281,6 +336,12 @@ public sealed class ActionContainerSystem : EntitySystem
         RaiseLocalEvent(uid, ref ev);
         data.Container = null;
     }
+
+    private void OnActionAdded(EntityUid uid, ActionsContainerComponent component, ActionAddedEvent args)
+    {
+        if (TryComp<MindComponent>(uid, out var mindComp) && mindComp.OwnedEntity != null && HasComp<ActionsContainerComponent>(mindComp.OwnedEntity.Value))
+            _actions.GrantContainedAction(mindComp.OwnedEntity.Value, uid, args.Action);
+    }
 }
 
 /// <summary>
index 0d6a813526a62027b2ed1900f821ecb22ad1c0af..d12ce339c863007a8066c37e44ee065269dd8c40 100644 (file)
@@ -11,6 +11,7 @@ public sealed partial class ActionUpgradeComponent : Component
     /// <summary>
     ///     Current Level of the action.
     /// </summary>
+    [ViewVariables]
     public int Level = 1;
 
     /// <summary>
index f4897794930fe64a6f47f2a8aaad4ab776887708..b89b462814cea555876f3509c94152ce91f2b77a 100644 (file)
@@ -21,7 +21,7 @@ public sealed class ActionUpgradeSystem : EntitySystem
 
     private void OnActionUpgradeEvent(EntityUid uid, ActionUpgradeComponent component, ActionUpgradeEvent args)
     {
-        if (!CanLevelUp(args.NewLevel, component.EffectedLevels, out var newActionProto)
+        if (!CanUpgrade(args.NewLevel, component.EffectedLevels, out var newActionProto)
             || !_actions.TryGetActionData(uid, out var actionComp))
             return;
 
@@ -56,8 +56,9 @@ public sealed class ActionUpgradeSystem : EntitySystem
         _entityManager.DeleteEntity(uid);
     }
 
-    public bool TryUpgradeAction(EntityUid? actionId, ActionUpgradeComponent? actionUpgradeComponent = null, int newLevel = 0)
+    public bool TryUpgradeAction(EntityUid? actionId, out EntityUid? upgradeActionId, ActionUpgradeComponent? actionUpgradeComponent = null, int newLevel = 0)
     {
+        upgradeActionId = null;
         if (!TryGetActionUpgrade(actionId, out var actionUpgradeComp))
             return false;
 
@@ -68,48 +69,75 @@ public sealed class ActionUpgradeSystem : EntitySystem
         if (newLevel < 1)
             newLevel = actionUpgradeComponent.Level + 1;
 
-        if (!CanLevelUp(newLevel, actionUpgradeComponent.EffectedLevels, out _))
+        if (!CanLevelUp(newLevel, actionUpgradeComponent.EffectedLevels))
             return false;
 
-        UpgradeAction(actionId, actionUpgradeComp);
+        actionUpgradeComponent.Level = newLevel;
+
+        // If it can level up but can't upgrade, still return true and return current actionId as the upgradeId.
+        if (!CanUpgrade(newLevel, actionUpgradeComponent.EffectedLevels, out var newActionProto))
+        {
+            upgradeActionId = actionId;
+            DebugTools.AssertNotNull(upgradeActionId);
+            return true;
+        }
+
+        upgradeActionId = UpgradeAction(actionId, actionUpgradeComp, newActionProto, newLevel);
+        DebugTools.AssertNotNull(upgradeActionId);
         return true;
     }
 
-    // TODO: Add checks for branching upgrades
-    private bool CanLevelUp(
-        int newLevel,
-        Dictionary<int, EntProtoId> levelDict,
-        [NotNullWhen(true)]out EntProtoId? newLevelProto)
+    private bool CanLevelUp(int newLevel, Dictionary<int, EntProtoId> levelDict)
     {
-        newLevelProto = null;
-
         if (levelDict.Count < 1)
             return false;
 
         var canLevel = false;
         var finalLevel = levelDict.Keys.ToList()[levelDict.Keys.Count - 1];
 
+        foreach (var (level, proto) in levelDict)
+        {
+            if (newLevel > finalLevel)
+                continue;
+
+            if ((newLevel <= finalLevel && newLevel != level) || newLevel == level)
+            {
+                canLevel = true;
+                break;
+            }
+        }
+
+        return canLevel;
+    }
+
+    private bool CanUpgrade(int newLevel, Dictionary<int, EntProtoId> levelDict,  [NotNullWhen(true)]out EntProtoId? newLevelProto)
+    {
+        var canUpgrade = false;
+        newLevelProto = null;
+
+        var finalLevel = levelDict.Keys.ToList()[levelDict.Keys.Count - 1];
+
         foreach (var (level, proto) in levelDict)
         {
             if (newLevel != level || newLevel > finalLevel)
                 continue;
 
-            canLevel = true;
+            canUpgrade = true;
             newLevelProto = proto;
             DebugTools.AssertNotNull(newLevelProto);
             break;
         }
 
-        return canLevel;
+        return canUpgrade;
     }
 
     /// <summary>
     ///     Raises a level by one
     /// </summary>
-    public void UpgradeAction(EntityUid? actionId, ActionUpgradeComponent? actionUpgradeComponent = null, int newLevel = 0)
+    public EntityUid? UpgradeAction(EntityUid? actionId, ActionUpgradeComponent? actionUpgradeComponent = null, EntProtoId? newActionProto = null, int newLevel = 0)
     {
         if (!TryGetActionUpgrade(actionId, out var actionUpgradeComp))
-            return;
+            return null;
 
         actionUpgradeComponent ??= actionUpgradeComp;
         DebugTools.AssertNotNull(actionUpgradeComponent);
@@ -118,7 +146,47 @@ public sealed class ActionUpgradeSystem : EntitySystem
         if (newLevel < 1)
             newLevel = actionUpgradeComponent.Level + 1;
 
-        RaiseActionUpgradeEvent(newLevel, actionId.Value);
+        actionUpgradeComponent.Level = newLevel;
+        // RaiseActionUpgradeEvent(newLevel, actionId.Value);
+
+        if (!CanUpgrade(newLevel, actionUpgradeComponent.EffectedLevels, out var newActionPrototype)
+            || !_actions.TryGetActionData(actionId, out var actionComp))
+            return null;
+
+        newActionProto ??= newActionPrototype;
+        DebugTools.AssertNotNull(newActionProto);
+
+        var originalContainer = actionComp.Container;
+        var originalAttachedEntity = actionComp.AttachedEntity;
+
+        _actionContainer.RemoveAction(actionId.Value, actionComp);
+
+        EntityUid? upgradedActionId = null;
+        if (originalContainer != null
+            && TryComp<ActionsContainerComponent>(originalContainer.Value, out var actionContainerComp))
+        {
+            upgradedActionId = _actionContainer.AddAction(originalContainer.Value, newActionProto, actionContainerComp);
+
+            if (originalAttachedEntity != null)
+                _actions.GrantContainedActions(originalAttachedEntity.Value, originalContainer.Value);
+            else
+                _actions.GrantContainedActions(originalContainer.Value, originalContainer.Value);
+        }
+        else if (originalAttachedEntity != null)
+        {
+            upgradedActionId = _actionContainer.AddAction(originalAttachedEntity.Value, newActionProto);
+        }
+
+        if (!TryComp<ActionUpgradeComponent>(upgradedActionId, out var upgradeComp))
+            return null;
+
+        upgradeComp.Level = newLevel;
+
+        // TODO: Preserve ordering of actions
+
+        _entityManager.DeleteEntity(actionId);
+
+        return upgradedActionId.Value;
     }
 
     private void RaiseActionUpgradeEvent(int level, EntityUid actionId)
index fc7af4a40835087842a086052f44e1c2a915b10a..4eaa641eeb774e62a5ddeab2d6b253738858437d 100644 (file)
@@ -691,6 +691,24 @@ public abstract class SharedActionsSystem : EntitySystem
         }
     }
 
+    /// <summary>
+    ///     Grants the provided action from the container to the target entity. If the target entity has no action
+    /// component, this will give them one.
+    /// </summary>
+    /// <param name="performer"></param>
+    /// <param name="container"></param>
+    /// <param name="actionId"></param>
+    public void GrantContainedAction(Entity<ActionsComponent?> performer, Entity<ActionsContainerComponent?> container, EntityUid actionId)
+    {
+        if (!Resolve(container, ref container.Comp))
+            return;
+
+        performer.Comp ??= EnsureComp<ActionsComponent>(performer);
+
+        if (TryGetActionData(actionId, out var action))
+            AddActionDirect(performer, actionId, performer.Comp, action);
+    }
+
     public IEnumerable<(EntityUid Id, BaseActionComponent Comp)> GetActions(EntityUid holderId, ActionsComponent? actions = null)
     {
         if (!Resolve(holderId, ref actions, false))
@@ -723,6 +741,18 @@ public abstract class SharedActionsSystem : EntitySystem
         }
     }
 
+    /// <summary>
+    ///     Removes a single provided action provided by another entity.
+    /// </summary>
+    public void RemoveProvidedAction(EntityUid performer, EntityUid container, EntityUid actionId, ActionsComponent? comp = null)
+    {
+        if (!Resolve(performer, ref comp, false) || !TryGetActionData(actionId, out var action))
+            return;
+
+        if (action.Container == container)
+            RemoveAction(performer, actionId, comp);
+    }
+
     public void RemoveAction(EntityUid? actionId)
     {
         if (actionId == null)