DumpableSystem.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. using System.Linq;
  2. using Content.Shared.Disposal;
  3. using Content.Shared.DoAfter;
  4. using Content.Shared.Interaction;
  5. using Content.Shared.Item;
  6. using Content.Shared.Placeable;
  7. using Content.Shared.Storage.Components;
  8. using Content.Shared.Verbs;
  9. using Robust.Shared.Audio.Systems;
  10. using Robust.Shared.Containers;
  11. using Robust.Shared.Prototypes;
  12. using Robust.Shared.Random;
  13. using Robust.Shared.Utility;
  14. namespace Content.Shared.Storage.EntitySystems;
  15. public sealed class DumpableSystem : EntitySystem
  16. {
  17. [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
  18. [Dependency] private readonly IRobustRandom _random = default!;
  19. [Dependency] private readonly SharedAudioSystem _audio = default!;
  20. [Dependency] private readonly SharedDisposalUnitSystem _disposalUnitSystem = default!;
  21. [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
  22. [Dependency] private readonly SharedTransformSystem _transformSystem = default!;
  23. private EntityQuery<ItemComponent> _itemQuery;
  24. public override void Initialize()
  25. {
  26. base.Initialize();
  27. _itemQuery = GetEntityQuery<ItemComponent>();
  28. SubscribeLocalEvent<DumpableComponent, AfterInteractEvent>(OnAfterInteract, after: new[]{ typeof(SharedEntityStorageSystem) });
  29. SubscribeLocalEvent<DumpableComponent, GetVerbsEvent<AlternativeVerb>>(AddDumpVerb);
  30. SubscribeLocalEvent<DumpableComponent, GetVerbsEvent<UtilityVerb>>(AddUtilityVerbs);
  31. SubscribeLocalEvent<DumpableComponent, DumpableDoAfterEvent>(OnDoAfter);
  32. }
  33. private void OnAfterInteract(EntityUid uid, DumpableComponent component, AfterInteractEvent args)
  34. {
  35. if (!args.CanReach || args.Handled)
  36. return;
  37. if (!_disposalUnitSystem.HasDisposals(args.Target) && !HasComp<PlaceableSurfaceComponent>(args.Target))
  38. return;
  39. if (!TryComp<StorageComponent>(uid, out var storage))
  40. return;
  41. if (!storage.Container.ContainedEntities.Any())
  42. return;
  43. StartDoAfter(uid, args.Target.Value, args.User, component);
  44. args.Handled = true;
  45. }
  46. private void AddDumpVerb(EntityUid uid, DumpableComponent dumpable, GetVerbsEvent<AlternativeVerb> args)
  47. {
  48. if (!args.CanAccess || !args.CanInteract)
  49. return;
  50. if (!TryComp<StorageComponent>(uid, out var storage) || !storage.Container.ContainedEntities.Any())
  51. return;
  52. AlternativeVerb verb = new()
  53. {
  54. Act = () =>
  55. {
  56. StartDoAfter(uid, args.Target, args.User, dumpable);//Had multiplier of 0.6f
  57. },
  58. Text = Loc.GetString("dump-verb-name"),
  59. Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/drop.svg.192dpi.png")),
  60. };
  61. args.Verbs.Add(verb);
  62. }
  63. private void AddUtilityVerbs(EntityUid uid, DumpableComponent dumpable, GetVerbsEvent<UtilityVerb> args)
  64. {
  65. if (!args.CanAccess || !args.CanInteract)
  66. return;
  67. if (!TryComp<StorageComponent>(uid, out var storage) || !storage.Container.ContainedEntities.Any())
  68. return;
  69. if (_disposalUnitSystem.HasDisposals(args.Target))
  70. {
  71. UtilityVerb verb = new()
  72. {
  73. Act = () =>
  74. {
  75. StartDoAfter(uid, args.Target, args.User, dumpable);
  76. },
  77. Text = Loc.GetString("dump-disposal-verb-name", ("unit", args.Target)),
  78. IconEntity = GetNetEntity(uid)
  79. };
  80. args.Verbs.Add(verb);
  81. }
  82. if (HasComp<PlaceableSurfaceComponent>(args.Target))
  83. {
  84. UtilityVerb verb = new()
  85. {
  86. Act = () =>
  87. {
  88. StartDoAfter(uid, args.Target, args.User, dumpable);
  89. },
  90. Text = Loc.GetString("dump-placeable-verb-name", ("surface", args.Target)),
  91. IconEntity = GetNetEntity(uid)
  92. };
  93. args.Verbs.Add(verb);
  94. }
  95. }
  96. private void StartDoAfter(EntityUid storageUid, EntityUid targetUid, EntityUid userUid, DumpableComponent dumpable)
  97. {
  98. if (!TryComp<StorageComponent>(storageUid, out var storage))
  99. return;
  100. var delay = 0f;
  101. foreach (var entity in storage.Container.ContainedEntities)
  102. {
  103. if (!_itemQuery.TryGetComponent(entity, out var itemComp) ||
  104. !_prototypeManager.TryIndex(itemComp.Size, out var itemSize))
  105. {
  106. continue;
  107. }
  108. delay += itemSize.Weight;
  109. }
  110. delay *= (float) dumpable.DelayPerItem.TotalSeconds * dumpable.Multiplier;
  111. _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, userUid, delay, new DumpableDoAfterEvent(), storageUid, target: targetUid, used: storageUid)
  112. {
  113. BreakOnMove = true,
  114. NeedHand = true,
  115. });
  116. }
  117. private void OnDoAfter(EntityUid uid, DumpableComponent component, DumpableDoAfterEvent args)
  118. {
  119. if (args.Handled || args.Cancelled || !TryComp<StorageComponent>(uid, out var storage) || storage.Container.ContainedEntities.Count == 0)
  120. return;
  121. var dumpQueue = new Queue<EntityUid>(storage.Container.ContainedEntities);
  122. var dumped = false;
  123. if (_disposalUnitSystem.HasDisposals(args.Args.Target))
  124. {
  125. dumped = true;
  126. foreach (var entity in dumpQueue)
  127. {
  128. _disposalUnitSystem.DoInsertDisposalUnit(args.Args.Target.Value, entity, args.Args.User);
  129. }
  130. }
  131. else if (HasComp<PlaceableSurfaceComponent>(args.Args.Target))
  132. {
  133. dumped = true;
  134. var (targetPos, targetRot) = _transformSystem.GetWorldPositionRotation(args.Args.Target.Value);
  135. foreach (var entity in dumpQueue)
  136. {
  137. _transformSystem.SetWorldPositionRotation(entity, targetPos + _random.NextVector2Box() / 4, targetRot);
  138. }
  139. }
  140. else
  141. {
  142. var targetPos = _transformSystem.GetWorldPosition(uid);
  143. foreach (var entity in dumpQueue)
  144. {
  145. var transform = Transform(entity);
  146. _transformSystem.SetWorldPositionRotation(entity, targetPos + _random.NextVector2Box() / 4, _random.NextAngle(), transform);
  147. }
  148. }
  149. if (dumped)
  150. {
  151. _audio.PlayPredicted(component.DumpSound, uid, args.User);
  152. }
  153. }
  154. }