1
0

FireVisualizerSystem.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using Content.Client.Atmos.Components;
  2. using Content.Shared.Atmos;
  3. using Robust.Client.GameObjects;
  4. using Robust.Shared.Map;
  5. namespace Content.Client.Atmos.EntitySystems;
  6. /// <summary>
  7. /// This handles the display of fire effects on flammable entities.
  8. /// </summary>
  9. public sealed class FireVisualizerSystem : VisualizerSystem<FireVisualsComponent>
  10. {
  11. [Dependency] private readonly PointLightSystem _lights = default!;
  12. public override void Initialize()
  13. {
  14. base.Initialize();
  15. SubscribeLocalEvent<FireVisualsComponent, ComponentInit>(OnComponentInit);
  16. SubscribeLocalEvent<FireVisualsComponent, ComponentShutdown>(OnShutdown);
  17. }
  18. private void OnShutdown(EntityUid uid, FireVisualsComponent component, ComponentShutdown args)
  19. {
  20. if (component.LightEntity != null)
  21. {
  22. Del(component.LightEntity.Value);
  23. component.LightEntity = null;
  24. }
  25. // Need LayerMapTryGet because Init fails if there's no existing sprite / appearancecomp
  26. // which means in some setups (most frequently no AppearanceComp) the layer never exists.
  27. if (TryComp<SpriteComponent>(uid, out var sprite) &&
  28. sprite.LayerMapTryGet(FireVisualLayers.Fire, out var layer))
  29. {
  30. sprite.RemoveLayer(layer);
  31. }
  32. }
  33. private void OnComponentInit(EntityUid uid, FireVisualsComponent component, ComponentInit args)
  34. {
  35. if (!TryComp<SpriteComponent>(uid, out var sprite) || !TryComp(uid, out AppearanceComponent? appearance))
  36. return;
  37. sprite.LayerMapReserveBlank(FireVisualLayers.Fire);
  38. sprite.LayerSetVisible(FireVisualLayers.Fire, false);
  39. sprite.LayerSetShader(FireVisualLayers.Fire, "unshaded");
  40. if (component.Sprite != null)
  41. sprite.LayerSetRSI(FireVisualLayers.Fire, component.Sprite);
  42. UpdateAppearance(uid, component, sprite, appearance);
  43. }
  44. protected override void OnAppearanceChange(EntityUid uid, FireVisualsComponent component, ref AppearanceChangeEvent args)
  45. {
  46. if (args.Sprite != null)
  47. UpdateAppearance(uid, component, args.Sprite, args.Component);
  48. }
  49. private void UpdateAppearance(EntityUid uid, FireVisualsComponent component, SpriteComponent sprite, AppearanceComponent appearance)
  50. {
  51. if (!sprite.LayerMapTryGet(FireVisualLayers.Fire, out var index))
  52. return;
  53. AppearanceSystem.TryGetData<bool>(uid, FireVisuals.OnFire, out var onFire, appearance);
  54. AppearanceSystem.TryGetData<float>(uid, FireVisuals.FireStacks, out var fireStacks, appearance);
  55. sprite.LayerSetVisible(index, onFire);
  56. if (!onFire)
  57. {
  58. if (component.LightEntity != null)
  59. {
  60. Del(component.LightEntity.Value);
  61. component.LightEntity = null;
  62. }
  63. return;
  64. }
  65. if (fireStacks > component.FireStackAlternateState && !string.IsNullOrEmpty(component.AlternateState))
  66. sprite.LayerSetState(index, component.AlternateState);
  67. else
  68. sprite.LayerSetState(index, component.NormalState);
  69. component.LightEntity ??= Spawn(null, new EntityCoordinates(uid, default));
  70. var light = EnsureComp<PointLightComponent>(component.LightEntity.Value);
  71. _lights.SetColor(component.LightEntity.Value, component.LightColor, light);
  72. // light needs a minimum radius to be visible at all, hence the + 1.5f
  73. _lights.SetRadius(component.LightEntity.Value, Math.Clamp(1.5f + component.LightRadiusPerStack * fireStacks, 0f, component.MaxLightRadius), light);
  74. _lights.SetEnergy(component.LightEntity.Value, Math.Clamp(1 + component.LightEnergyPerStack * fireStacks, 0f, component.MaxLightEnergy), light);
  75. // TODO flickering animation? Or just add a noise mask to the light? But that requires an engine PR.
  76. }
  77. }
  78. public enum FireVisualLayers : byte
  79. {
  80. Fire
  81. }