1
0

DamageVisualsComponent.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. using Content.Shared.FixedPoint;
  2. namespace Content.Client.Damage;
  3. [RegisterComponent]
  4. public sealed partial class DamageVisualsComponent : Component
  5. {
  6. /// <summary>
  7. /// Damage thresholds between damage state changes.
  8. ///
  9. /// If there are any negative thresholds, or there is
  10. /// less than one threshold, the visualizer is marked
  11. /// as invalid.
  12. /// </summary>
  13. /// <remarks>
  14. /// A 'zeroth' threshold is automatically added,
  15. /// and this list is automatically sorted for
  16. /// efficiency beforehand. As such, the zeroth
  17. /// threshold is not required - and negative
  18. /// thresholds are automatically caught as
  19. /// invalid. The zeroth threshold automatically
  20. /// sets all layers to invisible, so a sprite
  21. /// isn't required for it.
  22. /// </remarks>
  23. [DataField("thresholds", required: true)]
  24. public List<FixedPoint2> Thresholds = new();
  25. /// <summary>
  26. /// Layers to target, by layerMapKey.
  27. /// If a target layer map key is invalid
  28. /// (in essence, undefined), then the target
  29. /// layer is removed from the list for efficiency.
  30. ///
  31. /// If no layers are valid, then the visualizer
  32. /// is marked as invalid.
  33. ///
  34. /// If this is not defined, however, the visualizer
  35. /// instead adds an overlay to the sprite.
  36. /// </summary>
  37. /// <remarks>
  38. /// Layers can be disabled here by passing
  39. /// the layer's name as a key to SetData,
  40. /// and passing in a bool set to either 'false'
  41. /// to disable it, or 'true' to enable it.
  42. /// Setting the layer as disabled will make it
  43. /// completely invisible.
  44. /// </remarks>
  45. [DataField("targetLayers")] public List<Enum>? TargetLayers;
  46. /// <summary>
  47. /// The actual sprites for every damage group
  48. /// that the entity should display visually.
  49. ///
  50. /// This is keyed by a damage group identifier
  51. /// (for example, Brute), and has a value
  52. /// of a DamageVisualizerSprite (see below)
  53. /// </summary>
  54. [DataField("damageOverlayGroups")] public Dictionary<string, DamageVisualizerSprite>? DamageOverlayGroups;
  55. /// <summary>
  56. /// Sets if you want sprites to overlay the
  57. /// entity when damaged, or if you would
  58. /// rather have each target layer's state
  59. /// replaced by a different state
  60. /// within its RSI.
  61. ///
  62. /// This cannot be set to false if:
  63. /// - There are no target layers
  64. /// - There is no damage group
  65. /// </summary>
  66. [DataField("overlay")] public bool Overlay = true;
  67. /// <summary>
  68. /// A single damage group to target.
  69. /// This should only be defined if
  70. /// overlay is set to false.
  71. /// If this is defined with damageSprites,
  72. /// this will be ignored.
  73. /// </summary>
  74. /// <remarks>
  75. /// This is here because otherwise,
  76. /// you would need several permutations
  77. /// of group sprites depending on
  78. /// what kind of damage combination
  79. /// you would want, on which threshold.
  80. /// </remarks>
  81. [DataField("damageGroup")] public string? DamageGroup;
  82. /// <summary>
  83. /// Set this if you want incoming damage to be
  84. /// divided.
  85. /// </summary>
  86. /// <remarks>
  87. /// This is more useful if you have similar
  88. /// damage sprites in between entities,
  89. /// but with different damage thresholds
  90. /// and you want to avoid duplicating
  91. /// these sprites.
  92. /// </remarks>
  93. [DataField("damageDivisor")] public float Divisor = 1;
  94. /// <summary>
  95. /// Set this to track all damage, instead of specific groups.
  96. /// </summary>
  97. /// <remarks>
  98. /// This will only work if you have damageOverlay
  99. /// defined - otherwise, it will not work.
  100. /// </remarks>
  101. [DataField("trackAllDamage")] public bool TrackAllDamage;
  102. /// <summary>
  103. /// This is the overlay sprite used, if _trackAllDamage is
  104. /// enabled. Supports no complex per-group layering,
  105. /// just an actually simple damage overlay. See
  106. /// DamageVisualizerSprite for more information.
  107. /// </summary>
  108. [DataField("damageOverlay")] public DamageVisualizerSprite? DamageOverlay;
  109. public readonly List<Enum> TargetLayerMapKeys = new();
  110. public bool Disabled = false;
  111. public bool Valid = true;
  112. public FixedPoint2 LastDamageThreshold = FixedPoint2.Zero;
  113. public readonly Dictionary<object, bool> DisabledLayers = new();
  114. public readonly Dictionary<object, string> LayerMapKeyStates = new();
  115. public readonly Dictionary<string, FixedPoint2> LastThresholdPerGroup = new();
  116. public string TopMostLayerKey = default!;
  117. }
  118. // deals with the edge case of human damage visuals not
  119. // being in color without making a Dict<Dict<Dict<Dict<Dict<Dict...
  120. [DataDefinition]
  121. public sealed partial class DamageVisualizerSprite
  122. {
  123. /// <summary>
  124. /// The RSI path for the damage visualizer
  125. /// group overlay.
  126. /// </summary>
  127. /// <remarks>
  128. /// States in here will require one of four
  129. /// forms:
  130. ///
  131. /// If tracking damage groups:
  132. /// - {base_state}_{group}_{threshold} if targeting
  133. /// a static layer on a sprite (either as an
  134. /// overlay or as a state change)
  135. /// - DamageOverlay_{group}_{threshold} if not
  136. /// targeting a layer on a sprite.
  137. ///
  138. /// If not tracking damage groups:
  139. /// - {base_state}_{threshold} if it is targeting
  140. /// a layer
  141. /// - DamageOverlay_{threshold} if not targeting
  142. /// a layer.
  143. /// </remarks>
  144. [DataField("sprite", required: true)] public string Sprite = default!;
  145. /// <summary>
  146. /// The color of this sprite overlay.
  147. /// Supports only hexadecimal format.
  148. /// </summary>
  149. [DataField("color")] public string? Color;
  150. }