HolosignSystem.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. using Content.Shared.Examine;
  2. using Content.Shared.Coordinates.Helpers;
  3. using Content.Server.Power.Components;
  4. using Content.Server.PowerCell;
  5. using Content.Shared.Interaction;
  6. using Content.Shared.Storage;
  7. namespace Content.Server.Holosign;
  8. public sealed class HolosignSystem : EntitySystem
  9. {
  10. [Dependency] private readonly PowerCellSystem _powerCell = default!;
  11. [Dependency] private readonly SharedTransformSystem _transform = default!;
  12. public override void Initialize()
  13. {
  14. base.Initialize();
  15. SubscribeLocalEvent<HolosignProjectorComponent, BeforeRangedInteractEvent>(OnBeforeInteract);
  16. SubscribeLocalEvent<HolosignProjectorComponent, ExaminedEvent>(OnExamine);
  17. }
  18. private void OnExamine(EntityUid uid, HolosignProjectorComponent component, ExaminedEvent args)
  19. {
  20. // TODO: This should probably be using an itemstatus
  21. // TODO: I'm too lazy to do this rn but it's literally copy-paste from emag.
  22. _powerCell.TryGetBatteryFromSlot(uid, out var battery);
  23. var charges = UsesRemaining(component, battery);
  24. var maxCharges = MaxUses(component, battery);
  25. using (args.PushGroup(nameof(HolosignProjectorComponent)))
  26. {
  27. args.PushMarkup(Loc.GetString("limited-charges-charges-remaining", ("charges", charges)));
  28. if (charges > 0 && charges == maxCharges)
  29. {
  30. args.PushMarkup(Loc.GetString("limited-charges-max-charges"));
  31. }
  32. }
  33. }
  34. private void OnBeforeInteract(EntityUid uid, HolosignProjectorComponent component, BeforeRangedInteractEvent args)
  35. {
  36. if (args.Handled
  37. || !args.CanReach // prevent placing out of range
  38. || HasComp<StorageComponent>(args.Target) // if it's a storage component like a bag, we ignore usage so it can be stored
  39. || !_powerCell.TryUseCharge(uid, component.ChargeUse, user: args.User) // if no battery or no charge, doesn't work
  40. )
  41. return;
  42. // places the holographic sign at the click location, snapped to grid.
  43. // overlapping of the same holo on one tile remains allowed to allow holofan refreshes
  44. var holoUid = EntityManager.SpawnEntity(component.SignProto, args.ClickLocation.SnapToGrid(EntityManager));
  45. var xform = Transform(holoUid);
  46. if (!xform.Anchored)
  47. _transform.AnchorEntity(holoUid, xform); // anchor to prevent any tempering with (don't know what could even interact with it)
  48. args.Handled = true;
  49. }
  50. private int UsesRemaining(HolosignProjectorComponent component, BatteryComponent? battery = null)
  51. {
  52. if (battery == null ||
  53. component.ChargeUse == 0f) return 0;
  54. return (int) (battery.CurrentCharge / component.ChargeUse);
  55. }
  56. private int MaxUses(HolosignProjectorComponent component, BatteryComponent? battery = null)
  57. {
  58. if (battery == null ||
  59. component.ChargeUse == 0f) return 0;
  60. return (int) (battery.MaxCharge / component.ChargeUse);
  61. }
  62. }