diff --git a/Content.Client/_Rat/Overwatch/OverwatchWindow.xaml.cs b/Content.Client/_Rat/Overwatch/OverwatchWindow.xaml.cs
index beb65b9e05..4b4b039c0f 100644
--- a/Content.Client/_Rat/Overwatch/OverwatchWindow.xaml.cs
+++ b/Content.Client/_Rat/Overwatch/OverwatchWindow.xaml.cs
@@ -58,6 +58,13 @@ public OverwatchWindow()
StopWatchingButton.OnPressed += _ =>
{
_ui?.StopWatching();
+
+ foreach (var row in _memberRows.Values)
+ {
+ row.SetWatching(false);
+ }
+
+ _watchingStateCache.Clear();
StopWatchingButton.Visible = false;
};
@@ -140,8 +147,11 @@ private void OnMemberStartWatching(OverwatchMemberRow selectedRow)
if (row != selectedRow)
{
row.SetWatching(false);
+ _watchingStateCache[row.Member] = false;
}
}
+
+ StopWatchingButton.Visible = true;
}
///
@@ -551,6 +561,11 @@ public sealed class OverwatchMemberRow : BoxContainer
///
public bool IsWatching { get; private set; }
+ ///
+ /// Сущность участника.
+ ///
+ public NetEntity Member => _member;
+
///
/// Селектор отрядов для назначения участника.
///
diff --git a/Content.Server/_Rat/Overwatch/OverwatchSystem.cs b/Content.Server/_Rat/Overwatch/OverwatchSystem.cs
index 305aecfd55..ffd8ce79ae 100644
--- a/Content.Server/_Rat/Overwatch/OverwatchSystem.cs
+++ b/Content.Server/_Rat/Overwatch/OverwatchSystem.cs
@@ -167,13 +167,6 @@ private void OnUIOpenAttempt(Entity ent, ref Activata
{
if (args.User is not { Valid: true } user)
return;
-
- var userFaction = GetUserFaction(user);
- if (string.IsNullOrEmpty(userFaction) || userFaction != ent.Comp.Faction)
- {
- args.Cancel();
- return;
- }
}
///
@@ -310,10 +303,6 @@ private void OnCreateSquad(Entity ent, ref OverwatchC
if (args.Actor is not { Valid: true } actor)
return;
- var userFaction = GetUserFaction(actor);
- if (string.IsNullOrEmpty(userFaction) || userFaction != ent.Comp.Faction)
- return;
-
var created = _squadSystem.CreateSquad(ent.Comp.Faction, args.SquadName);
if (created)
{
@@ -329,10 +318,6 @@ private void OnDeleteSquad(Entity ent, ref OverwatchD
if (args.Actor is not { Valid: true } actor)
return;
- var userFaction = GetUserFaction(actor);
- if (string.IsNullOrEmpty(userFaction) || userFaction != ent.Comp.Faction)
- return;
-
if (_squadSystem.RemoveSquad(ent.Comp.Faction, args.SquadId))
{
RefreshData(ent);
@@ -347,10 +332,6 @@ private void OnAssignSquad(Entity ent, ref OverwatchA
if (args.Actor is not { Valid: true } actor)
return;
- var userFaction = GetUserFaction(actor);
- if (string.IsNullOrEmpty(userFaction) || userFaction != ent.Comp.Faction)
- return;
-
var player = GetEntity(args.Player);
if (!player.Valid)
return;
@@ -373,10 +354,6 @@ private void OnRemoveSquadMember(Entity ent, ref Over
if (args.Actor is not { Valid: true } actor)
return;
- var userFaction = GetUserFaction(actor);
- if (string.IsNullOrEmpty(userFaction) || userFaction != ent.Comp.Faction)
- return;
-
var player = GetEntity(args.Player);
if (!player.Valid)
return;
@@ -397,10 +374,6 @@ private void OnSendAnnouncement(Entity ent, ref Overw
if (args.Actor is not { Valid: true } actor)
return;
- var userFaction = GetUserFaction(actor);
- if (string.IsNullOrEmpty(userFaction) || userFaction != ent.Comp.Faction)
- return;
-
if (string.IsNullOrEmpty(args.Message))
return;
@@ -474,10 +447,6 @@ private void OnViewCamera(Entity ent, ref OverwatchVi
if (args.Actor is not { Valid: true } actor)
return;
- var userFaction = GetUserFaction(actor);
- if (string.IsNullOrEmpty(userFaction) || userFaction != ent.Comp.Faction)
- return;
-
var target = GetEntity(args.Target);
if (!TryComp(target, out var factionComp) ||
factionComp.Faction != ent.Comp.Faction ||
@@ -530,10 +499,6 @@ private void OnStopWatching(Entity ent, ref Overwatch
if (args.Actor is not { Valid: true } actor)
return;
- var userFaction = GetUserFaction(actor);
- if (string.IsNullOrEmpty(userFaction) || userFaction != ent.Comp.Faction)
- return;
-
if (TryComp(actor, out var watchingComp) && watchingComp.Watching.HasValue)
{
StopWatching(actor, watchingComp);
@@ -716,17 +681,6 @@ public override void Update(float frameTime)
_cacheInvalidationTimer = 0;
}
- ///
- /// Получает фракцию игрока.
- ///
- private string? GetUserFaction(EntityUid user)
- {
- if (!TryComp(user, out var factionComp))
- return null;
-
- return factionComp.Faction;
- }
-
///
/// Получает кэшированный список членов фракции.
///
diff --git a/Resources/Locale/ru-RU/_Rat/overwatch.ftl b/Resources/Locale/ru-RU/_Rat/overwatch.ftl
index 3dcc298971..cc9d318235 100644
--- a/Resources/Locale/ru-RU/_Rat/overwatch.ftl
+++ b/Resources/Locale/ru-RU/_Rat/overwatch.ftl
@@ -39,7 +39,7 @@ overwatch-member-status-alive = Жив
overwatch-member-status-ssd = SSD
overwatch-member-status-dead = Мёртв
overwatch-member-status-unknown = Неизвестно
-overwatch-member-coordinates = ({ $x }, { $y })
+overwatch-member-coordinates = ({ $x }; { $y })
overwatch-member-coordinates-none = —
overwatch-stop-watching-button = Остановить наблюдение
@@ -79,3 +79,24 @@ ent-GSCOverwatchComputer = консоль overwatch «ЧЕРНАЯ СЕТЬ»
.desc = Консоль системы наблюдения «ЧЕРНАЯ СЕТЬ» GSC. Децентрализованная сеть наблюдения для независимых операторов.
ent-CDOverwatchComputer = консоль overwatch «ЧЕРНАЯ СЕТЬ»
.desc = Консоль системы наблюдения «ЧЕРНАЯ СЕТЬ» CD. Децентрализованная сеть наблюдения для независимых операторов.
+
+ent-BaseOverwatchClipboard = цифровой планшет overwatch
+ .desc = Громоздкий цифровой планшет, содержащий информацию о членах фракции. При таком количестве компрометирующих документов его следует беречь.
+ent-DSMOverwatchClipboard = цифровой планшет overwatch «ОКО КАЙЗЕРА»
+ .desc = { ent-BaseOverwatchClipboard.desc }
+ent-NCWLOverwatchClipboard = цифровой планшет overwatch «ДОЗОРНЫЙ»
+ .desc = { ent-BaseOverwatchClipboard.desc }
+ent-SHIOverwatchClipboard = цифровой планшет overwatch «C.A.S.S.I.E.»
+ .desc = { ent-BaseOverwatchClipboard.desc }
+ent-TAPOverwatchClipboard = цифровой планшет overwatch «ЗВЕЗДНЫЙ ШЁПОТ»
+ .desc = { ent-BaseOverwatchClipboard.desc }
+ent-IPMOverwatchClipboard = цифровой планшет overwatch «ЧЕРНАЯ СЕТЬ»
+ .desc = { ent-BaseOverwatchClipboard.desc }
+ent-SAWOverwatchClipboard = цифровой планшет overwatch «ЧЕРНАЯ СЕТЬ»
+ .desc = { ent-BaseOverwatchClipboard.desc }
+ent-GSCOverwatchClipboard = цифровой планшет overwatch «ЧЕРНАЯ СЕТЬ»
+ .desc = { ent-BaseOverwatchClipboard.desc }
+ent-CDOverwatchClipboard = цифровой планшет overwatch «ЧЕРНАЯ СЕТЬ»
+ .desc = { ent-BaseOverwatchClipboard.desc }
+
+overwatch-clipboard-computer-verb-text = Переключить меню overwatch
diff --git a/Resources/Prototypes/_Rat/Entities/Structures/Machines/Computers/overwatch.yml b/Resources/Prototypes/_Rat/Entities/Structures/Machines/Computers/overwatch.yml
index 8f32cb6ea0..2b66677055 100644
--- a/Resources/Prototypes/_Rat/Entities/Structures/Machines/Computers/overwatch.yml
+++ b/Resources/Prototypes/_Rat/Entities/Structures/Machines/Computers/overwatch.yml
@@ -1,5 +1,6 @@
- type: entity
parent: BaseComputer
+ abstract: true
id: BaseComputerOverwatch
name: overwatch console
description: A computer console used to track faction members via wearable cameras.
@@ -225,3 +226,141 @@
# layers:
# - map: ["computerLayerScreen"]
# state: tsp
+
+- type: entity
+ parent: BoxFolderBase
+ abstract: true
+ id: BaseOverwatchClipboard
+ name: overwatc digi-board
+ description: A bulky electric clipboard, filled with shipping orders and financing details. With so many compromising documents, you ought to keep this safe.
+ components:
+ - type: Sprite
+ sprite: Objects/Misc/qm_clipboard.rsi
+ layers:
+ - state: qm_clipboard
+ - state: qm_clipboard_paper
+ map: ["qm_clipboard_paper"]
+ visible: false
+ - state: qm_clipboard_pen
+ map: ["qm_clipboard_pen"]
+ visible: false
+ - state: qm_clipboard_over
+ - type: ContainerContainer
+ containers:
+ storagebase: !type:Container
+ ents: []
+ pen_slot: !type:ContainerSlot {}
+ - type: ItemSlots
+ slots:
+ pen_slot:
+ name: clipboard-slot-component-slot-name-pen
+ whitelist:
+ tags:
+ - Write
+ insertOnInteract: true
+ - type: Item
+ sprite: Objects/Misc/qm_clipboard.rsi
+ size: Small
+ - type: Clothing
+ slots: [belt]
+ quickEquip: false
+ sprite: Objects/Misc/qm_clipboard.rsi
+ - type: Storage
+ grid:
+ - 0,0,4,3
+ quickInsert: true
+ whitelist:
+ tags:
+ - Document
+ - type: StorageFill
+ contents: []
+ - type: ItemMapper
+ mapLayers:
+ qm_clipboard_paper:
+ whitelist:
+ tags:
+ - Document
+ qm_clipboard_pen:
+ whitelist:
+ tags:
+ - Write
+ - type: CargoOrderConsole
+ - type: BankClient
+ - type: ActivatableUI
+ verbText: overwatch-clipboard-computer-verb-text
+ key: enum.OverwatchUiKey.Key
+ - type: UserInterface
+ interfaces:
+ enum.OverwatchUiKey.Key:
+ type: Content.Client._Rat.Overwatch.OverwatchBoundUserInterface
+ enum.StorageUiKey.Key:
+ type: StorageBoundUserInterface
+ - type: MeleeWeapon
+ wideAnimationRotation: 180
+ damage:
+ types:
+ Blunt: 10
+
+- type: entity
+ parent: BaseOverwatchClipboard
+ id: DSMOverwatchClipboard
+ name: overwatch console DSM
+ components:
+ - type: OverwatchConsole
+ faction: DSM
+
+- type: entity
+ parent: BaseOverwatchClipboard
+ id: NCWLOverwatchClipboard
+ name: overwatch console NCWL
+ components:
+ - type: OverwatchConsole
+ faction: NCWL
+
+- type: entity
+ parent: BaseOverwatchClipboard
+ id: SHIOverwatchClipboard
+ name: overwatch console SHI
+ components:
+ - type: OverwatchConsole
+ faction: SHI
+
+- type: entity
+ parent: BaseOverwatchClipboard
+ id: TAPOverwatchClipboard
+ name: overwatch console TAP
+ components:
+ - type: OverwatchConsole
+ faction: TAP
+
+- type: entity
+ parent: BaseOverwatchClipboard
+ id: IPMOverwatchClipboard
+ name: overwatch console IPM
+ components:
+ - type: OverwatchConsole
+ faction: IPM
+
+- type: entity
+ parent: BaseOverwatchClipboard
+ id: SAWOverwatchClipboard
+ name: overwatch console SAW
+ components:
+ - type: OverwatchConsole
+ faction: SAW
+
+- type: entity
+ parent: BaseOverwatchClipboard
+ id: GSCOverwatchClipboard
+ name: overwatch clipboard GSC
+ components:
+ - type: OverwatchConsole
+ faction: GSC
+
+- type: entity
+ parent: BaseOverwatchClipboard
+ id: CDOverwatchClipboard
+ name: overwatch console CD
+ components:
+ - type: OverwatchConsole
+ faction: CD