BotanySystem.Seed.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. using Content.Server.Botany.Components;
  2. using Content.Server.Kitchen.Components;
  3. using Content.Server.Popups;
  4. using Content.Shared.Chemistry.EntitySystems;
  5. using Content.Shared.Botany;
  6. using Content.Shared.Examine;
  7. using Content.Shared.Hands.EntitySystems;
  8. using Content.Shared.Popups;
  9. using Content.Shared.Random;
  10. using Content.Shared.Random.Helpers;
  11. using Robust.Server.GameObjects;
  12. using Robust.Shared.Map;
  13. using Robust.Shared.Prototypes;
  14. using Robust.Shared.Random;
  15. using System.Diagnostics.CodeAnalysis;
  16. using System.Linq;
  17. namespace Content.Server.Botany.Systems;
  18. public sealed partial class BotanySystem : EntitySystem
  19. {
  20. [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
  21. [Dependency] private readonly IRobustRandom _robustRandom = default!;
  22. [Dependency] private readonly AppearanceSystem _appearance = default!;
  23. [Dependency] private readonly PopupSystem _popupSystem = default!;
  24. [Dependency] private readonly SharedHandsSystem _hands = default!;
  25. [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
  26. [Dependency] private readonly MetaDataSystem _metaData = default!;
  27. [Dependency] private readonly RandomHelperSystem _randomHelper = default!;
  28. public override void Initialize()
  29. {
  30. base.Initialize();
  31. SubscribeLocalEvent<SeedComponent, ExaminedEvent>(OnExamined);
  32. }
  33. public bool TryGetSeed(SeedComponent comp, [NotNullWhen(true)] out SeedData? seed)
  34. {
  35. if (comp.Seed != null)
  36. {
  37. seed = comp.Seed;
  38. return true;
  39. }
  40. if (comp.SeedId != null
  41. && _prototypeManager.TryIndex(comp.SeedId, out SeedPrototype? protoSeed))
  42. {
  43. seed = protoSeed;
  44. return true;
  45. }
  46. seed = null;
  47. return false;
  48. }
  49. public bool TryGetSeed(ProduceComponent comp, [NotNullWhen(true)] out SeedData? seed)
  50. {
  51. if (comp.Seed != null)
  52. {
  53. seed = comp.Seed;
  54. return true;
  55. }
  56. if (comp.SeedId != null
  57. && _prototypeManager.TryIndex(comp.SeedId, out SeedPrototype? protoSeed))
  58. {
  59. seed = protoSeed;
  60. return true;
  61. }
  62. seed = null;
  63. return false;
  64. }
  65. private void OnExamined(EntityUid uid, SeedComponent component, ExaminedEvent args)
  66. {
  67. if (!args.IsInDetailsRange)
  68. return;
  69. if (!TryGetSeed(component, out var seed))
  70. return;
  71. using (args.PushGroup(nameof(SeedComponent), 1))
  72. {
  73. var name = Loc.GetString(seed.DisplayName);
  74. args.PushMarkup(Loc.GetString($"seed-component-description", ("seedName", name)));
  75. args.PushMarkup(Loc.GetString($"seed-component-plant-yield-text", ("seedYield", seed.Yield)));
  76. args.PushMarkup(Loc.GetString($"seed-component-plant-potency-text", ("seedPotency", seed.Potency)));
  77. }
  78. }
  79. #region SeedPrototype prototype stuff
  80. /// <summary>
  81. /// Spawns a new seed packet on the floor at a position, then tries to put it in the user's hands if possible.
  82. /// </summary>
  83. public EntityUid SpawnSeedPacket(SeedData proto, EntityCoordinates coords, EntityUid user, float? healthOverride = null)
  84. {
  85. var seed = Spawn(proto.PacketPrototype, coords);
  86. var seedComp = EnsureComp<SeedComponent>(seed);
  87. seedComp.Seed = proto;
  88. seedComp.HealthOverride = healthOverride;
  89. var name = Loc.GetString(proto.Name);
  90. var noun = Loc.GetString(proto.Noun);
  91. var val = Loc.GetString("botany-seed-packet-name", ("seedName", name), ("seedNoun", noun));
  92. _metaData.SetEntityName(seed, val);
  93. // try to automatically place in user's other hand
  94. _hands.TryPickupAnyHand(user, seed);
  95. return seed;
  96. }
  97. public IEnumerable<EntityUid> AutoHarvest(SeedData proto, EntityCoordinates position, int yieldMod = 1)
  98. {
  99. if (position.IsValid(EntityManager) &&
  100. proto.ProductPrototypes.Count > 0)
  101. return GenerateProduct(proto, position, yieldMod);
  102. return Enumerable.Empty<EntityUid>();
  103. }
  104. public IEnumerable<EntityUid> Harvest(SeedData proto, EntityUid user, int yieldMod = 1)
  105. {
  106. if (proto.ProductPrototypes.Count == 0 || proto.Yield <= 0)
  107. {
  108. _popupSystem.PopupCursor(Loc.GetString("botany-harvest-fail-message"), user, PopupType.Medium);
  109. return Enumerable.Empty<EntityUid>();
  110. }
  111. var name = Loc.GetString(proto.DisplayName);
  112. _popupSystem.PopupCursor(Loc.GetString("botany-harvest-success-message", ("name", name)), user, PopupType.Medium);
  113. return GenerateProduct(proto, Transform(user).Coordinates, yieldMod);
  114. }
  115. public IEnumerable<EntityUid> GenerateProduct(SeedData proto, EntityCoordinates position, int yieldMod = 1)
  116. {
  117. var totalYield = 0;
  118. if (proto.Yield > -1)
  119. {
  120. if (yieldMod < 0)
  121. totalYield = proto.Yield;
  122. else
  123. totalYield = proto.Yield * yieldMod;
  124. totalYield = Math.Max(1, totalYield);
  125. }
  126. var products = new List<EntityUid>();
  127. if (totalYield > 1 || proto.HarvestRepeat != HarvestType.NoRepeat)
  128. proto.Unique = false;
  129. for (var i = 0; i < totalYield; i++)
  130. {
  131. var product = _robustRandom.Pick(proto.ProductPrototypes);
  132. var entity = Spawn(product, position);
  133. _randomHelper.RandomOffset(entity, 0.25f);
  134. products.Add(entity);
  135. var produce = EnsureComp<ProduceComponent>(entity);
  136. produce.Seed = proto;
  137. ProduceGrown(entity, produce);
  138. _appearance.SetData(entity, ProduceVisuals.Potency, proto.Potency);
  139. if (proto.Mysterious)
  140. {
  141. var metaData = MetaData(entity);
  142. _metaData.SetEntityName(entity, metaData.EntityName + "?", metaData);
  143. _metaData.SetEntityDescription(entity,
  144. metaData.EntityDescription + " " + Loc.GetString("botany-mysterious-description-addon"), metaData);
  145. }
  146. }
  147. return products;
  148. }
  149. public bool CanHarvest(SeedData proto, EntityUid? held = null)
  150. {
  151. return !proto.Ligneous || proto.Ligneous && held != null && HasComp<SharpComponent>(held);
  152. }
  153. #endregion
  154. }