SharedGunSystem.Battery.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using Content.Shared.Examine;
  2. using Content.Shared.Weapons.Ranged.Components;
  3. using Content.Shared.Weapons.Ranged.Events;
  4. using Robust.Shared.GameStates;
  5. using Robust.Shared.Map;
  6. using Robust.Shared.Serialization;
  7. namespace Content.Shared.Weapons.Ranged.Systems;
  8. public abstract partial class SharedGunSystem
  9. {
  10. protected virtual void InitializeBattery()
  11. {
  12. // Trying to dump comp references hence the below
  13. // Hitscan
  14. SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, ComponentGetState>(OnBatteryGetState);
  15. SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, ComponentHandleState>(OnBatteryHandleState);
  16. SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, TakeAmmoEvent>(OnBatteryTakeAmmo);
  17. SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, GetAmmoCountEvent>(OnBatteryAmmoCount);
  18. SubscribeLocalEvent<HitscanBatteryAmmoProviderComponent, ExaminedEvent>(OnBatteryExamine);
  19. // Projectile
  20. SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, ComponentGetState>(OnBatteryGetState);
  21. SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, ComponentHandleState>(OnBatteryHandleState);
  22. SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, TakeAmmoEvent>(OnBatteryTakeAmmo);
  23. SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, GetAmmoCountEvent>(OnBatteryAmmoCount);
  24. SubscribeLocalEvent<ProjectileBatteryAmmoProviderComponent, ExaminedEvent>(OnBatteryExamine);
  25. }
  26. private void OnBatteryHandleState(EntityUid uid, BatteryAmmoProviderComponent component, ref ComponentHandleState args)
  27. {
  28. if (args.Current is not BatteryAmmoProviderComponentState state)
  29. return;
  30. component.Shots = state.Shots;
  31. component.Capacity = state.MaxShots;
  32. component.FireCost = state.FireCost;
  33. UpdateAmmoCount(uid, prediction: false);
  34. }
  35. private void OnBatteryGetState(EntityUid uid, BatteryAmmoProviderComponent component, ref ComponentGetState args)
  36. {
  37. args.State = new BatteryAmmoProviderComponentState()
  38. {
  39. Shots = component.Shots,
  40. MaxShots = component.Capacity,
  41. FireCost = component.FireCost,
  42. };
  43. }
  44. private void OnBatteryExamine(EntityUid uid, BatteryAmmoProviderComponent component, ExaminedEvent args)
  45. {
  46. args.PushMarkup(Loc.GetString("gun-battery-examine", ("color", AmmoExamineColor), ("count", component.Shots)));
  47. }
  48. private void OnBatteryTakeAmmo(EntityUid uid, BatteryAmmoProviderComponent component, TakeAmmoEvent args)
  49. {
  50. var shots = Math.Min(args.Shots, component.Shots);
  51. // Don't dirty if it's an empty fire.
  52. if (shots == 0)
  53. return;
  54. for (var i = 0; i < shots; i++)
  55. {
  56. args.Ammo.Add(GetShootable(component, args.Coordinates));
  57. component.Shots--;
  58. }
  59. TakeCharge(uid, component);
  60. UpdateBatteryAppearance(uid, component);
  61. Dirty(uid, component);
  62. }
  63. private void OnBatteryAmmoCount(EntityUid uid, BatteryAmmoProviderComponent component, ref GetAmmoCountEvent args)
  64. {
  65. args.Count = component.Shots;
  66. args.Capacity = component.Capacity;
  67. }
  68. /// <summary>
  69. /// Update the battery (server-only) whenever fired.
  70. /// </summary>
  71. protected virtual void TakeCharge(EntityUid uid, BatteryAmmoProviderComponent component)
  72. {
  73. UpdateAmmoCount(uid, prediction: false);
  74. }
  75. protected void UpdateBatteryAppearance(EntityUid uid, BatteryAmmoProviderComponent component)
  76. {
  77. if (!TryComp<AppearanceComponent>(uid, out var appearance))
  78. return;
  79. Appearance.SetData(uid, AmmoVisuals.HasAmmo, component.Shots != 0, appearance);
  80. Appearance.SetData(uid, AmmoVisuals.AmmoCount, component.Shots, appearance);
  81. Appearance.SetData(uid, AmmoVisuals.AmmoMax, component.Capacity, appearance);
  82. }
  83. private (EntityUid? Entity, IShootable) GetShootable(BatteryAmmoProviderComponent component, EntityCoordinates coordinates)
  84. {
  85. switch (component)
  86. {
  87. case ProjectileBatteryAmmoProviderComponent proj:
  88. var ent = Spawn(proj.Prototype, coordinates);
  89. return (ent, EnsureShootable(ent));
  90. case HitscanBatteryAmmoProviderComponent hitscan:
  91. return (null, ProtoManager.Index<HitscanPrototype>(hitscan.Prototype));
  92. default:
  93. throw new ArgumentOutOfRangeException();
  94. }
  95. }
  96. [Serializable, NetSerializable]
  97. private sealed class BatteryAmmoProviderComponentState : ComponentState
  98. {
  99. public int Shots;
  100. public int MaxShots;
  101. public float FireCost;
  102. }
  103. }