1
0

StealConditionSystem.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. using Content.Server.Objectives.Components;
  2. using Content.Shared.CartridgeLoader;
  3. using Content.Shared.Interaction;
  4. using Content.Shared.Mind;
  5. using Content.Shared.Objectives.Components;
  6. using Content.Shared.Objectives.Systems;
  7. using Robust.Shared.Containers;
  8. using Robust.Shared.Prototypes;
  9. using Robust.Shared.Random;
  10. using Content.Shared.Mind.Components;
  11. using Content.Shared.Mobs.Systems;
  12. using Content.Shared.Mobs.Components;
  13. using Content.Shared.Movement.Pulling.Components;
  14. using Content.Shared.Stacks;
  15. namespace Content.Server.Objectives.Systems;
  16. public sealed class StealConditionSystem : EntitySystem
  17. {
  18. [Dependency] private readonly IRobustRandom _random = default!;
  19. [Dependency] private readonly IPrototypeManager _proto = default!;
  20. [Dependency] private readonly MetaDataSystem _metaData = default!;
  21. [Dependency] private readonly MobStateSystem _mobState = default!;
  22. [Dependency] private readonly SharedInteractionSystem _interaction = default!;
  23. [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
  24. [Dependency] private readonly EntityLookupSystem _lookup = default!;
  25. private EntityQuery<ContainerManagerComponent> _containerQuery;
  26. private HashSet<Entity<TransformComponent>> _nearestEnts = new();
  27. private HashSet<EntityUid> _countedItems = new();
  28. public override void Initialize()
  29. {
  30. base.Initialize();
  31. _containerQuery = GetEntityQuery<ContainerManagerComponent>();
  32. SubscribeLocalEvent<StealConditionComponent, ObjectiveAssignedEvent>(OnAssigned);
  33. SubscribeLocalEvent<StealConditionComponent, ObjectiveAfterAssignEvent>(OnAfterAssign);
  34. SubscribeLocalEvent<StealConditionComponent, ObjectiveGetProgressEvent>(OnGetProgress);
  35. }
  36. /// start checks of target acceptability, and generation of start values.
  37. private void OnAssigned(Entity<StealConditionComponent> condition, ref ObjectiveAssignedEvent args)
  38. {
  39. List<StealTargetComponent?> targetList = new();
  40. var query = AllEntityQuery<StealTargetComponent>();
  41. while (query.MoveNext(out var target))
  42. {
  43. if (condition.Comp.StealGroup != target.StealGroup)
  44. continue;
  45. targetList.Add(target);
  46. }
  47. // cancel if the required items do not exist
  48. if (targetList.Count == 0 && condition.Comp.VerifyMapExistence)
  49. {
  50. args.Cancelled = true;
  51. return;
  52. }
  53. //setup condition settings
  54. var maxSize = condition.Comp.VerifyMapExistence
  55. ? Math.Min(targetList.Count, condition.Comp.MaxCollectionSize)
  56. : condition.Comp.MaxCollectionSize;
  57. var minSize = condition.Comp.VerifyMapExistence
  58. ? Math.Min(targetList.Count, condition.Comp.MinCollectionSize)
  59. : condition.Comp.MinCollectionSize;
  60. condition.Comp.CollectionSize = _random.Next(minSize, maxSize);
  61. }
  62. //Set the visual, name, icon for the objective.
  63. private void OnAfterAssign(Entity<StealConditionComponent> condition, ref ObjectiveAfterAssignEvent args)
  64. {
  65. var group = _proto.Index(condition.Comp.StealGroup);
  66. string localizedName = Loc.GetString(group.Name);
  67. var title =condition.Comp.OwnerText == null
  68. ? Loc.GetString(condition.Comp.ObjectiveNoOwnerText, ("itemName", localizedName))
  69. : Loc.GetString(condition.Comp.ObjectiveText, ("owner", Loc.GetString(condition.Comp.OwnerText)), ("itemName", localizedName));
  70. var description = condition.Comp.CollectionSize > 1
  71. ? Loc.GetString(condition.Comp.DescriptionMultiplyText, ("itemName", localizedName), ("count", condition.Comp.CollectionSize))
  72. : Loc.GetString(condition.Comp.DescriptionText, ("itemName", localizedName));
  73. _metaData.SetEntityName(condition.Owner, title, args.Meta);
  74. _metaData.SetEntityDescription(condition.Owner, description, args.Meta);
  75. _objectives.SetIcon(condition.Owner, group.Sprite, args.Objective);
  76. }
  77. private void OnGetProgress(Entity<StealConditionComponent> condition, ref ObjectiveGetProgressEvent args)
  78. {
  79. args.Progress = GetProgress(args.Mind, condition);
  80. }
  81. private float GetProgress(MindComponent mind, StealConditionComponent condition)
  82. {
  83. if (!_containerQuery.TryGetComponent(mind.OwnedEntity, out var currentManager))
  84. return 0;
  85. var containerStack = new Stack<ContainerManagerComponent>();
  86. var count = 0;
  87. _countedItems.Clear();
  88. //check stealAreas
  89. if (condition.CheckStealAreas)
  90. {
  91. var areasQuery = AllEntityQuery<StealAreaComponent, TransformComponent>();
  92. while (areasQuery.MoveNext(out var uid, out var area, out var xform))
  93. {
  94. if (!area.Owners.Contains(mind.Owner))
  95. continue;
  96. _nearestEnts.Clear();
  97. _lookup.GetEntitiesInRange<TransformComponent>(xform.Coordinates, area.Range, _nearestEnts);
  98. foreach (var ent in _nearestEnts)
  99. {
  100. if (!_interaction.InRangeUnobstructed((uid, xform), (ent, ent.Comp), range: area.Range))
  101. continue;
  102. CheckEntity(ent, condition, ref containerStack, ref count);
  103. }
  104. }
  105. }
  106. //check pulling object
  107. if (TryComp<PullerComponent>(mind.OwnedEntity, out var pull)) //TO DO: to make the code prettier? don't like the repetition
  108. {
  109. var pulledEntity = pull.Pulling;
  110. if (pulledEntity != null)
  111. {
  112. CheckEntity(pulledEntity.Value, condition, ref containerStack, ref count);
  113. }
  114. }
  115. // recursively check each container for the item
  116. // checks inventory, bag, implants, etc.
  117. do
  118. {
  119. foreach (var container in currentManager.Containers.Values)
  120. {
  121. foreach (var entity in container.ContainedEntities)
  122. {
  123. // check if this is the item
  124. count += CheckStealTarget(entity, condition);
  125. // if it is a container check its contents
  126. if (_containerQuery.TryGetComponent(entity, out var containerManager))
  127. containerStack.Push(containerManager);
  128. }
  129. }
  130. } while (containerStack.TryPop(out currentManager));
  131. var result = count / (float) condition.CollectionSize;
  132. result = Math.Clamp(result, 0, 1);
  133. return result;
  134. }
  135. private void CheckEntity(EntityUid entity, StealConditionComponent condition, ref Stack<ContainerManagerComponent> containerStack, ref int counter)
  136. {
  137. // check if this is the item
  138. counter += CheckStealTarget(entity, condition);
  139. //we don't check the inventories of sentient entity
  140. if (!TryComp<MindContainerComponent>(entity, out var pullMind))
  141. {
  142. // if it is a container check its contents
  143. if (_containerQuery.TryGetComponent(entity, out var containerManager))
  144. containerStack.Push(containerManager);
  145. }
  146. }
  147. private int CheckStealTarget(EntityUid entity, StealConditionComponent condition)
  148. {
  149. if (_countedItems.Contains(entity))
  150. return 0;
  151. // check if this is the target
  152. if (!TryComp<StealTargetComponent>(entity, out var target))
  153. return 0;
  154. if (target.StealGroup != condition.StealGroup)
  155. return 0;
  156. // check if cartridge is installed
  157. if (TryComp<CartridgeComponent>(entity, out var cartridge) &&
  158. cartridge.InstallationStatus is not InstallationStatus.Cartridge)
  159. return 0;
  160. // check if needed target alive
  161. if (condition.CheckAlive)
  162. {
  163. if (TryComp<MobStateComponent>(entity, out var state))
  164. {
  165. if (!_mobState.IsAlive(entity, state))
  166. return 0;
  167. }
  168. }
  169. _countedItems.Add(entity);
  170. return TryComp<StackComponent>(entity, out var stack) ? stack.Count : 1;
  171. }
  172. }