AnomalyComponent.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. using System.Numerics;
  2. using Content.Shared.Anomaly.Effects;
  3. using Content.Shared.Anomaly.Prototypes;
  4. using Robust.Shared.Audio;
  5. using Robust.Shared.GameStates;
  6. using Robust.Shared.Prototypes;
  7. using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
  8. namespace Content.Shared.Anomaly.Components;
  9. /// <summary>
  10. /// This is used for tracking the general behavior of anomalies.
  11. /// This doesn't contain the specific implementations for what
  12. /// they do, just the generic behaviors associated with them.
  13. ///
  14. /// Anomalies and their related components were designed here: https://hackmd.io/@ss14-design/r1sQbkJOs
  15. /// </summary>
  16. [RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
  17. [Access(typeof(SharedAnomalySystem), typeof(SharedInnerBodyAnomalySystem))]
  18. public sealed partial class AnomalyComponent : Component
  19. {
  20. /// <summary>
  21. /// How likely an anomaly is to grow more dangerous. Moves both up and down.
  22. /// Ranges from 0 to 1.
  23. /// Values less than 0.5 indicate stability, whereas values greater
  24. /// than 0.5 indicate instability, which causes increases in severity.
  25. /// </summary>
  26. /// <remarks>
  27. /// Note that this doesn't refer to stability as a percentage: This is an arbitrary
  28. /// value that only matters in relation to the <see cref="GrowthThreshold"/> and <see cref="DecayThreshold"/>
  29. /// </remarks>
  30. [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
  31. public float Stability = 0f;
  32. /// <summary>
  33. /// How severe the effects of an anomaly are. Moves only upwards.
  34. /// Ranges from 0 to 1.
  35. /// A value of 0 indicates effects of extrememly minimal severity, whereas greater
  36. /// values indicate effects of linearly increasing severity.
  37. /// </summary>
  38. /// <remarks>
  39. /// Wacky-Stability scale lives on in my heart. - emo
  40. /// </remarks>
  41. [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
  42. public float Severity = 0f;
  43. #region Health
  44. /// <summary>
  45. /// The internal "health" of an anomaly.
  46. /// Ranges from 0 to 1.
  47. /// When the health of an anomaly reaches 0, it is destroyed without ever
  48. /// reaching a supercritical point.
  49. /// </summary>
  50. [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
  51. public float Health = 1f;
  52. /// <summary>
  53. /// If the <see cref="Stability"/> of the anomaly exceeds this value, it
  54. /// becomes too unstable to support itself and starts decreasing in <see cref="Health"/>.
  55. /// </summary>
  56. [DataField("decayhreshold"), ViewVariables(VVAccess.ReadWrite)]
  57. public float DecayThreshold = 0.15f;
  58. /// <summary>
  59. /// The amount of health lost when the stability is below the <see cref="DecayThreshold"/>
  60. /// </summary>
  61. [DataField("healthChangePerSecond"), ViewVariables(VVAccess.ReadWrite)]
  62. public float HealthChangePerSecond = -0.01f;
  63. #endregion
  64. #region Growth
  65. /// <summary>
  66. /// If the <see cref="Stability"/> of the anomaly exceeds this value, it
  67. /// becomes unstable and starts increasing in <see cref="Severity"/>.
  68. /// </summary>
  69. [DataField("growthThreshold"), ViewVariables(VVAccess.ReadWrite)]
  70. public float GrowthThreshold = 0.5f;
  71. /// <summary>
  72. /// A coefficient used for calculating the increase in severity when above the GrowthThreshold
  73. /// </summary>
  74. [DataField("severityGrowthCoefficient"), ViewVariables(VVAccess.ReadWrite)]
  75. public float SeverityGrowthCoefficient = 0.07f;
  76. #endregion
  77. #region Pulse
  78. /// <summary>
  79. /// The time at which the next artifact pulse will occur.
  80. /// </summary>
  81. [DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField, AutoPausedField]
  82. [ViewVariables(VVAccess.ReadWrite)]
  83. public TimeSpan NextPulseTime = TimeSpan.Zero;
  84. /// <summary>
  85. /// The minimum interval between pulses.
  86. /// </summary>
  87. [DataField]
  88. public TimeSpan MinPulseLength = TimeSpan.FromMinutes(2);
  89. /// <summary>
  90. /// The maximum interval between pulses.
  91. /// </summary>
  92. [DataField]
  93. public TimeSpan MaxPulseLength = TimeSpan.FromMinutes(4);
  94. /// <summary>
  95. /// A percentage by which the length of a pulse might vary.
  96. /// </summary>
  97. [DataField]
  98. public float PulseVariation = 0.1f;
  99. /// <summary>
  100. /// The range that an anomaly's stability can vary each pulse. Scales with severity.
  101. /// </summary>
  102. /// <remarks>
  103. /// This is more likely to trend upwards than donwards, because that's funny
  104. /// </remarks>
  105. [DataField]
  106. public Vector2 PulseStabilityVariation = new(-0.1f, 0.15f);
  107. /// <summary>
  108. /// The sound played when an anomaly pulses
  109. /// </summary>
  110. [DataField]
  111. public SoundSpecifier? PulseSound = new SoundCollectionSpecifier("RadiationPulse");
  112. /// <summary>
  113. /// The sound plays when an anomaly goes supercritical
  114. /// </summary>
  115. [DataField]
  116. public SoundSpecifier? SupercriticalSound = new SoundCollectionSpecifier("Explosion");
  117. #endregion
  118. /// <summary>
  119. /// The range of initial values for stability
  120. /// </summary>
  121. /// <remarks>
  122. /// +/- 0.2 from perfect stability (0.5)
  123. /// </remarks>
  124. [DataField]
  125. public (float, float) InitialStabilityRange = (0.4f, 0.6f);
  126. /// <summary>
  127. /// The range of initial values for severity
  128. /// </summary>
  129. /// <remarks>
  130. /// Between 0 and 0.5, which should be all mild effects
  131. /// </remarks>
  132. [DataField]
  133. public (float, float) InitialSeverityRange = (0.1f, 0.5f);
  134. /// <summary>
  135. /// The particle type that increases the severity of the anomaly.
  136. /// </summary>
  137. [DataField, AutoNetworkedField]
  138. public AnomalousParticleType SeverityParticleType;
  139. /// <summary>
  140. /// The particle type that destabilizes the anomaly.
  141. /// </summary>
  142. [DataField, AutoNetworkedField]
  143. public AnomalousParticleType DestabilizingParticleType;
  144. /// <summary>
  145. /// The particle type that weakens the anomalys health.
  146. /// </summary>
  147. [DataField, AutoNetworkedField]
  148. public AnomalousParticleType WeakeningParticleType;
  149. /// <summary>
  150. /// The particle type that change anomaly behaviour.
  151. /// </summary>
  152. [DataField, AutoNetworkedField]
  153. public AnomalousParticleType TransformationParticleType;
  154. #region Points and Vessels
  155. /// <summary>
  156. /// The vessel that the anomaly is connceted to. Stored so that multiple
  157. /// vessels cannot connect to the same anomaly.
  158. /// </summary>
  159. [ViewVariables(VVAccess.ReadWrite)]
  160. public EntityUid? ConnectedVessel;
  161. /// <summary>
  162. /// The minimum amount of research points generated per second
  163. /// </summary>
  164. [DataField]
  165. public int MinPointsPerSecond = 10;
  166. /// <summary>
  167. /// The maximum amount of research points generated per second
  168. /// This doesn't include the point bonus for being unstable.
  169. /// </summary>
  170. [DataField]
  171. public int MaxPointsPerSecond = 70;
  172. /// <summary>
  173. /// The multiplier applied to the point value for the
  174. /// anomaly being above the <see cref="GrowthThreshold"/>
  175. /// </summary>
  176. [DataField]
  177. public float GrowingPointMultiplier = 1.5f;
  178. #endregion
  179. /// <summary>
  180. /// A prototype entity that appears when an anomaly supercrit collapse.
  181. /// </summary>
  182. [DataField, ViewVariables(VVAccess.ReadWrite)]
  183. public EntProtoId? CorePrototype;
  184. /// <summary>
  185. /// A prototype entity that appears when an anomaly decays.
  186. /// </summary>
  187. [DataField, ViewVariables(VVAccess.ReadWrite)]
  188. public EntProtoId? CoreInertPrototype;
  189. #region Behavior Deviations
  190. [DataField]
  191. public ProtoId<AnomalyBehaviorPrototype>? CurrentBehavior;
  192. /// <summary>
  193. /// Presumption of anomaly to change behavior. The higher the number, the higher the chance that the anomaly will change its behavior.
  194. /// </summary>
  195. [DataField]
  196. public float Continuity = 0f;
  197. /// <summary>
  198. /// Minimum contituty probability chance, that can be selected by anomaly on MapInit
  199. /// </summary>
  200. [DataField]
  201. public float MinContituty = 0.1f;
  202. /// <summary>
  203. /// Maximum contituty probability chance, that can be selected by anomaly on MapInit
  204. /// </summary>
  205. [DataField]
  206. public float MaxContituty = 1.0f;
  207. #endregion
  208. #region Floating Animation
  209. /// <summary>
  210. /// How long it takes to go from the bottom of the animation to the top.
  211. /// </summary>
  212. [ViewVariables(VVAccess.ReadWrite)]
  213. [DataField("animationTime")]
  214. public float AnimationTime = 2f;
  215. /// <summary>
  216. /// How far it goes in any direction.
  217. /// </summary>
  218. [ViewVariables(VVAccess.ReadWrite)]
  219. [DataField("offset")]
  220. public Vector2 FloatingOffset = new(0, 0);
  221. public readonly string AnimationKey = "anomalyfloat";
  222. #endregion
  223. [DataField]
  224. public bool DeleteEntity = true;
  225. }
  226. /// <summary>
  227. /// Event raised at regular intervals on an anomaly to do whatever its effect is.
  228. /// </summary>
  229. /// <param name="Anomaly">The anomaly pulsing</param>
  230. /// <param name="Stability"></param>
  231. /// <param name="Severity"></param>
  232. [ByRefEvent]
  233. public readonly record struct AnomalyPulseEvent(EntityUid Anomaly, float Stability, float Severity, float PowerModifier);
  234. /// <summary>
  235. /// Event raised on an anomaly when it reaches a supercritical point.
  236. /// </summary>
  237. [ByRefEvent]
  238. public readonly record struct AnomalySupercriticalEvent(EntityUid Anomaly, float PowerModifier);
  239. /// <summary>
  240. /// Event broadcast after an anomaly goes supercritical
  241. /// </summary>
  242. /// <param name="Anomaly">The anomaly being shut down.</param>
  243. /// <param name="Supercritical">Whether or not the anomaly shut down passively or via a supercritical event.</param>
  244. [ByRefEvent]
  245. public readonly record struct AnomalyShutdownEvent(EntityUid Anomaly, bool Supercritical);
  246. /// <summary>
  247. /// Event broadcast when an anomaly's severity is changed.
  248. /// </summary>
  249. /// <param name="Anomaly">The anomaly being changed</param>
  250. [ByRefEvent]
  251. public readonly record struct AnomalySeverityChangedEvent(EntityUid Anomaly, float Stability, float Severity);
  252. /// <summary>
  253. /// Event broadcast when an anomaly's stability is changed.
  254. /// </summary>
  255. [ByRefEvent]
  256. public readonly record struct AnomalyStabilityChangedEvent(EntityUid Anomaly, float Stability, float Severity);
  257. /// <summary>
  258. /// Event broadcast when an anomaly's health is changed.
  259. /// </summary>
  260. /// <param name="Anomaly">The anomaly being changed</param>
  261. [ByRefEvent]
  262. public readonly record struct AnomalyHealthChangedEvent(EntityUid Anomaly, float Health);
  263. /// <summary>
  264. /// Event broadcast when an anomaly's behavior is changed.
  265. /// This is raised after the relevant components are applied
  266. /// </summary>
  267. [ByRefEvent]
  268. public readonly record struct AnomalyBehaviorChangedEvent(EntityUid Anomaly, ProtoId<AnomalyBehaviorPrototype>? Old, ProtoId<AnomalyBehaviorPrototype>? New);