NukeComponent.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. using System.Threading;
  2. using Content.Server.Explosion.EntitySystems;
  3. using Content.Shared.Containers.ItemSlots;
  4. using Content.Shared.Explosion;
  5. using Content.Shared.Nuke;
  6. using Robust.Shared.Audio;
  7. using Robust.Shared.Map;
  8. using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
  9. namespace Content.Server.Nuke
  10. {
  11. /// <summary>
  12. /// Nuclear device that can devastate an entire station.
  13. /// Basically a station self-destruction mechanism.
  14. /// To activate it, user needs to insert an authorization disk and enter a secret code.
  15. /// </summary>
  16. [RegisterComponent]
  17. [Access(typeof(NukeSystem))]
  18. public sealed partial class NukeComponent : SharedNukeComponent
  19. {
  20. /// <summary>
  21. /// Default bomb timer value in seconds.
  22. /// </summary>
  23. [DataField("timer")]
  24. [ViewVariables(VVAccess.ReadWrite)]
  25. public int Timer = 300;
  26. /// <summary>
  27. /// If the nuke is disarmed, this sets the minimum amount of time the timer can have.
  28. /// The remaining time will reset to this value if it is below it.
  29. /// </summary>
  30. [DataField]
  31. public int MinimumTime = 180;
  32. /// <summary>
  33. /// How long until the bomb can arm again after deactivation.
  34. /// Used to prevent announcements spam.
  35. /// </summary>
  36. [DataField("cooldown")]
  37. public int Cooldown = 30;
  38. /// <summary>
  39. /// The <see cref="ItemSlot"/> that stores the nuclear disk. The entity whitelist, sounds, and some other
  40. /// behaviours are specified by this <see cref="ItemSlot"/> definition. Make sure the whitelist, is correct
  41. /// otherwise a blank bit of paper will work as a "disk".
  42. /// </summary>
  43. [DataField("diskSlot")]
  44. public ItemSlot DiskSlot = new();
  45. /// <summary>
  46. /// When this time is left, nuke will play last alert sound
  47. /// </summary>
  48. [DataField("alertTime")]
  49. public float AlertSoundTime = 10.0f;
  50. /// <summary>
  51. /// How long a user must wait to disarm the bomb.
  52. /// </summary>
  53. [DataField("disarmDoafterLength")]
  54. public float DisarmDoafterLength = 30.0f;
  55. [DataField("alertLevelOnActivate")] public string AlertLevelOnActivate = default!;
  56. [DataField("alertLevelOnDeactivate")] public string AlertLevelOnDeactivate = default!;
  57. /// <summary>
  58. /// This is stored so we can do a funny by making 0 shift the last played note up by 12 semitones (octave)
  59. /// </summary>
  60. public int LastPlayedKeypadSemitones = 0;
  61. [DataField("keypadPressSound")]
  62. public SoundSpecifier KeypadPressSound = new SoundPathSpecifier("/Audio/Machines/Nuke/general_beep.ogg");
  63. [DataField("accessGrantedSound")]
  64. public SoundSpecifier AccessGrantedSound = new SoundPathSpecifier("/Audio/Machines/Nuke/confirm_beep.ogg");
  65. [DataField("accessDeniedSound")]
  66. public SoundSpecifier AccessDeniedSound = new SoundPathSpecifier("/Audio/Machines/Nuke/angry_beep.ogg");
  67. [DataField("alertSound")]
  68. public SoundSpecifier AlertSound = new SoundPathSpecifier("/Audio/Machines/Nuke/nuke_alarm.ogg");
  69. [DataField("armSound")]
  70. public SoundSpecifier ArmSound = new SoundPathSpecifier("/Audio/Misc/notice1.ogg");
  71. [DataField("disarmSound")]
  72. public SoundSpecifier DisarmSound = new SoundPathSpecifier("/Audio/Misc/notice2.ogg");
  73. [DataField("armMusic")]
  74. public SoundSpecifier ArmMusic = new SoundCollectionSpecifier("NukeMusic");
  75. // These datafields here are duplicates of those in explosive component. But I'm hesitant to use explosive
  76. // component, just in case at some point, somehow, when grenade crafting added in someone manages to wire up a
  77. // proximity trigger or something to the nuke and set it off prematurely. I want to make sure they MEAN to set of
  78. // the nuke.
  79. #region ExplosiveComponent
  80. /// <summary>
  81. /// The explosion prototype. This determines the damage types, the tile-break chance, and some visual
  82. /// information (e.g., the light that the explosion gives off).
  83. /// </summary>
  84. [ViewVariables(VVAccess.ReadWrite)]
  85. [DataField("explosionType", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<ExplosionPrototype>))]
  86. public string ExplosionType = default!;
  87. /// <summary>
  88. /// The maximum intensity the explosion can have on a single time. This limits the maximum damage and tile
  89. /// break chance the explosion can achieve at any given location.
  90. /// </summary>
  91. [ViewVariables(VVAccess.ReadWrite)]
  92. [DataField("maxIntensity")]
  93. public float MaxIntensity = 100;
  94. /// <summary>
  95. /// How quickly the intensity drops off as you move away from the epicenter.
  96. /// </summary>
  97. [ViewVariables(VVAccess.ReadWrite)]
  98. [DataField("intensitySlope")]
  99. public float IntensitySlope = 5;
  100. /// <summary>
  101. /// The total intensity of this explosion. The radius of the explosion scales like the cube root of this
  102. /// number (see <see cref="ExplosionSystem.RadiusToIntensity"/>).
  103. /// </summary>
  104. [ViewVariables(VVAccess.ReadWrite)]
  105. [DataField("totalIntensity")]
  106. public float TotalIntensity = 100000;
  107. /// <summary>
  108. /// Avoid somehow double-triggering this explosion.
  109. /// </summary>
  110. public bool Exploded;
  111. #endregion
  112. /// <summary>
  113. /// Origin station of this bomb, if it exists.
  114. /// If this doesn't exist, then the origin grid and map will be filled in, instead.
  115. /// </summary>
  116. public EntityUid? OriginStation;
  117. /// <summary>
  118. /// Origin map and grid of this bomb.
  119. /// If a station wasn't tied to a given grid when the bomb was spawned,
  120. /// this will be filled in instead.
  121. /// </summary>
  122. public (MapId, EntityUid?)? OriginMapGrid;
  123. [DataField("codeLength")] public int CodeLength = 6;
  124. [ViewVariables] public string Code = string.Empty;
  125. /// <summary>
  126. /// Time until explosion in seconds.
  127. /// </summary>
  128. [ViewVariables(VVAccess.ReadWrite)]
  129. public float RemainingTime;
  130. /// <summary>
  131. /// Time until bomb cooldown will expire in seconds.
  132. /// </summary>
  133. [ViewVariables]
  134. public float CooldownTime;
  135. /// <summary>
  136. /// Current nuclear code buffer. Entered manually by players.
  137. /// If valid it will allow arm/disarm bomb.
  138. /// </summary>
  139. [ViewVariables]
  140. public string EnteredCode = "";
  141. /// <summary>
  142. /// Current status of a nuclear bomb.
  143. /// </summary>
  144. [ViewVariables]
  145. public NukeStatus Status = NukeStatus.AWAIT_DISK;
  146. /// <summary>
  147. /// Check if nuke has already played the nuke song so we don't do it again
  148. /// </summary>
  149. public bool PlayedNukeSong = false;
  150. /// <summary>
  151. /// Check if nuke has already played last alert sound
  152. /// </summary>
  153. public bool PlayedAlertSound = false;
  154. public EntityUid? AlertAudioStream = default;
  155. /// <summary>
  156. /// The radius from the nuke for which there must be floor tiles for it to be anchorable.
  157. /// </summary>
  158. [ViewVariables(VVAccess.ReadWrite)]
  159. [DataField("requiredFloorRadius")]
  160. public float RequiredFloorRadius = 5;
  161. }
  162. }