diff --git a/Content.Server/SurveillanceCamera/Components/SurveillanceBodyCameraComponent.cs b/Content.Server/SurveillanceCamera/Components/SurveillanceBodyCameraComponent.cs
deleted file mode 100644
index 99235dd7a5..0000000000
--- a/Content.Server/SurveillanceCamera/Components/SurveillanceBodyCameraComponent.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace Content.Server.SurveillanceCamera;
-
-[RegisterComponent]
-public sealed partial class SurveillanceBodyCameraComponent : Component
-{
- [DataField("wattage"), ViewVariables(VVAccess.ReadWrite)]
- public float Wattage = 0.3f;
-
- public bool lastState = false;
-}
diff --git a/Content.Server/SurveillanceCamera/Components/SurveillanceCameraComponent.cs b/Content.Server/SurveillanceCamera/Components/SurveillanceCameraComponent.cs
index 52f84e6562..b907eb29a7 100644
--- a/Content.Server/SurveillanceCamera/Components/SurveillanceCameraComponent.cs
+++ b/Content.Server/SurveillanceCamera/Components/SurveillanceCameraComponent.cs
@@ -1,4 +1,4 @@
-using Content.Server.SurveillanceCamera.Systems;
+using Content.Server._White.SurveillanceCamera;
using Content.Shared.DeviceNetwork;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
diff --git a/Content.Server/SurveillanceCamera/Systems/SurveillanceBodyCameraSystem.cs b/Content.Server/SurveillanceCamera/Systems/SurveillanceBodyCameraSystem.cs
deleted file mode 100644
index d0e312dc80..0000000000
--- a/Content.Server/SurveillanceCamera/Systems/SurveillanceBodyCameraSystem.cs
+++ /dev/null
@@ -1,118 +0,0 @@
-using Content.Server.Popups;
-using Content.Server.Power.EntitySystems;
-using Content.Server.PowerCell;
-using Content.Shared.Clothing.EntitySystems;
-using Content.Shared.Examine;
-using Content.Shared.Interaction;
-using Content.Shared.Item;
-using Content.Shared.PowerCell.Components;
-using Content.Shared.Toggleable;
-
-namespace Content.Server.SurveillanceCamera.Systems;
-
-///
-/// This handles the bodycamera all itself. Activation, examine,init, powercell stuff.
-///
-public sealed class SurveillanceBodyCameraSystem : EntitySystem
-{
- [Dependency] private readonly PowerCellSystem _powerCell = default!;
- [Dependency] private readonly PopupSystem _popup = default!;
- [Dependency] private readonly SurveillanceCameraSystem _surveillanceCameras = default!;
- [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
- [Dependency] private readonly SharedItemSystem _item = default!;
- [Dependency] private readonly ClothingSystem _clothing = default!;
- [Dependency] private readonly BatterySystem _battery = default!;
-
- public override void Initialize()
- {
- base.Initialize();
-
- SubscribeLocalEvent(OnActivate);
- SubscribeLocalEvent(OnPowerCellChanged);
- SubscribeLocalEvent(OnExamine);
- SubscribeLocalEvent(OnInit);
- }
-
- public void OnInit(EntityUid uid, SurveillanceBodyCameraComponent comp, ComponentInit args)
- {
-
- if (!TryComp(uid, out var surComp))
- return;
-
- _surveillanceCameras.SetActive(uid, false, surComp);
- surComp.NetworkSet = true;
- AppearanceChange(uid, surComp.Active);
- }
- public override void Update(float frameTime)
- {
- var query = EntityQueryEnumerator();
- while (query.MoveNext(out var uid, out var cam))
- {
- if (!_powerCell.TryGetBatteryFromSlot(uid, out var battery))
- continue;
-
- if (!TryComp(uid, out var surComp))
- continue;
-
- if (!surComp.Active)
- continue;
-
- if (!_battery.TryUseCharge(uid, cam.Wattage * frameTime))
- {
- _surveillanceCameras.SetActive(uid, false, surComp);
- AppearanceChange(uid, surComp.Active);
- }
- }
- }
- public void OnActivate(EntityUid uid, SurveillanceBodyCameraComponent comp, ActivateInWorldEvent args)
- {
- if (!TryComp(uid, out var surComp))
- return;
-
- if (!_powerCell.TryGetBatteryFromSlot(uid, out var battery))
- return;
-
- _surveillanceCameras.SetActive(uid, battery.CurrentCharge > comp.Wattage && !surComp.Active, surComp);
- AppearanceChange(uid, surComp.Active);
-
- var message = Loc.GetString(surComp.Active ? "surveillance-body-camera-on" : "surveillance-body-camera-off");
- _popup.PopupEntity(message, args.User, args.User);
- args.Handled = true;
- }
-
- public void OnPowerCellChanged(EntityUid uid, SurveillanceBodyCameraComponent comp, PowerCellChangedEvent args)
- {
- if (!TryComp(uid, out var surComp))
- return;
-
- if (args.Ejected)
- {
- _surveillanceCameras.SetActive(uid, false, surComp);
- AppearanceChange(uid, surComp.Active);
- }
- }
-
- public void OnExamine(EntityUid uid, SurveillanceBodyCameraComponent comp, ExaminedEvent args)
- {
- if (!TryComp(uid, out var surComp))
- return;
-
- if (args.IsInDetailsRange)
- {
- var message =
- Loc.GetString(surComp.Active ? "surveillance-body-camera-on" : "surveillance-body-camera-off");
- args.PushMarkup(message);
- }
- }
-
- public void AppearanceChange(EntityUid uid, Boolean isActive)
- {
- if (TryComp(uid, out var appearance) &&
- TryComp(uid, out var item))
- {
- _item.SetHeldPrefix(uid, isActive ? "on" : "off", false, item);
- _clothing.SetEquippedPrefix(uid, isActive ? null : "off");
- _appearance.SetData(uid, ToggleVisuals.Toggled, isActive, appearance);
- }
- }
-}
diff --git a/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraSystem.cs b/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraSystem.cs
index 7d3da28547..b2b1938e8e 100644
--- a/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraSystem.cs
+++ b/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraSystem.cs
@@ -1,3 +1,4 @@
+using Content.Server._White.SurveillanceCamera;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
@@ -134,9 +135,9 @@ public sealed class SurveillanceCameraSystem : EntitySystem
return;
}
- if (TryComp(uid, out var bodycamComp))
+ if (TryComp(uid, out _)) // WD EDIT
{
- component.NameSet = false;
+ return;
}
if (component.NameSet && component.NetworkSet)
@@ -212,7 +213,7 @@ public sealed class SurveillanceCameraSystem : EntitySystem
UpdateSetupInterface(uid, camera);
}
- private void UpdateSetupInterface(EntityUid uid, SurveillanceCameraComponent? camera = null, DeviceNetworkComponent? deviceNet = null)
+ public void UpdateSetupInterface(EntityUid uid, SurveillanceCameraComponent? camera = null, DeviceNetworkComponent? deviceNet = null)
{
if (!Resolve(uid, ref camera, ref deviceNet))
{
diff --git a/Content.Server/_White/SurveillanceCamera/SurveillanceBodyCameraComponent.cs b/Content.Server/_White/SurveillanceCamera/SurveillanceBodyCameraComponent.cs
new file mode 100644
index 0000000000..91ddf18692
--- /dev/null
+++ b/Content.Server/_White/SurveillanceCamera/SurveillanceBodyCameraComponent.cs
@@ -0,0 +1,19 @@
+using Robust.Shared.Prototypes;
+
+namespace Content.Server._White.SurveillanceCamera;
+
+[RegisterComponent]
+public sealed partial class SurveillanceBodyCameraComponent : Component
+{
+ [DataField("wattage"), ViewVariables(VVAccess.ReadWrite)]
+ public float Wattage = 0.3f;
+
+ [DataField]
+ public EntityUid? ToggleActionEntity;
+
+ [DataField]
+ public EntProtoId ToggleAction = "ToggleBodyCamera";
+
+ public bool LastState = false;
+}
+
diff --git a/Content.Server/_White/SurveillanceCamera/SurveillanceBodyCameraSystem.cs b/Content.Server/_White/SurveillanceCamera/SurveillanceBodyCameraSystem.cs
new file mode 100644
index 0000000000..600f5e2d29
--- /dev/null
+++ b/Content.Server/_White/SurveillanceCamera/SurveillanceBodyCameraSystem.cs
@@ -0,0 +1,141 @@
+using Content.Server.Popups;
+using Content.Server.Power.EntitySystems;
+using Content.Server.PowerCell;
+using Content.Server.SurveillanceCamera;
+using Content.Shared.Examine;
+using Content.Shared.Clothing.EntitySystems;
+using Content.Shared.Item;
+using Content.Shared.Actions;
+using Content.Shared.PowerCell.Components;
+using Content.Shared._White.SurveillanceCamera;
+using Content.Shared.IdentityManagement;
+using Content.Shared.Toggleable;
+using Robust.Shared.Player;
+
+namespace Content.Server._White.SurveillanceCamera;
+
+public sealed class SurveillanceBodyCameraSystem : EntitySystem
+{
+ [Dependency] private readonly PowerCellSystem _powerCell = default!;
+ [Dependency] private readonly PopupSystem _popup = default!;
+ [Dependency] private readonly SurveillanceCameraSystem _surveillanceCameras = default!;
+ [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+ [Dependency] private readonly SharedItemSystem _item = default!;
+ [Dependency] private readonly ClothingSystem _clothing = default!;
+ [Dependency] private readonly BatterySystem _battery = default!;
+
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnStartup);
+ SubscribeLocalEvent(OnGetActions);
+ SubscribeLocalEvent(OnToggleAction);
+ SubscribeLocalEvent(OnPowerCellChanged);
+ SubscribeLocalEvent(OnExamine);
+ SubscribeLocalEvent(OnInit);
+ }
+
+ private void OnStartup(EntityUid uid, SurveillanceBodyCameraComponent component, ComponentStartup args)
+ {
+ EnsureComp(uid, out SurveillanceCameraComponent surComp);
+ _surveillanceCameras.UpdateSetupInterface(uid, surComp);
+ }
+
+ private void OnGetActions(EntityUid uid, SurveillanceBodyCameraComponent component, GetItemActionsEvent args)
+ {
+ args.AddAction(ref component.ToggleActionEntity, component.ToggleAction);
+ }
+
+ private void OnToggleAction(EntityUid uid, SurveillanceBodyCameraComponent component, ToggleBodyCameraEvent args)
+ {
+ if (!TryComp(uid, out var surComp))
+ return;
+
+ if (!_powerCell.TryGetBatteryFromSlot(uid, out var battery))
+ return;
+
+ _surveillanceCameras.SetActive(uid, battery.CurrentCharge > component.Wattage && !surComp.Active, surComp);
+ AppearanceChange(uid, surComp.Active);
+
+ var message = Loc.GetString(surComp.Active ? "surveillance-body-camera-on" : "surveillance-body-camera-off",
+ ("item", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(message, uid, Filter.PvsExcept(uid, entityManager: EntityManager), true);
+ }
+
+ public void OnInit(EntityUid uid, SurveillanceBodyCameraComponent comp, ComponentInit args)
+ {
+ if (!TryComp(uid, out var surComp))
+ return;
+
+ _surveillanceCameras.SetActive(uid, false, surComp);
+ surComp.NetworkSet = true;
+ AppearanceChange(uid, surComp.Active);
+ }
+ public override void Update(float frameTime)
+ {
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var cam))
+ {
+ if (!_powerCell.TryGetBatteryFromSlot(uid, out var battery))
+ continue;
+
+ if (!TryComp(uid, out var surComp))
+ continue;
+
+ if (!surComp.Active)
+ continue;
+
+ if (_battery.TryUseCharge(uid, cam.Wattage * frameTime, battery))
+ continue;
+
+ var message = Loc.GetString("surveillance-body-camera-off",
+ ("item", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(message, uid, Filter.PvsExcept(uid, entityManager: EntityManager), true);
+
+ _surveillanceCameras.SetActive(uid, false, surComp);
+ AppearanceChange(uid, surComp.Active);
+ }
+ }
+
+ private void OnPowerCellChanged(EntityUid uid, SurveillanceBodyCameraComponent comp, PowerCellChangedEvent args)
+ {
+ if (!TryComp(uid, out var surComp))
+ return;
+
+ if (!args.Ejected)
+ return;
+
+ if (surComp.Active)
+ {
+ var message = Loc.GetString("surveillance-body-camera-off",
+ ("item", Identity.Entity(uid, EntityManager)));
+ _popup.PopupEntity(message, uid, Filter.PvsExcept(uid, entityManager: EntityManager), true);
+ }
+
+ _surveillanceCameras.SetActive(uid, false, surComp);
+ AppearanceChange(uid, surComp.Active);
+ }
+
+ public void OnExamine(EntityUid uid, SurveillanceBodyCameraComponent comp, ExaminedEvent args)
+ {
+ if (!TryComp(uid, out var surComp))
+ return;
+
+ if (!args.IsInDetailsRange)
+ return;
+
+ var message = Loc.GetString(surComp.Active ? "surveillance-body-camera-on" : "surveillance-body-camera-off",
+ ("item", Identity.Entity(uid, EntityManager)));
+ args.PushMarkup(message);
+ }
+
+ public void AppearanceChange(EntityUid uid, bool isActive)
+ {
+ if (!TryComp(uid, out var appearance) ||
+ !TryComp(uid, out var item))
+ return;
+
+ _item.SetHeldPrefix(uid, isActive ? "on" : "off", false, item);
+ _clothing.SetEquippedPrefix(uid, isActive ? null : "off");
+ _appearance.SetData(uid, ToggleVisuals.Toggled, isActive, appearance);
+ }
+}
diff --git a/Content.Shared/_White/SurveillanceCamera/ToggleBodyCameraEvent.cs b/Content.Shared/_White/SurveillanceCamera/ToggleBodyCameraEvent.cs
new file mode 100644
index 0000000000..f7db8a78bd
--- /dev/null
+++ b/Content.Shared/_White/SurveillanceCamera/ToggleBodyCameraEvent.cs
@@ -0,0 +1,10 @@
+using Content.Shared.Actions;
+
+namespace Content.Shared._White.SurveillanceCamera;
+
+///
+/// Action-event for toggle-able Body Camera/>
+///
+public sealed partial class ToggleBodyCameraEvent : InstantActionEvent
+{
+}
diff --git a/Resources/Locale/en-US/surveillance-camera/surveillance-camera-ui.ftl b/Resources/Locale/en-US/surveillance-camera/surveillance-camera-ui.ftl
index 9cb32b6eaf..ee695cc3a3 100644
--- a/Resources/Locale/en-US/surveillance-camera/surveillance-camera-ui.ftl
+++ b/Resources/Locale/en-US/surveillance-camera/surveillance-camera-ui.ftl
@@ -11,3 +11,6 @@ surveillance-camera-monitor-ui-no-subnets = No Subnets
surveillance-camera-setup = Setup
surveillance-camera-setup-ui-set = Set
+surveillance-body-camera-on = {THE($item)} starts flashing
+surveillance-body-camera-off = {THE($item)} stops flashing
+
diff --git a/Resources/Locale/ru-RU/actions/actions/body-camera.ftl b/Resources/Locale/ru-RU/actions/actions/body-camera.ftl
new file mode 100644
index 0000000000..c85d75f3d3
--- /dev/null
+++ b/Resources/Locale/ru-RU/actions/actions/body-camera.ftl
@@ -0,0 +1,2 @@
+ent-ToggleBodyCamera = Переключить бодикамеру
+ .desc = Переключить бодикамеру
\ No newline at end of file
diff --git a/Resources/Locale/ru-RU/surveillance-camera/surveillance-camera-ui.ftl b/Resources/Locale/ru-RU/surveillance-camera/surveillance-camera-ui.ftl
index 4ab4bbecf0..128282c890 100644
--- a/Resources/Locale/ru-RU/surveillance-camera/surveillance-camera-ui.ftl
+++ b/Resources/Locale/ru-RU/surveillance-camera/surveillance-camera-ui.ftl
@@ -9,5 +9,5 @@ surveillance-camera-monitor-ui-status-disconnected = Отключено
surveillance-camera-monitor-ui-no-subnets = Нет подсетей
surveillance-camera-setup = Настроить
surveillance-camera-setup-ui-set = Установить
-surveillance-body-camera-on = Камера включена
-surveillance-body-camera-off = Камера выключена
+surveillance-body-camera-on = { $item } начинает мигать
+surveillance-body-camera-off = { $item } перестает мигать
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Security/body-camera.yml b/Resources/Prototypes/Entities/Objects/Specific/Security/body-camera.yml
index 006cd7366f..41bd031fd9 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/Security/body-camera.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/Security/body-camera.yml
@@ -74,3 +74,8 @@
- type: Tag
tags:
- SurveillanceBodyCamera
+ - type: ActivatableUI
+ key: enum.SurveillanceCameraSetupUiKey.Camera
+ singleUser: true
+ closeOnHandDeselect: false
+ verbText: surveillance-camera-setup
diff --git a/Resources/Prototypes/_White/Actions/types.yml b/Resources/Prototypes/_White/Actions/types.yml
index ed478a94d6..f38f61a0e7 100644
--- a/Resources/Prototypes/_White/Actions/types.yml
+++ b/Resources/Prototypes/_White/Actions/types.yml
@@ -41,3 +41,16 @@
sprite: White/Clothing/Head/nightvision.rsi
state: icon
event: !type:ToggleNightVisionEvent
+
+- type: entity
+ id: ToggleBodyCamera
+ name: Toggle body camera.
+ description: Toggles body camera.
+ noSpawn: true
+ components:
+ - type: InstantAction
+ itemIconStyle: BigAction
+ priority: -20
+ icon: { sprite: Objects\Specific\Security\body-camera.rsi, state: unpowered }
+ iconOn: { sprite: Objects\Specific\Security\body-camera.rsi, state: active }
+ event: !type:ToggleBodyCameraEvent
\ No newline at end of file