HolopadSystem.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. using Content.Shared.Chat.TypingIndicator;
  2. using Content.Shared.Holopad;
  3. using Robust.Client.GameObjects;
  4. using Robust.Client.Graphics;
  5. using Robust.Shared.Prototypes;
  6. using Robust.Shared.Timing;
  7. using System.Linq;
  8. using DrawDepth = Content.Shared.DrawDepth.DrawDepth;
  9. namespace Content.Client.Holopad;
  10. public sealed class HolopadSystem : SharedHolopadSystem
  11. {
  12. [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
  13. [Dependency] private readonly IGameTiming _timing = default!;
  14. public override void Initialize()
  15. {
  16. base.Initialize();
  17. SubscribeLocalEvent<HolopadHologramComponent, ComponentStartup>(OnComponentStartup);
  18. SubscribeLocalEvent<HolopadHologramComponent, BeforePostShaderRenderEvent>(OnShaderRender);
  19. SubscribeAllEvent<TypingChangedEvent>(OnTypingChanged);
  20. }
  21. private void OnComponentStartup(Entity<HolopadHologramComponent> entity, ref ComponentStartup ev)
  22. {
  23. UpdateHologramSprite(entity, entity.Comp.LinkedEntity);
  24. }
  25. private void OnShaderRender(Entity<HolopadHologramComponent> entity, ref BeforePostShaderRenderEvent ev)
  26. {
  27. if (ev.Sprite.PostShader == null)
  28. return;
  29. UpdateHologramSprite(entity, entity.Comp.LinkedEntity);
  30. }
  31. private void OnTypingChanged(TypingChangedEvent ev, EntitySessionEventArgs args)
  32. {
  33. var uid = args.SenderSession.AttachedEntity;
  34. if (!Exists(uid))
  35. return;
  36. if (!HasComp<HolopadUserComponent>(uid))
  37. return;
  38. var netEv = new HolopadUserTypingChangedEvent(GetNetEntity(uid.Value), ev.IsTyping);
  39. RaiseNetworkEvent(netEv);
  40. }
  41. private void UpdateHologramSprite(EntityUid hologram, EntityUid? target)
  42. {
  43. // Get required components
  44. if (!TryComp<SpriteComponent>(hologram, out var hologramSprite) ||
  45. !TryComp<HolopadHologramComponent>(hologram, out var holopadhologram))
  46. return;
  47. // Remove all sprite layers
  48. for (int i = hologramSprite.AllLayers.Count() - 1; i >= 0; i--)
  49. hologramSprite.RemoveLayer(i);
  50. if (TryComp<SpriteComponent>(target, out var targetSprite))
  51. {
  52. // Use the target's holographic avatar (if available)
  53. if (TryComp<HolographicAvatarComponent>(target, out var targetAvatar) &&
  54. targetAvatar.LayerData != null)
  55. {
  56. for (int i = 0; i < targetAvatar.LayerData.Length; i++)
  57. {
  58. var layer = targetAvatar.LayerData[i];
  59. hologramSprite.AddLayer(targetAvatar.LayerData[i], i);
  60. }
  61. }
  62. // Otherwise copy the target's current physical appearance
  63. else
  64. {
  65. hologramSprite.CopyFrom(targetSprite);
  66. }
  67. }
  68. // There is no target, display a default sprite instead (if available)
  69. else
  70. {
  71. if (string.IsNullOrEmpty(holopadhologram.RsiPath) || string.IsNullOrEmpty(holopadhologram.RsiState))
  72. return;
  73. var layer = new PrototypeLayerData();
  74. layer.RsiPath = holopadhologram.RsiPath;
  75. layer.State = holopadhologram.RsiState;
  76. hologramSprite.AddLayer(layer);
  77. }
  78. // Override specific values
  79. hologramSprite.Color = Color.White;
  80. hologramSprite.Offset = holopadhologram.Offset;
  81. hologramSprite.DrawDepth = (int)DrawDepth.Mobs;
  82. hologramSprite.NoRotation = true;
  83. hologramSprite.DirectionOverride = Direction.South;
  84. hologramSprite.EnableDirectionOverride = true;
  85. // Remove shading from all layers (except displacement maps)
  86. for (int i = 0; i < hologramSprite.AllLayers.Count(); i++)
  87. {
  88. if (hologramSprite.TryGetLayer(i, out var layer) && layer.ShaderPrototype != "DisplacedStencilDraw")
  89. hologramSprite.LayerSetShader(i, "unshaded");
  90. }
  91. UpdateHologramShader(hologram, hologramSprite, holopadhologram);
  92. }
  93. private void UpdateHologramShader(EntityUid uid, SpriteComponent sprite, HolopadHologramComponent holopadHologram)
  94. {
  95. // Find the texture height of the largest layer
  96. float texHeight = sprite.AllLayers.Max(x => x.PixelSize.Y);
  97. var instance = _prototypeManager.Index<ShaderPrototype>(holopadHologram.ShaderName).InstanceUnique();
  98. instance.SetParameter("color1", new Vector3(holopadHologram.Color1.R, holopadHologram.Color1.G, holopadHologram.Color1.B));
  99. instance.SetParameter("color2", new Vector3(holopadHologram.Color2.R, holopadHologram.Color2.G, holopadHologram.Color2.B));
  100. instance.SetParameter("alpha", holopadHologram.Alpha);
  101. instance.SetParameter("intensity", holopadHologram.Intensity);
  102. instance.SetParameter("texHeight", texHeight);
  103. instance.SetParameter("t", (float)_timing.CurTime.TotalSeconds * holopadHologram.ScrollRate);
  104. sprite.PostShader = instance;
  105. sprite.RaiseShaderEvent = true;
  106. }
  107. }