ActionUpgradeSystem.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using System.Diagnostics.CodeAnalysis;
  2. using System.Linq;
  3. using Content.Shared.Actions.Events;
  4. using Robust.Shared.Prototypes;
  5. using Robust.Shared.Utility;
  6. namespace Content.Shared.Actions;
  7. public sealed class ActionUpgradeSystem : EntitySystem
  8. {
  9. [Dependency] private readonly SharedActionsSystem _actions = default!;
  10. [Dependency] private readonly ActionContainerSystem _actionContainer = default!;
  11. [Dependency] private readonly EntityManager _entityManager = default!;
  12. public override void Initialize()
  13. {
  14. base.Initialize();
  15. SubscribeLocalEvent<ActionUpgradeComponent, ActionUpgradeEvent>(OnActionUpgradeEvent);
  16. }
  17. private void OnActionUpgradeEvent(EntityUid uid, ActionUpgradeComponent component, ActionUpgradeEvent args)
  18. {
  19. if (!CanUpgrade(args.NewLevel, component.EffectedLevels, out var newActionProto)
  20. || !_actions.TryGetActionData(uid, out var actionComp))
  21. return;
  22. var originalContainer = actionComp.Container;
  23. var originalAttachedEntity = actionComp.AttachedEntity;
  24. _actionContainer.RemoveAction(uid, actionComp);
  25. EntityUid? upgradedActionId = null;
  26. if (originalContainer != null
  27. && TryComp<ActionsContainerComponent>(originalContainer.Value, out var actionContainerComp))
  28. {
  29. upgradedActionId = _actionContainer.AddAction(originalContainer.Value, newActionProto, actionContainerComp);
  30. if (originalAttachedEntity != null)
  31. _actions.GrantContainedActions(originalAttachedEntity.Value, originalContainer.Value);
  32. else
  33. _actions.GrantContainedActions(originalContainer.Value, originalContainer.Value);
  34. }
  35. else if (originalAttachedEntity != null)
  36. {
  37. upgradedActionId = _actionContainer.AddAction(originalAttachedEntity.Value, newActionProto);
  38. }
  39. if (!TryComp<ActionUpgradeComponent>(upgradedActionId, out var upgradeComp))
  40. return;
  41. upgradeComp.Level = args.NewLevel;
  42. // TODO: Preserve ordering of actions
  43. _entityManager.DeleteEntity(uid);
  44. }
  45. public bool TryUpgradeAction(EntityUid? actionId, out EntityUid? upgradeActionId, ActionUpgradeComponent? actionUpgradeComponent = null, int newLevel = 0)
  46. {
  47. upgradeActionId = null;
  48. if (!TryGetActionUpgrade(actionId, out var actionUpgradeComp))
  49. return false;
  50. actionUpgradeComponent ??= actionUpgradeComp;
  51. DebugTools.AssertNotNull(actionUpgradeComponent);
  52. DebugTools.AssertNotNull(actionId);
  53. if (newLevel < 1)
  54. newLevel = actionUpgradeComponent.Level + 1;
  55. if (!CanLevelUp(newLevel, actionUpgradeComponent.EffectedLevels))
  56. return false;
  57. actionUpgradeComponent.Level = newLevel;
  58. // If it can level up but can't upgrade, still return true and return current actionId as the upgradeId.
  59. if (!CanUpgrade(newLevel, actionUpgradeComponent.EffectedLevels, out var newActionProto))
  60. {
  61. upgradeActionId = actionId;
  62. DebugTools.AssertNotNull(upgradeActionId);
  63. return true;
  64. }
  65. upgradeActionId = UpgradeAction(actionId, actionUpgradeComp, newActionProto, newLevel);
  66. DebugTools.AssertNotNull(upgradeActionId);
  67. return true;
  68. }
  69. private bool CanLevelUp(int newLevel, Dictionary<int, EntProtoId> levelDict)
  70. {
  71. if (levelDict.Count < 1)
  72. return false;
  73. var canLevel = false;
  74. var finalLevel = levelDict.Keys.ToList()[levelDict.Keys.Count - 1];
  75. foreach (var (level, proto) in levelDict)
  76. {
  77. if (newLevel > finalLevel)
  78. continue;
  79. if ((newLevel <= finalLevel && newLevel != level) || newLevel == level)
  80. {
  81. canLevel = true;
  82. break;
  83. }
  84. }
  85. return canLevel;
  86. }
  87. private bool CanUpgrade(int newLevel, Dictionary<int, EntProtoId> levelDict, [NotNullWhen(true)]out EntProtoId? newLevelProto)
  88. {
  89. var canUpgrade = false;
  90. newLevelProto = null;
  91. var finalLevel = levelDict.Keys.ToList()[levelDict.Keys.Count - 1];
  92. foreach (var (level, proto) in levelDict)
  93. {
  94. if (newLevel != level || newLevel > finalLevel)
  95. continue;
  96. canUpgrade = true;
  97. newLevelProto = proto;
  98. DebugTools.AssertNotNull(newLevelProto);
  99. break;
  100. }
  101. return canUpgrade;
  102. }
  103. /// <summary>
  104. /// Raises a level by one
  105. /// </summary>
  106. public EntityUid? UpgradeAction(EntityUid? actionId, ActionUpgradeComponent? actionUpgradeComponent = null, EntProtoId? newActionProto = null, int newLevel = 0)
  107. {
  108. if (!TryGetActionUpgrade(actionId, out var actionUpgradeComp))
  109. return null;
  110. actionUpgradeComponent ??= actionUpgradeComp;
  111. DebugTools.AssertNotNull(actionUpgradeComponent);
  112. DebugTools.AssertNotNull(actionId);
  113. if (newLevel < 1)
  114. newLevel = actionUpgradeComponent.Level + 1;
  115. actionUpgradeComponent.Level = newLevel;
  116. // RaiseActionUpgradeEvent(newLevel, actionId.Value);
  117. if (!CanUpgrade(newLevel, actionUpgradeComponent.EffectedLevels, out var newActionPrototype)
  118. || !_actions.TryGetActionData(actionId, out var actionComp))
  119. return null;
  120. newActionProto ??= newActionPrototype;
  121. DebugTools.AssertNotNull(newActionProto);
  122. var originalContainer = actionComp.Container;
  123. var originalAttachedEntity = actionComp.AttachedEntity;
  124. _actionContainer.RemoveAction(actionId.Value, actionComp);
  125. EntityUid? upgradedActionId = null;
  126. if (originalContainer != null
  127. && TryComp<ActionsContainerComponent>(originalContainer.Value, out var actionContainerComp))
  128. {
  129. upgradedActionId = _actionContainer.AddAction(originalContainer.Value, newActionProto, actionContainerComp);
  130. if (originalAttachedEntity != null)
  131. _actions.GrantContainedActions(originalAttachedEntity.Value, originalContainer.Value);
  132. else
  133. _actions.GrantContainedActions(originalContainer.Value, originalContainer.Value);
  134. }
  135. else if (originalAttachedEntity != null)
  136. {
  137. upgradedActionId = _actionContainer.AddAction(originalAttachedEntity.Value, newActionProto);
  138. }
  139. if (!TryComp<ActionUpgradeComponent>(upgradedActionId, out var upgradeComp))
  140. return null;
  141. upgradeComp.Level = newLevel;
  142. // TODO: Preserve ordering of actions
  143. _entityManager.DeleteEntity(actionId);
  144. return upgradedActionId.Value;
  145. }
  146. private void RaiseActionUpgradeEvent(int level, EntityUid actionId)
  147. {
  148. var ev = new ActionUpgradeEvent(level, actionId);
  149. RaiseLocalEvent(actionId, ev);
  150. }
  151. public bool TryGetActionUpgrade(
  152. [NotNullWhen(true)] EntityUid? uid,
  153. [NotNullWhen(true)] out ActionUpgradeComponent? result,
  154. bool logError = true)
  155. {
  156. result = null;
  157. if (!Exists(uid))
  158. return false;
  159. if (!TryComp<ActionUpgradeComponent>(uid, out var actionUpgradeComponent))
  160. {
  161. Log.Error($"Failed to get action upgrade from action entity: {ToPrettyString(uid.Value)}");
  162. return false;
  163. }
  164. result = actionUpgradeComponent;
  165. DebugTools.AssertOwner(uid, result);
  166. return true;
  167. }
  168. }