Skip to content

Ивентовый контент#545

Open
XxRaay wants to merge 10 commits intoimperial-space:developfrom
XxRaay:animatronic
Open

Ивентовый контент#545
XxRaay wants to merge 10 commits intoimperial-space:developfrom
XxRaay:animatronic

Conversation

@XxRaay
Copy link
Contributor

@XxRaay XxRaay commented Jan 2, 2026

О ПР`е

Тип: feat

Изменения: Ивентовый контент

Технические детали

Нет

Изменения кода официальных разработчиков

Нет

Summary by CodeRabbit

  • Новые функции

    • Портативный контроллер аниматроников с графическим окном для администрирования: выбор цели, сброс цели и режим наблюдения.
    • Четыре новых аниматроника с параметрами движения и сетью waypoint'ов, система навигации и повторной инициализации путей.
    • Контактный урон при столкновениях с перезарядкой.
  • Документация

    • Добавлены локализации (ru-RU) и новые прототипы/спрайты для аниматроников.

- Added AnimatronicControllerBoundUserInterface for managing animatronic interactions.
- Created AnimatronicControllerWindow for UI representation of animatronics and waypoints.
- Introduced AnimatronicRuntimeComponent to handle animatronic behavior.
- Developed AnimatronicControllerSystem to manage UI events and animatronic states.
- Added AnimatronicComponent and AnimatronicWaypointComponent for animatronic entities.
- Implemented networking events for animatronic control and state updates.
- Added prototypes for animatronic entities and waypoints, including visual assets.
@github-actions github-actions bot added size/Medium Насколько сложно будет апстримить Resprite Изменения заменяют оригинальные текстуры визардов Change Wiz Code Изменения вмешиваются в код визардов Prototypes Изменения добавляет новые прототипы C# Изменения добавляют новый C# код Change WIz Prototypes Изменения вмешиваются в код прототипов визардов Sprite Изменения добавляют спрайты UI Изменения затрагивают UI and removed size/Medium Насколько сложно будет апстримить labels Jan 2, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Добавлен полный набор функционала для управления аниматрониками: клиентский UI (AnimatronicControllerWindow и BoundUserInterface), сетевые сообщения/состояния (запрос данных, команды назначения цели и наблюдения, DTO для аниматроников и путевых точек), серверные системы (AnimatronicControllerSystem, AnimatronicTargetSystem, AnimatronicPathfindingSystem, AnimatronicSystem, AnimatronicDamageSystem) и компоненты (Animatronic, AnimatronicWaypoint, путь, урон, контроллер). Добавлены прототипы и ресурсы спрайтов. Клиент запрашивает состояние, отправляет команды; сервер формирует состояние, управляет целями, путями и рассылкой обновлений UI.

Sequence Diagram(s)

sequenceDiagram
    participant User as Пользователь
    participant UI as AnimatronicControllerWindow\n(Клиент UI)
    participant BUI as AnimatronicControllerBoundUserInterface\n(Клиент BUI)
    participant Net as Сеть
    participant ACS as AnimatronicControllerSystem\n(Сервер)
    participant ATS as AnimatronicTargetSystem\n(Сервер)
    participant APS as AnimatronicPathfindingSystem\n(Сервер)

    rect rgba(220,240,255,0.5)
    Note over User,ACS: Открытие UI и запрос данных
    User->>UI: Открывает окно
    UI->>BUI: Open() / подписка на события
    BUI->>Net: RequestAnimDataEvent
    Net->>ACS: Получен запрос
    ACS->>ACS: BuildAnimDataState()
    ACS->>Net: AnimDataStateEvent
    Net->>BUI: Получено состояние
    BUI->>UI: UpdateState()
    end

    rect rgba(240,255,240,0.5)
    Note over User,APS: Назначение цели аниматронику
    User->>UI: Выбирает waypoint
    UI->>BUI: OnAnimatronicWaypointSelected
    BUI->>Net: SetAnimatronicTargetEvent(anim, waypoint)
    Net->>ACS: Команда получена
    ACS->>ATS: SetTarget(anim, waypoint)
    ATS->>ATS: Валидация и регистрация в NPCSteering
    ATS->>APS: InitializePathRetryIfNeeded(anim)
    APS->>APS: Инициация поиска пути
    ACS->>Net: AnimDataStateEvent (обновл.)
    Net->>BUI: Обновление состояния
    BUI->>UI: UpdateState()
    end

    rect rgba(255,240,240,0.5)
    Note over APS,ACS: Движение, достижение и обновление UI
    APS->>APS: UpdatePathIfNeeded() / HandlePathAvailability()
    APS->>APS: OnReachedTarget() при достижении
    APS->>ACS: AnimatronicReachedTargetEvent
    ACS->>ACS: UpdateAllOpenUis()
    ACS->>Net: AnimDataStateEvent (цель достигнута)
    Net->>BUI: Получено обновление
    BUI->>UI: UpdateState()
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive Название PR на русском языке «Ивентовый контент» слишком расплывчато и не отражает конкретную суть изменений. Изменения включают полную реализацию системы контроля аниматроников (компоненты, системы, UI, прототипы, локализацию), но заголовок просто указывает на «контент события» без деталей. Уточните название, например: «Добавить систему контроля аниматроников для ивента» или «Реализовать контроллер аниматроников (UI, системы, компоненты, прототипы)» для большей информативности.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fcbc42 and 0b1f88d.

⛔ Files ignored due to path filters (10)
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/bonnie.png is excluded by !**/*.png
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/chica.png is excluded by !**/*.png
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/foxy.png is excluded by !**/*.png
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/freddy.png is excluded by !**/*.png
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/icon bonnie.png is excluded by !**/*.png
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/icon chica.png is excluded by !**/*.png
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/icon foxy.png is excluded by !**/*.png
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/icon freddy.png is excluded by !**/*.png
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/icon metal frame.png is excluded by !**/*.png
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/metal frame.png is excluded by !**/*.png
📒 Files selected for processing (16)
  • Content.Client/Imperial/XxRaay/UI/AnimatronicControllerBoundUserInterface.cs
  • Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml
  • Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs
  • Content.Server/Imperial/XxRaay/Components/AnimatronicRuntimeComponent.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerComponent.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerUiKey.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicWaypointComponent.cs
  • Content.Shared/Imperial/XxRaay/Components/Events/AnimatronicReachedTargetEvent.cs
  • Resources/Prototypes/Imperial/XxRaay/animatronic_controller.yml
  • Resources/Prototypes/Imperial/XxRaay/animatronic_waypoints.yml
  • Resources/Prototypes/Imperial/XxRaay/animatronics.yml
  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/meta.json
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: XxRaay
Repo: imperial-space/SS14-public PR: 317
File: Content.Server/Imperial/Power/EntitySystems/Events/SupermatterLightningEvent.cs:9-12
Timestamp: 2025-07-31T09:43:48.369Z
Learning: Пользователь XxRaay в проекте imperial-space/SS14-public предпочитает оставлять комментарии к коду на русском языке и не считает необходимым переводить их на английский.
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил неточность в анализе using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs - Content.Shared.Item действительно используется (ItemComponent), в отличие от Robust.Shared.Map и Robust.Server.GameObjects которые не используются.
📚 Learning: 2025-09-10T05:01:24.544Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 437
File: Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs:24-27
Timestamp: 2025-09-10T05:01:24.544Z
Learning: В проекте imperial-space/SS14-public система взаимодействий позволяет экипированным предметам получать события AfterInteractEvent. Когда пользователь взаимодействует с целью, экипированный предмет может получить событие как "используемая" сущность (Used), где args.User - это пользователь, а args.Target - цель взаимодействия. Поэтому подписка SubscribeLocalEvent<ComponentType, AfterInteractEvent> на компоненты экипированных предметов работает корректно.

Applied to files:

  • Content.Shared/Imperial/XxRaay/Components/Events/AnimatronicReachedTargetEvent.cs
📚 Learning: 2025-07-27T16:27:11.103Z
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 354
File: Resources/Textures/Imperial/Seriozha/SCP/airlocks/doorremoreall.rsi/meta.json:1-14
Timestamp: 2025-07-27T16:27:11.103Z
Learning: В проекте imperial-space/SS14-public пользователь Stevensegege указал, что дублирование метаданных между файлами doorremote.rsi и doorremoreall.rsi в Resources/Textures/Imperial/Seriozha/SCP/airlocks/ является необходимым и преднамеренным решением для данного случая.

Applied to files:

  • Resources/Textures/Imperial/XxRaay/animatronics.rsi/meta.json
📚 Learning: 2025-08-04T20:34:48.192Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил неточность в анализе using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs - Content.Shared.Item действительно используется (ItemComponent), в отличие от Robust.Shared.Map и Robust.Server.GameObjects которые не используются.

Applied to files:

  • Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerComponent.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs
📚 Learning: 2025-08-04T20:34:48.192Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил анализ using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs: Content.Shared.Item используется (ItemComponent на строке 70), Robust.Shared.Map используется (IMapManager на строке 44), только Robust.Server.GameObjects действительно не используется и должна быть удалена.

Applied to files:

  • Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerComponent.cs
🧬 Code graph analysis (9)
Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs (2)
Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs (2)
  • SetAnimatronicTargetEvent (26-31)
  • SetAnimatronicTargetEvent (33-38)
Content.Shared/Imperial/XxRaay/Components/Events/AnimatronicReachedTargetEvent.cs (1)
  • AnimatronicReachedTargetEvent (8-10)
Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs (3)
Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs (2)
  • Initialize (38-44)
  • OnSetTarget (46-94)
Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs (9)
  • SetAnimatronicTargetEvent (26-31)
  • SetAnimatronicTargetEvent (33-38)
  • SetAnimatronicObservingEvent (46-49)
  • AnimDto (76-78)
  • AnimDto (80-85)
  • WaypointDto (95-97)
  • WaypointDto (99-104)
  • AnimDataStateEvent (58-60)
  • AnimDataStateEvent (62-66)
Content.Shared/Imperial/XxRaay/Components/Events/AnimatronicReachedTargetEvent.cs (1)
  • AnimatronicReachedTargetEvent (8-10)
Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerComponent.cs (3)
Content.Server/Imperial/XxRaay/Components/AnimatronicRuntimeComponent.cs (1)
  • RegisterComponent (7-11)
Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs (1)
  • RegisterComponent (15-65)
Content.Shared/Imperial/XxRaay/Components/AnimatronicWaypointComponent.cs (1)
  • RegisterComponent (9-18)
Content.Shared/Imperial/XxRaay/Components/AnimatronicWaypointComponent.cs (3)
Content.Server/Imperial/XxRaay/Components/AnimatronicRuntimeComponent.cs (1)
  • RegisterComponent (7-11)
Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs (1)
  • RegisterComponent (15-65)
Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerComponent.cs (1)
  • RegisterComponent (9-12)
Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs (2)
Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs (6)
  • AnimDto (76-78)
  • AnimDto (80-85)
  • WaypointDto (95-97)
  • WaypointDto (99-104)
  • AnimDataStateEvent (58-60)
  • AnimDataStateEvent (62-66)
Content.Client/Imperial/XxRaay/UI/AnimatronicControllerBoundUserInterface.cs (1)
  • UpdateState (39-47)
Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerUiKey.cs (1)
Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs (6)
  • NetSerializable (14-17)
  • NetSerializable (19-39)
  • NetSerializable (41-50)
  • NetSerializable (52-67)
  • NetSerializable (69-86)
  • NetSerializable (88-105)
Content.Server/Imperial/XxRaay/Components/AnimatronicRuntimeComponent.cs (3)
Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs (1)
  • RegisterComponent (15-65)
Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerComponent.cs (1)
  • RegisterComponent (9-12)
Content.Shared/Imperial/XxRaay/Components/AnimatronicWaypointComponent.cs (1)
  • RegisterComponent (9-18)
Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs (3)
Content.Server/Imperial/XxRaay/Components/AnimatronicRuntimeComponent.cs (1)
  • RegisterComponent (7-11)
Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerComponent.cs (1)
  • RegisterComponent (9-12)
Content.Shared/Imperial/XxRaay/Components/AnimatronicWaypointComponent.cs (1)
  • RegisterComponent (9-18)
Content.Client/Imperial/XxRaay/UI/AnimatronicControllerBoundUserInterface.cs (2)
Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs (2)
  • AnimatronicControllerWindow (29-33)
  • UpdateState (35-53)
Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs (5)
  • SetAnimatronicTargetEvent (26-31)
  • SetAnimatronicTargetEvent (33-38)
  • SetAnimatronicObservingEvent (46-49)
  • AnimDataStateEvent (58-60)
  • AnimDataStateEvent (62-66)
🔇 Additional comments (15)
Content.Shared/Imperial/XxRaay/Components/AnimatronicWaypointComponent.cs (2)

6-18: Хорошая документация и структура компонента.

Компонент правильно оформлен с XML-документацией, атрибутами RegisterComponent и NetworkedComponent, а также с DataField для сериализации. Структура соответствует паттернам SS14 ECS.


13-14: Текущее состояние: все прототипы корректно инициализируют waypointId.

Проверка показала, что все 6 waypoint-прототипов в файле Resources/Prototypes/Imperial/XxRaay/animatronic_waypoints.yml явно устанавливают непустые значения waypointId (WP1–WP6). Системы AnimatronicSystem и AnimatronicControllerSystem используют эти значения без ошибок. Дефолтное значение string.Empty является невидимым fallback'ом.

Хотя код работает корректно в текущем состоянии, с точки зрения defensive programming можно рассмотреть добавление валидации при инициализации компонента, чтобы гарантировать, что пустые ID не будут случайно введены в будущих прототипах.

Resources/Prototypes/Imperial/XxRaay/animatronic_controller.yml (1)

1-27: Хорошо настроенный админский инструмент.

Прототип корректно настроен как административный инструмент с ограничениями:

  • adminOnly: true - доступ только для администраторов
  • singleUser: true - предотвращает конфликты при одновременном использовании
  • inHandsOnly: true - требует держать в руках, предотвращает злоупотребления

Структура соответствует стандартам SS14, и привязка к AnimatronicControllerBoundUserInterface интегрируется с клиентским UI из других файлов PR.

Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerUiKey.cs (1)

6-10: Корректная реализация UI ключа.

Enum правильно определён с атрибутом NetSerializable для сетевой сериализации и типом byte для эффективности. Структура соответствует паттернам SS14 для UI ключей и корректно используется в прототипе контроллера.

Resources/Textures/Imperial/XxRaay/animatronics.rsi/meta.json (1)

7-8: Метаданные файла корректны. Атрибуция "Askall" и лицензия CC-BY-SA-3.0 соответствуют стандартам проекта и не требуют изменений.

Content.Shared/Imperial/XxRaay/Components/Events/AnimatronicReachedTargetEvent.cs (1)

1-10: LGTM! Корректная реализация события-маркера.

Пустое событие, наследующее EntityEventArgs, является стандартным паттерном для событий-маркеров в ECS-архитектуре. Документация на русском языке соответствует предпочтениям проекта.

Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerComponent.cs (1)

1-13: LGTM! Корректная реализация компонента-маркера.

Пустой компонент с атрибутами [RegisterComponent] и [NetworkedComponent] является стандартным паттерном для tag-компонентов, которые просто помечают сущность (в данном случае - портативный контроллер аниматроников). Документация на русском языке соответствует стандартам проекта.

Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml (1)

1-15: LGTM! Корректная структура UI для контроллера аниматроников.

XAML-разметка выглядит правильно:

  • Наследуется от BaseImperialWindow (соответствует стилю проекта)
  • Разумные размеры окна (минимум 700×400, по умолчанию 800×450)
  • ScrollContainer для списка аниматроников обеспечит прокрутку при большом количестве элементов
  • Публичный доступ к Contents и AnimatronicsList позволяет code-behind динамически заполнять UI
Resources/Prototypes/Imperial/XxRaay/animatronics.yml (3)

67-72: Дублирование скорости (Chicken).

Та же проблема дублирования moveSpeed (2.2) и baseWalkSpeed/baseSprintSpeed (2.2).

⛔ Skipped due to learnings
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 413
File: Resources/Prototypes/Imperial/Crook/misc.yml:474-476
Timestamp: 2025-09-02T08:08:35.555Z
Learning: В проекте imperial-space/SS14-public для сущности MobDeathmoth в файле Resources/Prototypes/Imperial/Crook/misc.yml преднамеренно установлено значение baseSprintSpeed (2) меньше чем baseWalkSpeed (3.5) - это дизайнерское решение, а не ошибка.
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 354
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:114-117
Timestamp: 2025-07-27T16:35:42.639Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что дублирование пути спрайта в компонентах Sprite и Clothing для entity ImperialSCPMask в файле Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml является преднамеренным дизайнерским решением.
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 371
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:20-24
Timestamp: 2025-08-05T20:05:21.550Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что компонент SlowOnDamage с enabled: false в ImperialSCPBase является правильным переопределением родительского компонента из SimpleSpaceMobBase, который содержит настройки speedModifierThresholds.

83-88: Дублирование скорости (Foxar).

Та же проблема дублирования moveSpeed (7) и baseWalkSpeed/baseSprintSpeed (7).

⛔ Skipped due to learnings
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 413
File: Resources/Prototypes/Imperial/Crook/misc.yml:474-476
Timestamp: 2025-09-02T08:08:35.555Z
Learning: В проекте imperial-space/SS14-public для сущности MobDeathmoth в файле Resources/Prototypes/Imperial/Crook/misc.yml преднамеренно установлено значение baseSprintSpeed (2) меньше чем baseWalkSpeed (3.5) - это дизайнерское решение, а не ошибка.
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 371
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:20-24
Timestamp: 2025-08-05T20:05:21.550Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что компонент SlowOnDamage с enabled: false в ImperialSCPBase является правильным переопределением родительского компонента из SimpleSpaceMobBase, который содержит настройки speedModifierThresholds.
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 354
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:114-117
Timestamp: 2025-07-27T16:35:42.639Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что дублирование пути спрайта в компонентах Sprite и Clothing для entity ImperialSCPMask в файле Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml является преднамеренным дизайнерским решением.
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 437
File: Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs:0-0
Timestamp: 2025-09-10T04:59:56.355Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv (автор PR #437) уточнил, что DoAfter для копирования частот гарнитурой ниндзя должен прерываться при получении урона или движении, несмотря на то что в описании PR было указано "не должен прерываться". Правильные настройки: BreakOnDamage = true, BreakOnMove = true.

51-56: Дублирование скорости (Bunny).

Та же проблема дублирования moveSpeed (2.2) и baseWalkSpeed/baseSprintSpeed (2.2).

⛔ Skipped due to learnings
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 413
File: Resources/Prototypes/Imperial/Crook/misc.yml:474-476
Timestamp: 2025-09-02T08:08:35.555Z
Learning: В проекте imperial-space/SS14-public для сущности MobDeathmoth в файле Resources/Prototypes/Imperial/Crook/misc.yml преднамеренно установлено значение baseSprintSpeed (2) меньше чем baseWalkSpeed (3.5) - это дизайнерское решение, а не ошибка.
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 354
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:114-117
Timestamp: 2025-07-27T16:35:42.639Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что дублирование пути спрайта в компонентах Sprite и Clothing для entity ImperialSCPMask в файле Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml является преднамеренным дизайнерским решением.
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 371
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:20-24
Timestamp: 2025-08-05T20:05:21.550Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что компонент SlowOnDamage с enabled: false в ImperialSCPBase является правильным переопределением родительского компонента из SimpleSpaceMobBase, который содержит настройки speedModifierThresholds.
Content.Client/Imperial/XxRaay/UI/AnimatronicControllerBoundUserInterface.cs (1)

1-57: LGTM!

Реализация AnimatronicControllerBoundUserInterface корректна и следует стандартным паттернам Robust Toolbox для связывания UI. Подписки на события правильно передают сообщения на сервер, состояние корректно пробрасывается в окно, а освобождение ресурсов реализовано правильно.

Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs (1)

1-107: LGTM!

Сетевые DTO и события реализованы корректно. Все классы имеют необходимые атрибуты [NetSerializable, Serializable] и параметрless конструкторы для десериализации. Структура данных хорошо организована.

Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs (1)

46-94: Методы служат разным целям и не являются дублированием.

OnSetTarget в AnimatronicControllerSystem обрабатывает UI-событие и вызывает UpdateUi(), в то время как OnSetTarget в AnimatronicSystem обрабатывает сетевое событие и управляет логикой повтора пути (LastPathRetryTime, LastWaypointUpdateTime) с проверкой статуса NPCSteeringComponent. Несмотря на пересечение в базовой логике установки цели, эти методы имеют различные ответственности и не могут быть объединены без потери функциональности.

Likely an incorrect or invalid review comment.

Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs (1)

22-23: Удалите неиспользуемое поле MoveSpeed.

Поле MoveSpeed объявлено, но не используется в AnimatronicSystem, AnimatronicControllerSystem или в остальной кодовой базе. Удалите это поле, если оно не планируется использовать в ближайшем будущем.

⛔ Skipped due to learnings
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил анализ using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs: Content.Shared.Item используется (ItemComponent на строке 70), Robust.Shared.Map используется (IMapManager на строке 44), только Robust.Server.GameObjects действительно не используется и должна быть удалена.
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 413
File: Resources/Prototypes/Imperial/Crook/misc.yml:474-476
Timestamp: 2025-09-02T08:08:35.555Z
Learning: В проекте imperial-space/SS14-public для сущности MobDeathmoth в файле Resources/Prototypes/Imperial/Crook/misc.yml преднамеренно установлено значение baseSprintSpeed (2) меньше чем baseWalkSpeed (3.5) - это дизайнерское решение, а не ошибка.
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил неточность в анализе using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs - Content.Shared.Item действительно используется (ItemComponent), в отличие от Robust.Shared.Map и Robust.Server.GameObjects которые не используются.
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 376
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:189-197
Timestamp: 2025-08-10T16:44:31.921Z
Learning: В файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs в методе IsContrabandItem параметр detector необходимо сохранять, даже если он не используется напрямую в теле метода, так как он передаётся в вызовы вложенных методов IsIgnoredByDetector и IsContrabandAllowed. Удаление этого параметра вызывает ошибки компиляции.
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 371
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:20-24
Timestamp: 2025-08-05T20:05:21.550Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что компонент SlowOnDamage с enabled: false в ImperialSCPBase является правильным переопределением родительского компонента из SimpleSpaceMobBase, который содержит настройки speedModifierThresholds.

@The-Fiafi
Copy link
Contributor

Обновите свою локальную ветвь и движок до версии 268.1.0

…line systems

- Deleted AnimatronicRuntimeComponent as it was no longer needed.
- Updated AnimatronicControllerSystem to utilize new target and pathfinding systems.
- Refactored AnimatronicSystem to improve target assignment and pathfinding logic.
- Enhanced AnimatronicComponent by consolidating properties and removing unused fields.
- Added AnimatronicReachedTargetEvent to signal when animatronics reach their targets.
- Updated prototypes to include new components for animatronics.
@github-actions github-actions bot added the size/Medium Насколько сложно будет апстримить label Jan 5, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Fix all issues with AI Agents 🤖
In @Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs:
- Around line 111-115: Метод UpdateUi содержит неиспользуемый параметр user;
уберите параметр user из сигнатуры UpdateUi(EntityUid controller, EntityUid
user) и обновите все вызовы UpdateUi(...) в проекте, либо если нужна информация
о пользователе — используйте user внутри метода для фильтрации/логирования перед
построением состояния (вызов BuildAnimDataState() и _ui.SetUiState(controller,
AnimatronicControllerUiKey.Key, state)); обеспечьте синхронность сигнатур в
местах вызова после изменения.

In @Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs:
- Around line 58-62: The OnAnimatronicCollideEnd handler only removes
OtherEntity from AnimatronicDamageComponent.LastContactDamage on
EndCollideEvent, which can leak entries if the other entity is deleted without
that event; add a handler subscribed to EntityTerminatingEvent (for example
OnOtherEntityTerminating) that takes EntityTerminatingEvent/EntityUid of the
terminating entity and removes that uid from
AnimatronicDamageComponent.LastContactDamage, and ensure the system
registers/unregisters that handler alongside the existing collision handlers so
entries are cleaned when entities are destroyed or teleported.

In @Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs:
- Around line 21-24: Remove the empty override of Initialize in the
AnimatronicPathfindingSystem class: the method currently only calls
base.Initialize(), so delete the Initialize() override from
Content.Server.Imperial.XxRaay.Systems.AnimatronicPathfindingSystem to rely on
the base implementation; if there is any future custom initialization needed,
reintroduce an override and add logic there, otherwise do not keep a redundant
method that only forwards to Base.

In @Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs:
- Around line 1-8: Remove the unused System.Numerics using directive from
AnimatronicTargetSystem.cs: open the file, locate the top using directives
(including "using System.Numerics;") and delete that line so only required
namespaces (e.g., Robust.Shared, Content.Shared...) remain; run the compiler or
IDE analyzer to confirm no remaining references to System.Numerics and that
Vector2 types resolve from Robust.Shared.

In @Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs:
- Around line 20-24: The field MoveSpeed on AnimatronicComponent is unused;
either remove the declaration 'public float MoveSpeed = 2.0f;' from the
AnimatronicComponent class to eliminate dead code, or if intended for future
behavior, wire it into the animatronic system (e.g., reference MoveSpeed from
the appropriate movement/AI system or component methods such as any movement
update method) and add unit/behavior tests to validate its effect; prefer
removing the unused MoveSpeed field if no consumer is added.

In @Content.Shared/Imperial/XxRaay/Components/AnimatronicConstants.cs:
- Around line 25-28: The DefaultWaypointUpdateInterval in AnimatronicConstants
(public static readonly TimeSpan DefaultWaypointUpdateInterval) is very short
(0.15s) and may harm server performance with many animatronics; increase it to a
less aggressive value (suggest 0.25–0.5 seconds) by updating the
TimeSpan.FromSeconds argument accordingly (e.g., TimeSpan.FromSeconds(0.25) or
TimeSpan.FromSeconds(0.5)) to reduce update frequency while keeping behavior
acceptable.
♻️ Duplicate comments (1)
Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs (1)

72-86: Отсутствует проверка прав администратора для AdminCameraEui.

AdminCameraEui — это административный инструмент. Текущая реализация позволяет любому игроку с доступом к контроллеру аниматроников открыть админ-камеру без проверки прав. Это уязвимость безопасности.

🔎 Предлагаемое исправление

Добавьте зависимость и проверку прав:

+using Content.Server.Administration.Managers;

 [Dependency] private readonly UserInterfaceSystem _ui = default!;
 [Dependency] private readonly AnimatronicTargetSystem _targetSystem = default!;
 [Dependency] private readonly AnimatronicPathfindingSystem _pathfindingSystem = default!;
 [Dependency] private readonly EuiManager _eui = default!;
+[Dependency] private readonly IAdminManager _admin = default!;

 private void OnSetObserving(Entity<AnimatronicControllerComponent> ent, ref SetAnimatronicObservingEvent args)
 {
 	if (args.Actor is not { Valid: true } player)
 		return;

 	var animUid = GetEntity(args.Animatronic);
 	if (!Exists(animUid) || !HasComp<AnimatronicComponent>(animUid))
 		return;

 	if (!TryComp<ActorComponent>(player, out var actor))
 		return;

+	// Проверка прав администратора
+	if (!_admin.IsAdmin(actor.PlayerSession))
+		return;
+
 	var ui = new AdminCameraEui(animUid);
 	_eui.OpenEui(ui, actor.PlayerSession);
 }
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b1f88d and b2e0db6.

📒 Files selected for processing (11)
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicConstants.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicDamageComponent.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicPathfindingComponent.cs
  • Content.Shared/Imperial/XxRaay/Components/Events/AnimatronicReachedTargetEvent.cs
  • Resources/Prototypes/Imperial/XxRaay/animatronics.yml
🧰 Additional context used
🧠 Learnings (15)
📓 Common learnings
Learnt from: XxRaay
Repo: imperial-space/SS14-public PR: 317
File: Content.Server/Imperial/Power/EntitySystems/Events/SupermatterLightningEvent.cs:9-12
Timestamp: 2025-07-31T09:43:48.369Z
Learning: Пользователь XxRaay в проекте imperial-space/SS14-public предпочитает оставлять комментарии к коду на русском языке и не считает необходимым переводить их на английский.
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил неточность в анализе using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs - Content.Shared.Item действительно используется (ItemComponent), в отличие от Robust.Shared.Map и Robust.Server.GameObjects которые не используются.
📚 Learning: 2025-09-02T08:08:35.555Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 413
File: Resources/Prototypes/Imperial/Crook/misc.yml:474-476
Timestamp: 2025-09-02T08:08:35.555Z
Learning: В проекте imperial-space/SS14-public для сущности MobDeathmoth в файле Resources/Prototypes/Imperial/Crook/misc.yml преднамеренно установлено значение baseSprintSpeed (2) меньше чем baseWalkSpeed (3.5) - это дизайнерское решение, а не ошибка.

Applied to files:

  • Resources/Prototypes/Imperial/XxRaay/animatronics.yml
📚 Learning: 2025-08-04T20:34:48.192Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил анализ using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs: Content.Shared.Item используется (ItemComponent на строке 70), Robust.Shared.Map используется (IMapManager на строке 44), только Robust.Server.GameObjects действительно не используется и должна быть удалена.

Applied to files:

  • Resources/Prototypes/Imperial/XxRaay/animatronics.yml
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicDamageComponent.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-08-04T20:34:48.192Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил неточность в анализе using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs - Content.Shared.Item действительно используется (ItemComponent), в отличие от Robust.Shared.Map и Robust.Server.GameObjects которые не используются.

Applied to files:

  • Resources/Prototypes/Imperial/XxRaay/animatronics.yml
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicDamageComponent.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicConstants.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicPathfindingComponent.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-09-10T06:08:33.954Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 437
File: Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs:71-73
Timestamp: 2025-09-10T06:08:33.954Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv указал, что в NinjaHeadsetSystem удаление проверки !headsetUid.HasValue после TryGetTargetHeadset вызовет ошибку, несмотря на то что метод возвращает true только когда headsetUid устанавливается в валидное значение. Это говорит о наличии крайних случаев или особенностей InventorySystem, требующих обе проверки.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
📚 Learning: 2025-08-10T16:44:31.921Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 376
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:189-197
Timestamp: 2025-08-10T16:44:31.921Z
Learning: В файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs в методе IsContrabandItem параметр detector необходимо сохранять, даже если он не используется напрямую в теле метода, так как он передаётся в вызовы вложенных методов IsIgnoredByDetector и IsContrabandAllowed. Удаление этого параметра вызывает ошибки компиляции.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs
📚 Learning: 2025-08-08T21:30:17.736Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 376
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:117-148
Timestamp: 2025-08-08T21:30:17.736Z
Learning: В файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs в методе CheckForContraband множественные вызовы IsContrabandItem для одной и той же сущности являются необходимыми - попытка оптимизации через сохранение результата в локальной переменной приводит к появлению проблем в работе системы.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
📚 Learning: 2025-09-03T14:12:14.463Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 418
File: Resources/Prototypes/Imperial/Crook/misc.yml:357-361
Timestamp: 2025-09-03T14:12:14.463Z
Learning: Пользователь CrookLv в проекте imperial-space/SS14-public подтвердил, что высокий структурный урон (Structural: 75) для entity Smiler в файле Resources/Prototypes/Imperial/Crook/misc.yml является преднамеренным дизайнерским решением для контента Backrooms.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-09-04T08:12:23.038Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 423
File: Resources/Prototypes/Imperial/Crook/misc.yml:648-651
Timestamp: 2025-09-04T08:12:23.038Z
Learning: Пользователь CrookLv в проекте imperial-space/SS14-public предпочитает использовать один порог в компоненте SlowOnDamage для сущности BackroomsBacteria вместо множественных порогов для лучшей читаемости состояния здоровья.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicDamageComponent.cs
📚 Learning: 2025-08-06T23:35:51.099Z
Learnt from: krevetkqqq
Repo: imperial-space/SS14-public PR: 366
File: Content.Server/Imperial/ElectroMouse/ElectroMouseSystem.cs:684-684
Timestamp: 2025-08-06T23:35:51.099Z
Learning: В проекте imperial-space/SS14-public пользователь krevetkqqq объяснил, что DamageDict в DamageableComponent всегда заготовлен со значениями 0 для всех типов урона, поэтому никогда не бывает пустым и не требует проверки на пустоту перед использованием LINQ операций.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicDamageComponent.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-08-02T17:48:55.569Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:132-145
Timestamp: 2025-08-02T17:48:55.569Z
Learning: Пользователь CrookLv в проекте imperial-space/SS14-public объяснил, что в системе MetalDetectorSystem не следует реагировать на все предметы с компонентами MeleeWeaponComponent или RangedWeaponComponent, поскольку это приведет к срабатыванию на безобидные предметы (игрушки, баллоны). Система должна полагаться на ContrabandComponent для определения действительно опасных предметов.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
📚 Learning: 2025-07-27T11:26:21.822Z
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 354
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:161-161
Timestamp: 2025-07-27T11:26:21.822Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public намеренно установил высокое значение Blunt: 122 для entity ImperialSCPDoc в файле Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml, объясняя это тем, что персонаж должен быть "крутым" - это преднамеренное дизайнерское решение для SCP контента.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
📚 Learning: 2025-08-05T20:05:21.550Z
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 371
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:20-24
Timestamp: 2025-08-05T20:05:21.550Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что компонент SlowOnDamage с enabled: false в ImperialSCPBase является правильным переопределением родительского компонента из SimpleSpaceMobBase, который содержит настройки speedModifierThresholds.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicDamageComponent.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-10-06T14:45:55.852Z
Learnt from: XxRaay
Repo: imperial-space/SS14-public PR: 468
File: Resources/Prototypes/Imperial/XxRaay/syndiebattle_uplink.yml:2172-2181
Timestamp: 2025-10-06T14:45:55.852Z
Learning: В файле Resources/Prototypes/Imperial/XxRaay/syndiebattle_uplink.yml сущность MobSyndieBattleCatSyndy (syndicat) имеет намеренно нулевой урон в ближнем бою (MeleeWeapon damage.types.Slash: 0), так как это преднамеренное дизайнерское решение.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs
📚 Learning: 2025-09-10T05:05:09.383Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 437
File: Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs:135-139
Timestamp: 2025-09-10T05:05:09.383Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv сообщил, что добавление Dirty(uid, ninjaEncryption) для EncryptionKeyHolderComponent в NinjaHeadsetSystem вызывает ошибки. В SS14 для уведомления об изменениях каналов EncryptionKeyHolderComponent используется событие EncryptionChannelsChangedEvent вместо прямого помечания компонента как Dirty.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
🧬 Code graph analysis (6)
Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs (3)
Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs (3)
  • AnimatronicTargetSystem (15-75)
  • ClearTarget (48-62)
  • SetTarget (19-46)
Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs (3)
  • AnimatronicPathfindingSystem (15-155)
  • Initialize (21-24)
  • InitializePathRetryIfNeeded (143-154)
Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs (2)
  • SetAnimatronicTargetEvent (26-31)
  • SetAnimatronicTargetEvent (33-38)
Content.Shared/Imperial/XxRaay/Components/AnimatronicDamageComponent.cs (3)
Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs (1)
  • RegisterComponent (10-31)
Content.Shared/Imperial/XxRaay/Components/AnimatronicPathfindingComponent.cs (1)
  • RegisterComponent (11-38)
Content.Shared/Imperial/XxRaay/Components/AnimatronicConstants.cs (1)
  • AnimatronicConstants (8-44)
Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs (4)
Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs (2)
  • AnimatronicTargetSystem (15-75)
  • SetTarget (19-46)
Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs (3)
  • AnimatronicPathfindingSystem (15-155)
  • Initialize (21-24)
  • InitializePathRetryIfNeeded (143-154)
Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs (2)
  • Initialize (20-24)
  • OnSetTarget (26-48)
Content.Shared/Imperial/XxRaay/Components/Events/AnimatronicReachedTargetEvent.cs (2)
  • AnimatronicReachedTargetEvent (9-20)
  • AnimatronicReachedTargetEvent (16-19)
Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs (4)
Content.Shared/Imperial/XxRaay/Components/AnimatronicDamageComponent.cs (1)
  • RegisterComponent (12-33)
Content.Shared/Imperial/XxRaay/Components/AnimatronicPathfindingComponent.cs (1)
  • RegisterComponent (11-38)
Content.Shared/Imperial/XxRaay/Components/AnimatronicControllerComponent.cs (1)
  • RegisterComponent (9-12)
Content.Shared/Imperial/XxRaay/Components/AnimatronicWaypointComponent.cs (1)
  • RegisterComponent (9-18)
Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs (1)
Content.Shared/Imperial/XxRaay/Components/AnimatronicConstants.cs (1)
  • AnimatronicConstants (8-44)
Content.Shared/Imperial/XxRaay/Components/AnimatronicPathfindingComponent.cs (3)
Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs (1)
  • RegisterComponent (10-31)
Content.Shared/Imperial/XxRaay/Components/AnimatronicDamageComponent.cs (1)
  • RegisterComponent (12-33)
Content.Shared/Imperial/XxRaay/Components/AnimatronicConstants.cs (1)
  • AnimatronicConstants (8-44)
🔇 Additional comments (16)
Content.Shared/Imperial/XxRaay/Components/AnimatronicConstants.cs (1)

15-18: Значение ContactDamage = 200 соответствует намеренному дизайну.

Это событийный контент FNAF (Five Nights at Freddy's), где аниматроники по задумке являются опасными противниками. Высокий урон согласуется с жанром и назначением контента, а реализация включает 1-секундный кулдаун для контроля частоты применения урона.

Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs (2)

1-10: Импорты корректны.

Все используемые директивы using применяются в коде: IGameTiming (строка 19), DamageableSystem (строка 20), MobStateSystem (строка 21), IPrototypeManager (строка 22), DamageSpecifier и DamageGroupPrototype (строки 46, 52), FixedPoint2 (строка 52), MobStateComponent (строка 35), StartCollideEvent/EndCollideEvent (строки 27-28).


31-56: Логика нанесения урона реализована корректно.

Метод правильно проверяет наличие необходимых компонентов, состояние моба, и применяет кулдаун. Использование ignoreResistances: true соответствует ожидаемому поведению аниматроников.

Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs (2)

26-48: Логика обработки цели реализована корректно.

Метод правильно обрабатывает сетевые события, делегирует работу специализированным системам и инициализирует повторный поиск пути при необходимости.


16-18: Неиспользуемая зависимость _steering.

Поле _steering (NPCSteeringSystem) объявлено, но нигде не используется в этой системе. Вся работа со steering делегируется через _targetSystem и _pathfindingSystem.

🔎 Предлагаемое исправление
 [Dependency] private readonly AnimatronicTargetSystem _targetSystem = default!;
 [Dependency] private readonly AnimatronicPathfindingSystem _pathfindingSystem = default!;
-[Dependency] private readonly NPCSteeringSystem _steering = default!;

Также удалите неиспользуемые импорты:

 using Content.Shared.Imperial.XxRaay.Components;
-using Content.Server.NPC.Systems;
 using Content.Server.NPC.Components;
 using Content.Shared.Movement.Components;
 using Content.Shared.NPC;
 using Robust.Shared.GameObjects;
-using Robust.Shared.Player;
⛔ Skipped due to learnings
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил анализ using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs: Content.Shared.Item используется (ItemComponent на строке 70), Robust.Shared.Map используется (IMapManager на строке 44), только Robust.Server.GameObjects действительно не используется и должна быть удалена.
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил неточность в анализе using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs - Content.Shared.Item действительно используется (ItemComponent), в отличие от Robust.Shared.Map и Robust.Server.GameObjects которые не используются.
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 437
File: Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs:71-73
Timestamp: 2025-09-10T06:08:33.954Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv указал, что в NinjaHeadsetSystem удаление проверки !headsetUid.HasValue после TryGetTargetHeadset вызовет ошибку, несмотря на то что метод возвращает true только когда headsetUid устанавливается в валидное значение. Это говорит о наличии крайних случаев или особенностей InventorySystem, требующих обе проверки.
Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs (3)

19-46: Метод SetTarget реализован корректно.

Логика валидации и установки цели охватывает все edge cases. Обеспечение необходимых компонентов (InputMoverComponent, ActiveNPCComponent) перед регистрацией steering — правильный подход.


64-74: Метод HasReachedTarget реализован корректно.

Проверка карты и расчёт расстояния через TransformSystem.GetWorldPosition — правильный подход. Использование константы AnimatronicConstants.ReachDistance обеспечивает единообразие.


57-61: Отсутствует вызов Dirty для AnimatronicPathfindingComponent.

После изменения LastPathRetryTime и LastWaypointUpdateTime необходимо вызвать Dirty(animatronic, pathfinding) для синхронизации состояния. Хотя эти поля помечены [NonSerialized] в AnimatronicPathfindingComponent, вызов Dirty обеспечит консистентность при наличии других сериализуемых полей.

🔎 Предлагаемое исправление
 if (TryComp<AnimatronicPathfindingComponent>(animatronic, out var pathfinding))
 {
 	pathfinding.LastPathRetryTime = null;
 	pathfinding.LastWaypointUpdateTime = null;
+	Dirty(animatronic, pathfinding);
 }
⛔ Skipped due to learnings
Learnt from: XxRaay
Repo: imperial-space/SS14-public PR: 459
File: Content.Server/Imperial/XxRaay/SyndieBattle/SyndieBattleRuleSystem.cs:296-335
Timestamp: 2025-09-23T17:15:12.540Z
Learning: В проекте imperial-space/SS14-public пользователь XxRaay подтвердил, что изменения StoreComponent.Balance и StoreComponent.Categories в методе GiveCustomUplink не требуют явного вызова Dirty() для корректной работы сетевой синхронизации.
Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs (3)

88-109: Рефакторинг BuildAnimDataState выполнен корректно.

Метод централизует построение состояния UI, устраняя дублирование кода между UpdateUi и UpdateAllOpenUis. Хорошая практика.


52-70: Логика обработки цели в контроллере корректна.

Метод правильно делегирует установку цели _targetSystem и инициализирует повторный поиск пути при необходимости. Обновление UI после каждого действия обеспечивает актуальность отображаемых данных.


117-129: Метод UpdateAllOpenUis реализован эффективно.

Однократный вызов BuildAnimDataState() перед итерацией контроллеров минимизирует накладные расходы. Проверка IsUiOpen предотвращает лишние обновления.

Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs (4)

26-51: Цикл обновления реализован корректно.

Структура с ранними continue обеспечивает читаемость. Валидация карты и наличия цели предотвращает ошибки при обработке.


53-81: Метод UpdatePathIfNeeded реализован корректно.

Логика обновления пути учитывает как изменение координат цели, так и временной интервал обновления. Сброс FailedPathCount при обновлении — правильный подход.


83-129: Логика обработки доступности пути корректна, но сложна.

Метод правильно обрабатывает различные состояния пути и механизм повторных попыток. Проверка justRegistered предотвращает ложные срабатывания сразу после регистрации.

Рассмотрите возможность добавления комментариев для пояснения двух основных ветвей логики (путь доступен vs. путь недоступен) для улучшения поддерживаемости.


131-154: Методы OnReachedTarget и InitializePathRetryIfNeeded реализованы корректно.

Событие AnimatronicReachedTargetEvent вызывается с правильным EntityUid. Паттерн Resolve в InitializePathRetryIfNeeded обеспечивает гибкость использования метода с опциональным компонентом.

Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs (1)

1-4: Неиспользуемый импорт Robust.Shared.Serialization.

Импорт Robust.Shared.Serialization не используется в этом файле. Атрибут [DataField] не требует этого namespace.

🔎 Предлагаемое исправление
 using Robust.Shared.GameStates;
-using Robust.Shared.Serialization;
 using Robust.Shared.GameObjects;
⛔ Skipped due to learnings
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил неточность в анализе using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs - Content.Shared.Item действительно используется (ItemComponent), в отличие от Robust.Shared.Map и Robust.Server.GameObjects которые не используются.
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил анализ using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs: Content.Shared.Item используется (ItemComponent на строке 70), Robust.Shared.Map используется (IMapManager на строке 44), только Robust.Server.GameObjects действительно не используется и должна быть удалена.
Learnt from: Ser1-1y
Repo: imperial-space/SS14-public PR: 375
File: Content.Shared/Pinpointer/NavMapRequest.cs:9-15
Timestamp: 2025-08-06T16:36:30.691Z
Learning: Robust.Shared.Serialization в проекте SS14 корректно сериализует [Serializable, NetSerializable] классы с readonly-полями и без параметрless-конструктора; менять их не нужно.

Comment on lines +58 to +62
private void OnAnimatronicCollideEnd(Entity<AnimatronicDamageComponent> ent, ref EndCollideEvent args)
{
var otherUid = args.OtherEntity;
ent.Comp.LastContactDamage.Remove(otherUid);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Потенциальная утечка памяти при удалении сущностей.

Если сущность удаляется без вызова EndCollideEvent (например, при телепортации или удалении), запись в LastContactDamage останется. Рекомендуется также подписаться на EntityTerminatingEvent для очистки словаря.

🔎 Предлагаемое исправление
 public override void Initialize()
 {
 	base.Initialize();
 	SubscribeLocalEvent<AnimatronicDamageComponent, StartCollideEvent>(OnAnimatronicCollide);
 	SubscribeLocalEvent<AnimatronicDamageComponent, EndCollideEvent>(OnAnimatronicCollideEnd);
+	SubscribeLocalEvent<AnimatronicDamageComponent, EntityTerminatingEvent>(OnAnimatronicTerminating);
 }

+private void OnAnimatronicTerminating(Entity<AnimatronicDamageComponent> ent, ref EntityTerminatingEvent args)
+{
+	ent.Comp.LastContactDamage.Clear();
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private void OnAnimatronicCollideEnd(Entity<AnimatronicDamageComponent> ent, ref EndCollideEvent args)
{
var otherUid = args.OtherEntity;
ent.Comp.LastContactDamage.Remove(otherUid);
}
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<AnimatronicDamageComponent, StartCollideEvent>(OnAnimatronicCollide);
SubscribeLocalEvent<AnimatronicDamageComponent, EndCollideEvent>(OnAnimatronicCollideEnd);
SubscribeLocalEvent<AnimatronicDamageComponent, EntityTerminatingEvent>(OnAnimatronicTerminating);
}
private void OnAnimatronicCollideEnd(Entity<AnimatronicDamageComponent> ent, ref EndCollideEvent args)
{
var otherUid = args.OtherEntity;
ent.Comp.LastContactDamage.Remove(otherUid);
}
private void OnAnimatronicTerminating(Entity<AnimatronicDamageComponent> ent, ref EntityTerminatingEvent args)
{
ent.Comp.LastContactDamage.Clear();
}
🤖 Prompt for AI Agents
In @Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs around
lines 58-62, The OnAnimatronicCollideEnd handler only removes OtherEntity from
AnimatronicDamageComponent.LastContactDamage on EndCollideEvent, which can leak
entries if the other entity is deleted without that event; add a handler
subscribed to EntityTerminatingEvent (for example OnOtherEntityTerminating) that
takes EntityTerminatingEvent/EntityUid of the terminating entity and removes
that uid from AnimatronicDamageComponent.LastContactDamage, and ensure the
system registers/unregisters that handler alongside the existing collision
handlers so entries are cleaned when entities are destroyed or teleported.

Comment on lines +21 to +24
public override void Initialize()
{
base.Initialize();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Пустой метод Initialize можно удалить.

Метод Initialize содержит только вызов base.Initialize(). В SS14 это необязательно, если нет дополнительной логики инициализации.

🔎 Предлагаемое исправление
-public override void Initialize()
-{
-	base.Initialize();
-}
-
 public override void Update(float frameTime)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public override void Initialize()
{
base.Initialize();
}
public override void Update(float frameTime)
{
// Update method body follows...
}
🤖 Prompt for AI Agents
In @Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs
around lines 21-24, Remove the empty override of Initialize in the
AnimatronicPathfindingSystem class: the method currently only calls
base.Initialize(), so delete the Initialize() override from
Content.Server.Imperial.XxRaay.Systems.AnimatronicPathfindingSystem to rely on
the base implementation; if there is any future custom initialization needed,
reintroduce an override and add logic there, otherwise do not keep a redundant
method that only forwards to Base.

Comment on lines +20 to +24
/// <summary>
/// Скорость движения аниматроника.
/// </summary>
[DataField("moveSpeed")]
public float MoveSpeed = 2.0f;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for all usages of MoveSpeed in C# files
rg -n 'MoveSpeed' --type=cs -B3 -A3

Repository: imperial-space/SS14-public

Length of output: 8233


🏁 Script executed:

# Search for AnimatronicComponent usage and property access
rg -n 'AnimatronicComponent' --type=cs -B2 -A5

Repository: imperial-space/SS14-public

Length of output: 7247


🏁 Script executed:

# Search for direct access to MoveSpeed property on AnimatronicComponent
rg -n '\.MoveSpeed|component\.MoveSpeed' --type=cs

Repository: imperial-space/SS14-public

Length of output: 52


Удалите неиспользуемое поле MoveSpeed.

Поле объявлено, но не используется ни в одной системе. Если оно предназначено для будущего использования, добавьте соответствующий код; в противном случае удалите его.

🤖 Prompt for AI Agents
In @Content.Shared/Imperial/XxRaay/Components/AnimatronicComponent.cs around
lines 20-24, The field MoveSpeed on AnimatronicComponent is unused; either
remove the declaration 'public float MoveSpeed = 2.0f;' from the
AnimatronicComponent class to eliminate dead code, or if intended for future
behavior, wire it into the animatronic system (e.g., reference MoveSpeed from
the appropriate movement/AI system or component methods such as any movement
update method) and add unit/behavior tests to validate its effect; prefer
removing the unused MoveSpeed field if no consumer is added.

Comment on lines +25 to +28
/// <summary>
/// Интервал по умолчанию для обновления позиции waypoint'а (если он перемещается).
/// </summary>
public static readonly TimeSpan DefaultWaypointUpdateInterval = TimeSpan.FromSeconds(0.15);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Рассмотрите увеличение интервала обновления позиции waypoint.

Интервал обновления DefaultWaypointUpdateInterval = 0.15 секунды (150 мс) достаточно агрессивный. При наличии нескольких активных аниматроников это может негативно сказаться на производительности сервера из-за частых обновлений позиций.

Рекомендуется увеличить интервал до 0.25-0.5 секунды, если это не критично для игрового процесса.

🤖 Prompt for AI Agents
In @Content.Shared/Imperial/XxRaay/Components/AnimatronicConstants.cs around
lines 25-28, The DefaultWaypointUpdateInterval in AnimatronicConstants (public
static readonly TimeSpan DefaultWaypointUpdateInterval) is very short (0.15s)
and may harm server performance with many animatronics; increase it to a less
aggressive value (suggest 0.25–0.5 seconds) by updating the TimeSpan.FromSeconds
argument accordingly (e.g., TimeSpan.FromSeconds(0.25) or
TimeSpan.FromSeconds(0.5)) to reduce update frequency while keeping behavior
acceptable.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Fix all issues with AI agents
In @Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs:
- Around line 111-115: The method UpdateUi has an unused parameter user—remove
the user parameter from the UpdateUi signature (keep UpdateUi(EntityUid
controller)) and update all call sites that pass a user (the calls referenced
near lines 44, 49, 57, 69) to call the new two-argument-less signature; ensure
any delegates or event-handler registrations that reference UpdateUi are updated
to match the new signature (use the method name UpdateUi to locate and change
them).
- Around line 72-86: The OnSetObserving handler opens AdminCameraEui without
checking administrative rights; add an IAdminManager dependency (e.g.,
[Dependency] private readonly IAdminManager _admin = default!) to the system
and, inside OnSetObserving before constructing/opening the UI (before new
AdminCameraEui(...) and _eui.OpenEui(...)), call
_admin.GetAdminData(actor.PlayerSession) and return if it is null to prevent
non-admins from opening the admin camera UI.
- Around line 52-70: OnSetTarget currently ignores the boolean result of
_targetSystem.SetTarget; capture its return value, and if it is false log a
warning including animUid and waypoint/args.Clear (and actor if available) so
failures are visible, and only call
_pathfindingSystem.InitializePathRetryIfNeeded and/or proceed with further
actions (like UpdateUi) when SetTarget returned true (or at least document why
UI should still update on failure).

In @Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs:
- Around line 48-52: The code hardcodes the "Brute" damage group; add a
configurable field to AnimatronicDamageComponent (e.g., public string
DamageGroup = "Brute"; annotated with [DataField("damageGroup")]) and change the
lookup in AnimatronicDamageSystem from
_prototype.TryIndex<DamageGroupPrototype>("Brute", out var bruteGroup) to use
the component value:
_prototype.TryIndex<DamageGroupPrototype>(component.DamageGroup, out var
bruteGroup), making sure to null-check component and fall back to the default if
needed.

In @Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs:
- Around line 52-66: ClearTarget currently calls
_steering.Unregister(animatronic) unconditionally; change it to only call
Unregister when the animatronic actually has a target (check anim.TargetWaypoint
!= null) to make the intent explicit and avoid unregistering non-registered
entities; locate the ClearTarget method and wrap or gate the
_steering.Unregister(animatronic) call with a conditional that inspects the
AnimatronicComponent.TargetWaypoint (or equivalent) before calling Unregister,
leaving the rest of the cleanup (clearing TargetWaypoint, Dirty(animatronic,
anim), and resetting AnimatronicPathfindingComponent timing fields) intact.
- Around line 28-50: The method sets anim.TargetWaypoint, calls
Dirty(animatronic, anim), and
EnsureComp<InputMoverComponent>/EnsureComp<ActiveNPCComponent> before attempting
to get the waypoint Transform and register with _steering, so if
TryComp<TransformComponent> fails (or registration fails) the mover/active
components remain incorrectly added; modify the logic in AnimatronicTargetSystem
(the block that uses waypoint, EnsureComp<...>, TryComp<TransformComponent>, and
_steering.Register) to first verify the waypoint Transform and perform the
_steering.Register call (or check Register's success) and only then call
EnsureComp<InputMoverComponent> and EnsureComp<ActiveNPCComponent>, or
alternatively roll back/remove those components (via RemComp or ClearTarget) if
registration fails, ensuring state is consistent when the method returns false.
- Line 21: Private field naming violates convention: rename the injected field
TransformSystem to follow private camelCase with underscore. Change the field
declaration [Dependency] private readonly SharedTransformSystem TransformSystem
= default! to use _transformSystem, and update all usages of TransformSystem
(e.g., the references around the former lines 73-74) to _transformSystem so the
symbol name is consistent across the class.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2e0db6 and bb476de.

📒 Files selected for processing (3)
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: XxRaay
Repo: imperial-space/SS14-public PR: 317
File: Content.Server/Imperial/Power/EntitySystems/Events/SupermatterLightningEvent.cs:9-12
Timestamp: 2025-07-31T09:43:48.369Z
Learning: Пользователь XxRaay в проекте imperial-space/SS14-public предпочитает оставлять комментарии к коду на русском языке и не считает необходимым переводить их на английский.
Learnt from: onionsenpai-git
Repo: imperial-space/SS14-public PR: 394
File: Resources/Textures/Imperial/Other/ElysiumPrime/Misc/signs.rsi/meta.json:0-0
Timestamp: 2025-08-22T21:36:29.320Z
Learning: В проекте imperial-space/SS14-public движок корректно работает с горизонтальной упаковкой кадров в RSI спрайтах, даже если ширина PNG превышает size.x в meta.json файле. Пользователь onionsenpai-git подтвердил, что спрайты с размерами 64x32 при size.x=32 в meta.json работают без проблем.
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 354
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:114-117
Timestamp: 2025-07-27T16:35:42.639Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что дублирование пути спрайта в компонентах Sprite и Clothing для entity ImperialSCPMask в файле Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml является преднамеренным дизайнерским решением.
📚 Learning: 2025-09-10T06:08:33.954Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 437
File: Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs:71-73
Timestamp: 2025-09-10T06:08:33.954Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv указал, что в NinjaHeadsetSystem удаление проверки !headsetUid.HasValue после TryGetTargetHeadset вызовет ошибку, несмотря на то что метод возвращает true только когда headsetUid устанавливается в валидное значение. Это говорит о наличии крайних случаев или особенностей InventorySystem, требующих обе проверки.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
📚 Learning: 2025-08-04T20:34:48.192Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил неточность в анализе using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs - Content.Shared.Item действительно используется (ItemComponent), в отличие от Robust.Shared.Map и Robust.Server.GameObjects которые не используются.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-09-10T05:05:09.383Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 437
File: Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs:135-139
Timestamp: 2025-09-10T05:05:09.383Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv сообщил, что добавление Dirty(uid, ninjaEncryption) для EncryptionKeyHolderComponent в NinjaHeadsetSystem вызывает ошибки. В SS14 для уведомления об изменениях каналов EncryptionKeyHolderComponent используется событие EncryptionChannelsChangedEvent вместо прямого помечания компонента как Dirty.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-08-04T20:34:48.192Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил анализ using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs: Content.Shared.Item используется (ItemComponent на строке 70), Robust.Shared.Map используется (IMapManager на строке 44), только Robust.Server.GameObjects действительно не используется и должна быть удалена.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-08-02T17:48:55.569Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:132-145
Timestamp: 2025-08-02T17:48:55.569Z
Learning: Пользователь CrookLv в проекте imperial-space/SS14-public объяснил, что в системе MetalDetectorSystem не следует реагировать на все предметы с компонентами MeleeWeaponComponent или RangedWeaponComponent, поскольку это приведет к срабатыванию на безобидные предметы (игрушки, баллоны). Система должна полагаться на ContrabandComponent для определения действительно опасных предметов.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
📚 Learning: 2025-09-10T06:06:57.116Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 437
File: Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs:10-14
Timestamp: 2025-09-10T06:06:57.116Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv (автор PR #437) сообщил, что добавление using System.Collections.Generic; не требуется в файле Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs, несмотря на использование HashSet и List в коде.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs
📚 Learning: 2025-08-10T16:44:31.921Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 376
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:189-197
Timestamp: 2025-08-10T16:44:31.921Z
Learning: В файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs в методе IsContrabandItem параметр detector необходимо сохранять, даже если он не используется напрямую в теле метода, так как он передаётся в вызовы вложенных методов IsIgnoredByDetector и IsContrabandAllowed. Удаление этого параметра вызывает ошибки компиляции.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs
📚 Learning: 2025-08-06T23:35:51.099Z
Learnt from: krevetkqqq
Repo: imperial-space/SS14-public PR: 366
File: Content.Server/Imperial/ElectroMouse/ElectroMouseSystem.cs:684-684
Timestamp: 2025-08-06T23:35:51.099Z
Learning: В проекте imperial-space/SS14-public пользователь krevetkqqq объяснил, что DamageDict в DamageableComponent всегда заготовлен со значениями 0 для всех типов урона, поэтому никогда не бывает пустым и не требует проверки на пустоту перед использованием LINQ операций.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-08-05T20:05:21.550Z
Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 371
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:20-24
Timestamp: 2025-08-05T20:05:21.550Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что компонент SlowOnDamage с enabled: false в ImperialSCPBase является правильным переопределением родительского компонента из SimpleSpaceMobBase, который содержит настройки speedModifierThresholds.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
📚 Learning: 2025-09-03T14:12:14.463Z
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 418
File: Resources/Prototypes/Imperial/Crook/misc.yml:357-361
Timestamp: 2025-09-03T14:12:14.463Z
Learning: Пользователь CrookLv в проекте imperial-space/SS14-public подтвердил, что высокий структурный урон (Structural: 75) для entity Smiler в файле Resources/Prototypes/Imperial/Crook/misc.yml является преднамеренным дизайнерским решением для контента Backrooms.

Applied to files:

  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
🧬 Code graph analysis (2)
Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs (5)
Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs (2)
  • AnimatronicTargetSystem (18-79)
  • SetTarget (23-50)
Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs (3)
  • AnimatronicPathfindingSystem (15-155)
  • Initialize (21-24)
  • InitializePathRetryIfNeeded (143-154)
Content.Server/Imperial/XxRaay/Systems/AnimatronicSystem.cs (2)
  • Initialize (20-24)
  • OnSetTarget (26-48)
Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs (2)
  • SetAnimatronicTargetEvent (26-31)
  • SetAnimatronicTargetEvent (33-38)
Content.Shared/Imperial/XxRaay/Components/Events/AnimatronicReachedTargetEvent.cs (2)
  • AnimatronicReachedTargetEvent (9-20)
  • AnimatronicReachedTargetEvent (16-19)
Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs (2)
Content.Server.Database/Model.cs (1)
  • Server (707-719)
Content.Shared/Imperial/XxRaay/Components/AnimatronicConstants.cs (1)
  • AnimatronicConstants (8-44)
🔇 Additional comments (9)
Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs (7)

1-12: LGTM: Импорты корректны.

Все using-директивы используются в коде, избыточных импортов нет.


17-22: LGTM: Зависимости корректно объявлены.

Все внедренные зависимости используются в методах системы.


24-35: LGTM: Инициализация событий выполнена корректно.

Подписки на события BUI и локальное событие AnimatronicReachedTargetEvent настроены правильно.


37-40: LGTM: Обработка события достижения цели.

Обновление всех открытых UI при достижении цели аниматроником реализовано корректно.


42-50: LGTM: Обработчики открытия UI и запроса данных.

Оба обработчика корректно вызывают обновление UI для пользователя.


88-109: LGTM: Рефакторинг извлечения данных состояния.

Метод BuildAnimDataState успешно устраняет дублирование кода, отмеченное в предыдущем review. Логика построения списков аниматроников и вейпоинтов вынесена в отдельный метод, что улучшает читаемость и поддерживаемость кода.


117-129: LGTM: Обновление всех открытых UI.

Метод UpdateAllOpenUis корректно рассылает обновленное состояние всем открытым интерфейсам контроллеров аниматроников.

Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs (1)

68-78: LGTM: корректная проверка достижения цели.

Метод HasReachedTarget корректно проверяет:

  • Валидность MapID (не Nullspace и совпадение карт)
  • Расстояние между позициями через мировые координаты
  • Использование константы AnimatronicConstants.ReachDistance для порога

Логика реализована правильно и эффективно.

Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs (1)

48-56: Добавьте комментарий, объясняющий игнорирование сопротивлений для контактного урона аниматроников.

На строке 55 используется ignoreResistances: true, игнорирующий броню и защиту цели. Хотя подобный паттерн применяется и для других специальных видов урона (температура, неуничтожимые объекты), отсутствие комментария создаёт неясность о дизайнерском намерении.

Если это преднамеренное решение для повышения сложности игровых событий, добавьте пояснительный комментарий. Если это не было обдуманным выбором, рассмотрите удаление параметра.

♻️ Рекомендуемое исправление (вариант 1 – с комментарием)
 var damage = new DamageSpecifier(bruteGroup, FixedPoint2.New(damageComp.ContactDamage));
+// Аниматроники игнорируют броню как часть механики события
 _damageable.TryChangeDamage(otherUid, damage, ignoreResistances: true, origin: ent.Owner);

Comment on lines +52 to +70
private void OnSetTarget(Entity<AnimatronicControllerComponent> ent, ref SetAnimatronicTargetEvent args)
{
var animUid = GetEntity(args.Animatronic);
if (!TryComp<AnimatronicComponent>(animUid, out var anim))
{
UpdateUi(ent.Owner, args.Actor);
return;
}

EntityUid? wpUid = args.Clear ? null : GetEntity(args.Waypoint);
_targetSystem.SetTarget(animUid, wpUid);

if (!args.Clear && TryComp<AnimatronicPathfindingComponent>(animUid, out var pathfinding))
{
_pathfindingSystem.InitializePathRetryIfNeeded(animUid, pathfinding);
}

UpdateUi(ent.Owner, args.Actor);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Рассмотрите обработку результата SetTarget.

Метод _targetSystem.SetTarget возвращает bool, указывающий на успех операции, но возвращаемое значение не проверяется. Хотя UI всегда обновляется и отобразит текущее состояние, явная проверка и логирование неудачных попыток может помочь при отладке.

♻️ Предлагаемое улучшение
 private void OnSetTarget(Entity<AnimatronicControllerComponent> ent, ref SetAnimatronicTargetEvent args)
 {
 	var animUid = GetEntity(args.Animatronic);
 	if (!TryComp<AnimatronicComponent>(animUid, out var anim))
 	{
 		UpdateUi(ent.Owner, args.Actor);
 		return;
 	}
 
 	EntityUid? wpUid = args.Clear ? null : GetEntity(args.Waypoint);
-	_targetSystem.SetTarget(animUid, wpUid);
+	var success = _targetSystem.SetTarget(animUid, wpUid);
+	if (!success && !args.Clear)
+	{
+		// Логирование неудачной попытки установки цели
+		Log.Warning($"Не удалось установить цель для аниматроника {animUid}");
+	}
 
 	if (!args.Clear && TryComp<AnimatronicPathfindingComponent>(animUid, out var pathfinding))
 	{
 		_pathfindingSystem.InitializePathRetryIfNeeded(animUid, pathfinding);
 	}
 
 	UpdateUi(ent.Owner, args.Actor);
 }
🤖 Prompt for AI Agents
In @Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs around
lines 52 - 70, OnSetTarget currently ignores the boolean result of
_targetSystem.SetTarget; capture its return value, and if it is false log a
warning including animUid and waypoint/args.Clear (and actor if available) so
failures are visible, and only call
_pathfindingSystem.InitializePathRetryIfNeeded and/or proceed with further
actions (like UpdateUi) when SetTarget returned true (or at least document why
UI should still update on failure).

Comment on lines +72 to +86
private void OnSetObserving(Entity<AnimatronicControllerComponent> ent, ref SetAnimatronicObservingEvent args)
{
if (args.Actor is not { Valid: true } player)
return;

var animUid = GetEntity(args.Animatronic);
if (!Exists(animUid) || !HasComp<AnimatronicComponent>(animUid))
return;

if (!TryComp<ActorComponent>(player, out var actor))
return;

var ui = new AdminCameraEui(animUid);
_eui.OpenEui(ui, actor.PlayerSession);
}
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Отсутствует проверка авторизации для AdminCameraEui.

Проблема из предыдущего review все еще актуальна: AdminCameraEui открывается без проверки административных прав пользователя. Любой игрок с доступом к контроллеру аниматроников может открыть админ-камеру.

Необходимо добавить зависимость IAdminManager и проверить права перед открытием EUI:

[Dependency] private readonly IAdminManager _admin = default!;

И в методе:

// Проверка прав администратора
if (_admin.GetAdminData(actor.PlayerSession) == null)
    return;
🤖 Prompt for AI Agents
In @Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs around
lines 72 - 86, The OnSetObserving handler opens AdminCameraEui without checking
administrative rights; add an IAdminManager dependency (e.g., [Dependency]
private readonly IAdminManager _admin = default!) to the system and, inside
OnSetObserving before constructing/opening the UI (before new
AdminCameraEui(...) and _eui.OpenEui(...)), call
_admin.GetAdminData(actor.PlayerSession) and return if it is null to prevent
non-admins from opening the admin camera UI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В прототипе управления есть запрет на открытие не админу этого юи

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the animatronic_controller prototype to verify adminOnly setting
cat Resources/Prototypes/Imperial/XxRaay/animatronic_controller.yml

Length of output: 678


@XxRaay, вы абсолютно правы! Я подтвердил, что в прототипе animatronic_controller.yml действительно установлен флаг adminOnly: true в компоненте ActivatableUI:

- type: ActivatableUI
  key: enum.AnimatronicControllerUiKey.Key
  singleUser: true
  inHandsOnly: true
  adminOnly: true

Это означает, что система ActivatableUI на уровне движка не позволит неадминистраторам открыть данный UI, соответственно они не смогут вызвать события OnSetObserving и другие обработчики. Авторизация корректно обеспечивается на уровне прототипа, дополнительная проверка в коде не требуется. Приношу извинения за неточность в анализе!


🧠 Learnings used
Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил неточность в анализе using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs - Content.Shared.Item действительно используется (ItemComponent), в отличие от Robust.Shared.Map и Robust.Server.GameObjects которые не используются.

Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 437
File: Content.Server/Imperial/Ninja/NinjaHeadset/NinjaHeadsetSystem.cs:71-73
Timestamp: 2025-09-10T06:08:33.954Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv указал, что в NinjaHeadsetSystem удаление проверки !headsetUid.HasValue после TryGetTargetHeadset вызовет ошибку, несмотря на то что метод возвращает true только когда headsetUid устанавливается в валидное значение. Это говорит о наличии крайних случаев или особенностей InventorySystem, требующих обе проверки.

Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 373
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:113-119
Timestamp: 2025-08-06T14:13:47.824Z
Learning: Пользователь CrookLv в проекте imperial-space/SS14-public подтвердил, что металлоискатель в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs обрабатывает разрешения контрабанды корректно в игре, несмотря на кажущуюся проблему с передачей параметров в метод IsContrabandAllowed.

Learnt from: krevetkqqq
Repo: imperial-space/SS14-public PR: 442
File: Content.Server/Imperial/Seriozha/SCP/Systems/SCP035Systems.cs:117-120
Timestamp: 2025-09-13T10:07:03.031Z
Learning: В проекте imperial-space/SS14-public пользователь krevetkqqq указал, что в SCP035System метод TryUnequip должен использовать OR логику (comp.In != null || !comp.TryinUneq) для отмены снятия, а не AND логику. Это означает, что есть два отдельных условия для блокировки снятия маски, не только когда TryinUneq == false.

Learnt from: XxRaay
Repo: imperial-space/SS14-public PR: 374
File: Content.Server/Imperial/XxRaay/FlagSystem/FlagCaptureSystem.cs:222-242
Timestamp: 2025-08-15T08:14:18.983Z
Learning: Пользователь XxRaay в проекте imperial-space/SS14-public подтвердил корректность работы системы захвата флагов в FlagCaptureSystem.cs, несмотря на кажущиеся несоответствия в названиях фракций между прототипами и кодом. Система предотвращает захват игроком своего же флага.

Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:132-145
Timestamp: 2025-08-02T17:48:55.569Z
Learning: Пользователь CrookLv в проекте imperial-space/SS14-public объяснил, что в системе MetalDetectorSystem не следует реагировать на все предметы с компонентами MeleeWeaponComponent или RangedWeaponComponent, поскольку это приведет к срабатыванию на безобидные предметы (игрушки, баллоны). Система должна полагаться на ContrabandComponent для определения действительно опасных предметов.

Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 362
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:1-28
Timestamp: 2025-08-04T20:34:48.192Z
Learning: В проекте imperial-space/SS14-public пользователь CrookLv исправил анализ using директив в файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs: Content.Shared.Item используется (ItemComponent на строке 70), Robust.Shared.Map используется (IMapManager на строке 44), только Robust.Server.GameObjects действительно не используется и должна быть удалена.

Learnt from: CrookLv
Repo: imperial-space/SS14-public PR: 376
File: Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs:189-197
Timestamp: 2025-08-10T16:44:31.921Z
Learning: В файле Content.Server/Imperial/Crook/Systems/MetalDetectorSystem.cs в методе IsContrabandItem параметр detector необходимо сохранять, даже если он не используется напрямую в теле метода, так как он передаётся в вызовы вложенных методов IsIgnoredByDetector и IsContrabandAllowed. Удаление этого параметра вызывает ошибки компиляции.

Learnt from: XxRaay
Repo: imperial-space/SS14-public PR: 317
File: Content.Server/Imperial/Power/EntitySystems/Events/SupermatterLightningEvent.cs:9-12
Timestamp: 2025-07-31T09:43:48.369Z
Learning: Пользователь XxRaay в проекте imperial-space/SS14-public предпочитает оставлять комментарии к коду на русском языке и не считает необходимым переводить их на английский.

Learnt from: onionsenpai-git
Repo: imperial-space/SS14-public PR: 394
File: Resources/Textures/Imperial/Other/ElysiumPrime/Misc/signs.rsi/meta.json:0-0
Timestamp: 2025-08-22T21:36:29.320Z
Learning: В проекте imperial-space/SS14-public движок корректно работает с горизонтальной упаковкой кадров в RSI спрайтах, даже если ширина PNG превышает size.x в meta.json файле. Пользователь onionsenpai-git подтвердил, что спрайты с размерами 64x32 при size.x=32 в meta.json работают без проблем.

Learnt from: Stevensegege
Repo: imperial-space/SS14-public PR: 354
File: Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml:114-117
Timestamp: 2025-07-27T16:35:42.639Z
Learning: Пользователь Stevensegege в проекте imperial-space/SS14-public подтвердил, что дублирование пути спрайта в компонентах Sprite и Clothing для entity ImperialSCPMask в файле Resources/Prototypes/Imperial/Seriozha/SCP/SCP.yml является преднамеренным дизайнерским решением.

Comment on lines +48 to +52
if (!_prototype.TryIndex<DamageGroupPrototype>("Brute", out var bruteGroup))
{
Log.Error($"AnimatronicDamageSystem: Failed to find Brute damage group prototype");
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Рассмотрите вынесение типа урона в конфигурацию компонента.

Тип урона "Brute" жестко закодирован в строке 48. Это ограничивает гибкость системы, если в будущем потребуются аниматроники с другими типами урона (например, Burn или Toxin).

Рекомендуется добавить поле DamageType или DamageGroupId в AnimatronicDamageComponent для настройки типа урона через прототипы.

♻️ Предлагаемое улучшение

В AnimatronicDamageComponent добавьте:

[DataField("damageGroup")]
public string DamageGroup = "Brute";

Затем используйте:

-if (!_prototype.TryIndex<DamageGroupPrototype>("Brute", out var bruteGroup))
+if (!_prototype.TryIndex<DamageGroupPrototype>(damageComp.DamageGroup, out var damageGroup))
 {
-	Log.Error($"AnimatronicDamageSystem: Failed to find Brute damage group prototype");
+	Log.Error($"AnimatronicDamageSystem: Failed to find {damageComp.DamageGroup} damage group prototype");
 	return;
 }

-var damage = new DamageSpecifier(bruteGroup, FixedPoint2.New(damageComp.ContactDamage));
+var damage = new DamageSpecifier(damageGroup, FixedPoint2.New(damageComp.ContactDamage));

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs around
lines 48 - 52, The code hardcodes the "Brute" damage group; add a configurable
field to AnimatronicDamageComponent (e.g., public string DamageGroup = "Brute";
annotated with [DataField("damageGroup")]) and change the lookup in
AnimatronicDamageSystem from _prototype.TryIndex<DamageGroupPrototype>("Brute",
out var bruteGroup) to use the component value:
_prototype.TryIndex<DamageGroupPrototype>(component.DamageGroup, out var
bruteGroup), making sure to null-check component and fall back to the default if
needed.

Comment on lines +28 to +50
if (waypoint == null)
{
ClearTarget(animatronic);
return true;
}

if (!Exists(waypoint.Value) || !HasComp<AnimatronicWaypointComponent>(waypoint.Value))
return false;

anim.TargetWaypoint = waypoint.Value;
Dirty(animatronic, anim);

EnsureComp<InputMoverComponent>(animatronic);
EnsureComp<ActiveNPCComponent>(animatronic);

if (TryComp<TransformComponent>(waypoint.Value, out var targetXform))
{
_steering.Register(animatronic, targetXform.Coordinates);
return true;
}

return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Потенциальная проблема с консистентностью состояния при неудачной регистрации steering.

В строках 40-41 добавляются компоненты InputMoverComponent и ActiveNPCComponent независимо от того, успешно ли пройдет регистрация в steering на строке 45. Если TryComp<TransformComponent> вернет false или регистрация не удастся, метод вернет false, но компоненты останутся добавленными, что может привести к некорректному состоянию.

Рекомендуется проверить возможность регистрации перед добавлением компонентов или удалить компоненты в случае неудачи.

♻️ Предлагаемое исправление
 anim.TargetWaypoint = waypoint.Value;
 Dirty(animatronic, anim);

+if (!TryComp<TransformComponent>(waypoint.Value, out var targetXform))
+{
+	anim.TargetWaypoint = null;
+	Dirty(animatronic, anim);
+	return false;
+}
+
 EnsureComp<InputMoverComponent>(animatronic);
 EnsureComp<ActiveNPCComponent>(animatronic);

-if (TryComp<TransformComponent>(waypoint.Value, out var targetXform))
-{
-	_steering.Register(animatronic, targetXform.Coordinates);
-	return true;
-}
-
-return false;
+_steering.Register(animatronic, targetXform.Coordinates);
+return true;
🤖 Prompt for AI Agents
In @Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs around
lines 28 - 50, The method sets anim.TargetWaypoint, calls Dirty(animatronic,
anim), and EnsureComp<InputMoverComponent>/EnsureComp<ActiveNPCComponent> before
attempting to get the waypoint Transform and register with _steering, so if
TryComp<TransformComponent> fails (or registration fails) the mover/active
components remain incorrectly added; modify the logic in AnimatronicTargetSystem
(the block that uses waypoint, EnsureComp<...>, TryComp<TransformComponent>, and
_steering.Register) to first verify the waypoint Transform and perform the
_steering.Register call (or check Register's success) and only then call
EnsureComp<InputMoverComponent> and EnsureComp<ActiveNPCComponent>, or
alternatively roll back/remove those components (via RemComp or ClearTarget) if
registration fails, ensuring state is consistent when the method returns false.

Comment on lines +52 to +66
public void ClearTarget(EntityUid animatronic)
{
if (!TryComp<AnimatronicComponent>(animatronic, out var anim))
return;

anim.TargetWaypoint = null;
Dirty(animatronic, anim);
_steering.Unregister(animatronic);

if (TryComp<AnimatronicPathfindingComponent>(animatronic, out var pathfinding))
{
pathfinding.LastPathRetryTime = null;
pathfinding.LastWaypointUpdateTime = null;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Безопасность вызова Unregister без проверки текущего состояния.

На строке 59 вызывается _steering.Unregister(animatronic) без проверки, был ли аниматроник зарегистрирован в steering системе. Хотя NPCSteeringSystem.Unregister может безопасно обрабатывать незарегистрированные сущности, рекомендуется явно проверить anim.TargetWaypoint перед вызовом для ясности логики.

♻️ Предлагаемое улучшение
 public void ClearTarget(EntityUid animatronic)
 {
 	if (!TryComp<AnimatronicComponent>(animatronic, out var anim))
 		return;

+	if (anim.TargetWaypoint == null)
+		return;
+
 	anim.TargetWaypoint = null;
 	Dirty(animatronic, anim);
 	_steering.Unregister(animatronic);

 	if (TryComp<AnimatronicPathfindingComponent>(animatronic, out var pathfinding))
 	{
 		pathfinding.LastPathRetryTime = null;
 		pathfinding.LastWaypointUpdateTime = null;
 	}
 }
🤖 Prompt for AI Agents
In @Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs around
lines 52 - 66, ClearTarget currently calls _steering.Unregister(animatronic)
unconditionally; change it to only call Unregister when the animatronic actually
has a target (check anim.TargetWaypoint != null) to make the intent explicit and
avoid unregistering non-registered entities; locate the ClearTarget method and
wrap or gate the _steering.Unregister(animatronic) call with a conditional that
inspects the AnimatronicComponent.TargetWaypoint (or equivalent) before calling
Unregister, leaving the rest of the cleanup (clearing TargetWaypoint,
Dirty(animatronic, anim), and resetting AnimatronicPathfindingComponent timing
fields) intact.

Copy link
Contributor

@The-Fiafi The-Fiafi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Пожалуйста, настройте свой редактор или IDE

image

@XxRaay
Copy link
Contributor Author

XxRaay commented Jan 16, 2026

Пожалуйста, настройте свой редактор или IDE

image

Я не знаю как это сделать или исправить 🥹

Copy link
Contributor

@The-Fiafi The-Fiafi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

Исправьте форматирование. У вас в каждом файле какой то другой символ юникода

@The-Fiafi
Copy link
Contributor

Апстримните ветку

@XxRaay XxRaay requested a review from The-Fiafi February 12, 2026 14:52
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml`:
- Around line 4-5: Удалите неиспользуемые декларации пространств имён
xmlns:controls и xmlns:ac из XAML в файле AnimatronicControllerWindow.xaml:
найдите атрибуты
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" и
xmlns:ac="clr-namespace:Content.Client.Imperial.XxRaay.UI" в корневом элементе и
удалите их, оставив только используемые xmlns, чтобы убрать лишние объявления и
предупреждения.

In `@Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs`:
- Around line 87-91: The code currently only handles the valid case of
_entityManager.GetEntity(anim.Entity); add an else branch for when entity.Valid
== false to avoid leaving spriteView empty: clear any previous entity via
spriteView.SetEntity(null) or spriteView.ClearEntity, then set a visible
placeholder or error indicator (e.g., spriteView.ShowPlaceholder("Invalid
entity") or spriteView.SetErrorIcon) so the UI shows that the entity is invalid;
update the block around _entityManager.GetEntity, entity.Valid, and
spriteView.SetEntity accordingly.
- Around line 51-294: CreateAnimatronicCard contains duplicated hex color
literals (e.g. "#888888", "#4CAF50", "#FF4444", "#4A90E2") scattered through the
method; refactor by adding static readonly Color fields on the class (e.g.
AnimatronicControllerWindow.IdleColor, ActiveWaypointColor, ClearButtonColor,
ObservingButtonColor, HoverColor) and replace all literal Color.FromHex(...)
usages (including where you assign originalColor, clearButtonOriginalColor,
observingButtonOriginalColor, and entries in _buttonOriginalColors) with those
constants so colors are centralized and easily changed.
- Around line 25-26: Поле _animCards хранит данные, но нигде не читается —
удалите его и связанные операции заполнения: уберите объявление
Dictionary<NetEntity, PanelContainer> _animCards и удалите код в методе
UpdateState, который записывает в _animCards (поиск по имени _animCards и месту
заполнения на строке 47); если планируется использование вместо удаления —
замените запись/заполнение на реальное чтение/использование там, где требуется,
иначе просто удалите поле и соответствующий блок в UpdateState, чтобы убрать
мёртвый код.

Comment on lines +4 to +5
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:ac="clr-namespace:Content.Client.Imperial.XxRaay.UI"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Неиспользуемые пространства имён controls и ac.

Оба xmlns-объявления (xmlns:controls и xmlns:ac) не используются в XAML. Их можно удалить.

♻️ Предлагаемое исправление
 <i:BaseImperialWindow
     xmlns="https://spacestation14.io"
     xmlns:i="clr-namespace:Content.Client.Imperial.UI.Windows.BaseImperialWindow"
-    xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
-    xmlns:ac="clr-namespace:Content.Client.Imperial.XxRaay.UI"
     HeaderText="{Loc animatronic-controller-window-title}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:ac="clr-namespace:Content.Client.Imperial.XxRaay.UI"
<i:BaseImperialWindow
xmlns="https://spacestation14.io"
xmlns:i="clr-namespace:Content.Client.Imperial.UI.Windows.BaseImperialWindow"
HeaderText="{Loc animatronic-controller-window-title}"
🤖 Prompt for AI Agents
In `@Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml` around
lines 4 - 5, Удалите неиспользуемые декларации пространств имён xmlns:controls и
xmlns:ac из XAML в файле AnimatronicControllerWindow.xaml: найдите атрибуты
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" и
xmlns:ac="clr-namespace:Content.Client.Imperial.XxRaay.UI" в корневом элементе и
удалите их, оставив только используемые xmlns, чтобы убрать лишние объявления и
предупреждения.

Comment on lines +51 to +294
private PanelContainer CreateAnimatronicCard(AnimDto anim, List<WaypointDto> waypoints)
{
var card = new PanelContainer
{
StyleClasses = { "AngleRectPass" },
HorizontalExpand = true,
Margin = new Thickness(0, 0, 0, 5)
};

var cardContent = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
Margin = new Thickness(10, 10, 10, 10),
SeparationOverride = 0,
HorizontalExpand = true
};

var spritePanel = new PanelContainer
{
PanelOverride = new StyleBoxFlat
{
BackgroundColor = Color.FromHex("#2A2A2A")
},
VerticalExpand = true
};

var spriteView = new SpriteView
{
OverrideDirection = Direction.South,
Scale = new Vector2(5f, 5f),
SetSize = new Vector2(96, 96),
Margin = new Thickness(5, 5, 5, 5),
VerticalExpand = true,
VerticalAlignment = VAlignment.Center
};

var entity = _entityManager.GetEntity(anim.Entity);
if (entity.Valid)
{
spriteView.SetEntity(entity);
}

spritePanel.AddChild(spriteView);

var nameStatusPanel = new PanelContainer
{
PanelOverride = new StyleBoxFlat
{
BackgroundColor = Color.FromHex("#333333")
},
HorizontalExpand = true,
VerticalExpand = true
};

var nameStatusContent = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
Margin = new Thickness(5, 5, 5, 5),
SeparationOverride = 10,
HorizontalExpand = true
};

var nameStatusContainer = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Vertical,
VerticalExpand = true,
VerticalAlignment = VAlignment.Center
};

var nameLabel = new Label
{
Text = anim.DisplayName,
StyleClasses = { "LabelSubTextPassExtraBoldServerName" },
ModulateSelfOverride = Color.White
};

var statusContainer = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
SeparationOverride = 3
};

if (anim.CurrentWaypointId != null)
{
var dotsLabel = new Label
{
Text = Loc.GetString("animatronic-controller-waypoint-separator"),
StyleClasses = { "LabelSubTextPassMediumBuy" },
ModulateSelfOverride = Color.FromHex("#FFD700"),
VerticalAlignment = VAlignment.Center,
Margin = new Thickness(0, 0, 3, 0)
};

var waypointLabel = new Label
{
Text = anim.CurrentWaypointId,
StyleClasses = { "LabelSubTextPassMediumBuy" },
ModulateSelfOverride = Color.FromHex("#FFD700"),
VerticalAlignment = VAlignment.Center
};

statusContainer.AddChild(dotsLabel);
statusContainer.AddChild(waypointLabel);
}
else
{
var statusLabel = new Label
{
Text = Loc.GetString("animatronic-controller-status-idle"),
StyleClasses = { "LabelSubTextPassMediumBuy" },
ModulateSelfOverride = Color.FromHex("#888888")
};
statusContainer.AddChild(statusLabel);
}

nameStatusContainer.AddChild(nameLabel);
nameStatusContainer.AddChild(statusContainer);

var waypointButtonsContent = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
SeparationOverride = 5,
HorizontalExpand = true
};

var waypointGrid = new GridContainer
{
Columns = 2,
HorizontalExpand = true
};

foreach (var wp in waypoints)
{
var isActive = anim.CurrentWaypointId == wp.WaypointId;
var wpButton = new Button
{
Text = wp.WaypointId,
HorizontalExpand = true
};

var originalColor = isActive ? Color.FromHex("#4CAF50") : Color.FromHex("#888888");
_buttonOriginalColors[wp.Entity] = originalColor;
wpButton.ModulateSelfOverride = originalColor;

wpButton.StyleClasses.Add("ButtonOpenBoth");

var animEntity = anim.Entity;
var wpEntity = wp.Entity;

wpButton.OnPressed += _ =>
{
OnAnimatronicWaypointSelected?.Invoke(animEntity, wpEntity);
};

wpButton.OnMouseEntered += _ =>
{
if (!isActive)
wpButton.ModulateSelfOverride = Color.FromHex("#AAAAAA");
};

wpButton.OnMouseExited += _ =>
{
if (!isActive && _buttonOriginalColors.TryGetValue(wpEntity, out var original))
wpButton.ModulateSelfOverride = original;
};

waypointGrid.AddChild(wpButton);
}

var buttonsContainer = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Vertical,
SeparationOverride = 5,
VerticalExpand = true
};

var clearButton = new Button
{
Text = Loc.GetString("animatronic-controller-button-clear"),
StyleClasses = { "ButtonOpenBoth" },
ModulateSelfOverride = Color.FromHex("#FF4444"),
VerticalExpand = true,
HorizontalExpand = true
};

var clearButtonOriginalColor = Color.FromHex("#FF4444");
var animEntityForClear = anim.Entity;
clearButton.OnPressed += _ =>
{
OnAnimatronicClearTarget?.Invoke(animEntityForClear);
};

clearButton.OnMouseEntered += _ =>
{
clearButton.ModulateSelfOverride = Color.FromHex("#FF6666");
};

clearButton.OnMouseExited += _ =>
{
clearButton.ModulateSelfOverride = clearButtonOriginalColor;
};

var observingButton = new Button
{
Text = Loc.GetString("animatronic-controller-button-observing"),
StyleClasses = { "ButtonOpenBoth" },
ModulateSelfOverride = Color.FromHex("#4A90E2"),
VerticalExpand = true,
HorizontalExpand = true
};

var observingButtonOriginalColor = Color.FromHex("#4A90E2");
var animEntityForObserving = anim.Entity;
observingButton.OnPressed += _ =>
{
OnAnimatronicObserving?.Invoke(animEntityForObserving);
};

observingButton.OnMouseEntered += _ =>
{
observingButton.ModulateSelfOverride = Color.FromHex("#6BA3E8");
};

observingButton.OnMouseExited += _ =>
{
observingButton.ModulateSelfOverride = observingButtonOriginalColor;
};

buttonsContainer.AddChild(clearButton);
buttonsContainer.AddChild(observingButton);

waypointButtonsContent.AddChild(waypointGrid);
waypointButtonsContent.AddChild(buttonsContainer);

nameStatusContent.AddChild(nameStatusContainer);
nameStatusContent.AddChild(waypointButtonsContent);
nameStatusPanel.AddChild(nameStatusContent);

cardContent.AddChild(spritePanel);
cardContent.AddChild(nameStatusPanel);
card.AddChild(cardContent);

return card;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Дублирование hex-констант цветов.

Одни и те же цветовые коды ("#888888", "#4CAF50", "#FF4444", "#4A90E2" и др.) разбросаны по методу. Рекомендуется вынести их в static readonly Color поля класса для единообразия и простоты изменения.

♻️ Пример
+	private static readonly Color ColorInactive = Color.FromHex("#888888");
+	private static readonly Color ColorActive = Color.FromHex("#4CAF50");
+	private static readonly Color ColorClear = Color.FromHex("#FF4444");
+	private static readonly Color ColorClearHover = Color.FromHex("#FF6666");
+	private static readonly Color ColorObserving = Color.FromHex("#4A90E2");
+	private static readonly Color ColorObservingHover = Color.FromHex("#6BA3E8");
+	private static readonly Color ColorHover = Color.FromHex("#AAAAAA");
+	private static readonly Color ColorGold = Color.FromHex("#FFD700");
🤖 Prompt for AI Agents
In `@Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs` around
lines 51 - 294, CreateAnimatronicCard contains duplicated hex color literals
(e.g. "#888888", "#4CAF50", "#FF4444", "#4A90E2") scattered through the method;
refactor by adding static readonly Color fields on the class (e.g.
AnimatronicControllerWindow.IdleColor, ActiveWaypointColor, ClearButtonColor,
ObservingButtonColor, HoverColor) and replace all literal Color.FromHex(...)
usages (including where you assign originalColor, clearButtonOriginalColor,
observingButtonOriginalColor, and entries in _buttonOriginalColors) with those
constants so colors are centralized and easily changed.

Comment on lines +87 to +91
var entity = _entityManager.GetEntity(anim.Entity);
if (entity.Valid)
{
spriteView.SetEntity(entity);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Нет обработки случая невалидной entity.

Если entity.Valid == false, spriteView останется пустым без визуальной индикации. Стоит рассмотреть отображение placeholder-текста или иконки ошибки для отладки.

🤖 Prompt for AI Agents
In `@Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs` around
lines 87 - 91, The code currently only handles the valid case of
_entityManager.GetEntity(anim.Entity); add an else branch for when entity.Valid
== false to avoid leaving spriteView empty: clear any previous entity via
spriteView.SetEntity(null) or spriteView.ClearEntity, then set a visible
placeholder or error indicator (e.g., spriteView.ShowPlaceholder("Invalid
entity") or spriteView.SetErrorIcon) so the UI shows that the entity is invalid;
update the block around _entityManager.GetEntity, entity.Valid, and
spriteView.SetEntity accordingly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (5)
Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs (1)

21-24: 🧹 Nitpick | 🔵 Trivial

Пустой метод Initialize можно удалить.

Метод содержит только вызов base.Initialize(). В SS14 это необязательно, если нет дополнительной логики инициализации.

🔎 Предлагаемое исправление
-public override void Initialize()
-{
-	base.Initialize();
-}
-
 public override void Update(float frameTime)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs`
around lines 21 - 24, Remove the redundant empty override of Initialize in the
AnimatronicPathfindingSystem class: delete the Initialize method that only calls
base.Initialize() so the class inherits the base implementation directly (remove
the method named Initialize in AnimatronicPathfindingSystem).
Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs (2)

81-85: 🧹 Nitpick | 🔵 Trivial

Нет визуальной индикации для невалидных entity.

Если entity.Valid == false, spriteView останется пустым без визуальной индикации ошибки. Рассмотрите отображение placeholder-текста или иконки для отладки.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs` around
lines 81 - 85, При обработке результата _entityManager.GetEntity(anim.Entity)
добавьте визуальную индикацию для случая entity.Valid == false: вместо
оставления spriteView пустым, вызвать методы представления для отображения
плейсхолдера/иконки/текста ошибки (например использовать
spriteView.ShowPlaceholder/SetPlaceholder или spriteView.Clear() затем
spriteView.SetEmptyState) чтобы явно сообщить о невалидной сущности; внесите
изменения в блок, где сейчас вызывается spriteView.SetEntity(entity), чтобы в
ветке else вызывать выбранный метод плейсхолдера и при необходимости логировать
anim.Entity или короткое сообщение об ошибке для отладки.

45-288: 🧹 Nitpick | 🔵 Trivial

Рассмотрите вынесение hex-констант цветов в статические поля.

Цветовые коды ("#888888", "#4CAF50", "#FF4444", "#4A90E2" и др.) дублируются в методе. Вынесение в static readonly Color поля улучшит поддерживаемость.

♻️ Пример
+private static readonly Color ColorInactive = Color.FromHex("#888888");
+private static readonly Color ColorActive = Color.FromHex("#4CAF50");
+private static readonly Color ColorClear = Color.FromHex("#FF4444");
+private static readonly Color ColorObserving = Color.FromHex("#4A90E2");
+private static readonly Color ColorHover = Color.FromHex("#AAAAAA");
+private static readonly Color ColorGold = Color.FromHex("#FFD700");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs` around
lines 45 - 288, The method CreateAnimatronicCard contains repeated inline
Color.FromHex(...) literals (e.g. "#888888", "#4CAF50", "#FF4444", "#4A90E2",
"#FFD700", "#AAAAAA") — extract these hex values into descriptive static
readonly Color fields (e.g. IdleColor, ActiveWaypointColor, ClearButtonColor,
ObservingButtonColor, WaypointHighlightColor, HoverGrayColor) on the class and
replace all direct Color.FromHex calls and local
originalColor/clearButtonOriginalColor/observingButtonOriginalColor assignments
with those shared fields; ensure _buttonOriginalColors stores the static color
references and that all event handlers (OnMouseEntered/OnMouseExited/OnPressed)
use the new static fields so colors are not duplicated.
Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs (1)

36-48: ⚠️ Potential issue | 🟡 Minor

Потенциальная проблема консистентности состояния.

Компоненты InputMoverComponent и ActiveNPCComponent добавляются (строки 39-40) до проверки возможности регистрации в steering (строка 42). Если TryComp<TransformComponent> вернёт false, метод вернёт false, но компоненты останутся добавленными.

♻️ Предлагаемое исправление
 anim.TargetWaypoint = waypoint.Value;
 Dirty(animatronic, anim);

+if (!TryComp<TransformComponent>(waypoint.Value, out var targetXform))
+{
+	anim.TargetWaypoint = null;
+	Dirty(animatronic, anim);
+	return false;
+}
+
 EnsureComp<InputMoverComponent>(animatronic);
 EnsureComp<ActiveNPCComponent>(animatronic);

-if (TryComp<TransformComponent>(waypoint.Value, out var targetXform))
-{
-	_steering.Register(animatronic, targetXform.Coordinates);
-	return true;
-}
-
-return false;
+_steering.Register(animatronic, targetXform.Coordinates);
+return true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs` around
lines 36 - 48, Компоненты добавляются до проверки наличия Transform, что
оставляет систему в неконсистентном состоянии при неудаче; change the flow in
SetTarget (the block using anim.TargetWaypoint, Dirty(animatronic, anim),
EnsureComp<InputMoverComponent>, EnsureComp<ActiveNPCComponent>,
TryComp<TransformComponent>, and _steering.Register) so that you only call
EnsureComp<InputMoverComponent> and EnsureComp<ActiveNPCComponent> after
TryComp<TransformComponent> returns true and after _steering.Register succeeds
(or else revert/undo the changes), or alternatively perform the
TryComp/registration first and only then set anim.TargetWaypoint and call Dirty;
pick one approach and adjust the order to guarantee components are not left
added when _steering.Register fails.
Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs (1)

62-66: ⚠️ Potential issue | 🟡 Minor

Потенциальная утечка памяти при удалении сущностей.

Если сущность удаляется без вызова EndCollideEvent (например, при телепортации или удалении), запись в LastContactDamage останется навсегда. Рекомендуется подписаться на EntityTerminatingEvent для очистки словаря.

🔎 Предлагаемое исправление
 public override void Initialize()
 {
 	base.Initialize();
 	SubscribeLocalEvent<AnimatronicDamageComponent, StartCollideEvent>(OnAnimatronicCollide);
 	SubscribeLocalEvent<AnimatronicDamageComponent, EndCollideEvent>(OnAnimatronicCollideEnd);
+	SubscribeLocalEvent<AnimatronicDamageComponent, EntityTerminatingEvent>(OnAnimatronicTerminating);
 }

+private void OnAnimatronicTerminating(Entity<AnimatronicDamageComponent> ent, ref EntityTerminatingEvent args)
+{
+	ent.Comp.LastContactDamage.Clear();
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs` around
lines 62 - 66, The OnAnimatronicCollideEnd handler currently removes OtherEntity
from a single AnimatronicDamageComponent.LastContactDamage but won’t catch cases
where the collided entity is deleted without EndCollideEvent; subscribe to
EntityTerminatingEvent and implement a handler (e.g. OnEntityTerminating or
OnAnimatronicEntityTerminating) that, when an entity is terminating, iterates
relevant AnimatronicDamageComponent instances and calls
LastContactDamage.Remove(terminatingEntityUid) (and if the terminating entity is
the component owner, clear LastContactDamage altogether) so stale keys are
removed and memory isn’t leaked.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs`:
- Around line 81-85: При обработке результата
_entityManager.GetEntity(anim.Entity) добавьте визуальную индикацию для случая
entity.Valid == false: вместо оставления spriteView пустым, вызвать методы
представления для отображения плейсхолдера/иконки/текста ошибки (например
использовать spriteView.ShowPlaceholder/SetPlaceholder или spriteView.Clear()
затем spriteView.SetEmptyState) чтобы явно сообщить о невалидной сущности;
внесите изменения в блок, где сейчас вызывается spriteView.SetEntity(entity),
чтобы в ветке else вызывать выбранный метод плейсхолдера и при необходимости
логировать anim.Entity или короткое сообщение об ошибке для отладки.
- Around line 45-288: The method CreateAnimatronicCard contains repeated inline
Color.FromHex(...) literals (e.g. "#888888", "#4CAF50", "#FF4444", "#4A90E2",
"#FFD700", "#AAAAAA") — extract these hex values into descriptive static
readonly Color fields (e.g. IdleColor, ActiveWaypointColor, ClearButtonColor,
ObservingButtonColor, WaypointHighlightColor, HoverGrayColor) on the class and
replace all direct Color.FromHex calls and local
originalColor/clearButtonOriginalColor/observingButtonOriginalColor assignments
with those shared fields; ensure _buttonOriginalColors stores the static color
references and that all event handlers (OnMouseEntered/OnMouseExited/OnPressed)
use the new static fields so colors are not duplicated.

In `@Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs`:
- Around line 62-66: The OnAnimatronicCollideEnd handler currently removes
OtherEntity from a single AnimatronicDamageComponent.LastContactDamage but won’t
catch cases where the collided entity is deleted without EndCollideEvent;
subscribe to EntityTerminatingEvent and implement a handler (e.g.
OnEntityTerminating or OnAnimatronicEntityTerminating) that, when an entity is
terminating, iterates relevant AnimatronicDamageComponent instances and calls
LastContactDamage.Remove(terminatingEntityUid) (and if the terminating entity is
the component owner, clear LastContactDamage altogether) so stale keys are
removed and memory isn’t leaked.

In `@Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs`:
- Around line 21-24: Remove the redundant empty override of Initialize in the
AnimatronicPathfindingSystem class: delete the Initialize method that only calls
base.Initialize() so the class inherits the base implementation directly (remove
the method named Initialize in AnimatronicPathfindingSystem).

In `@Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs`:
- Around line 36-48: Компоненты добавляются до проверки наличия Transform, что
оставляет систему в неконсистентном состоянии при неудаче; change the flow in
SetTarget (the block using anim.TargetWaypoint, Dirty(animatronic, anim),
EnsureComp<InputMoverComponent>, EnsureComp<ActiveNPCComponent>,
TryComp<TransformComponent>, and _steering.Register) so that you only call
EnsureComp<InputMoverComponent> and EnsureComp<ActiveNPCComponent> after
TryComp<TransformComponent> returns true and after _steering.Register succeeds
(or else revert/undo the changes), or alternatively perform the
TryComp/registration first and only then set anim.TargetWaypoint and call Dirty;
pick one approach and adjust the order to guarantee components are not left
added when _steering.Register fails.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e4ed3dd3-c4dd-4df3-a5c9-98a9352f5265

📥 Commits

Reviewing files that changed from the base of the PR and between 3cbd80f and 7802300.

📒 Files selected for processing (6)
  • Content.Client/Imperial/XxRaay/UI/AnimatronicControllerWindow.xaml.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicControllerSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicDamageSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicPathfindingSystem.cs
  • Content.Server/Imperial/XxRaay/Systems/AnimatronicTargetSystem.cs
  • Content.Shared/Imperial/XxRaay/Components/AnimatronicNet.cs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C# Изменения добавляют новый C# код Change Wiz Code Изменения вмешиваются в код визардов Change WIz Prototypes Изменения вмешиваются в код прототипов визардов Prototypes Изменения добавляет новые прототипы Resprite Изменения заменяют оригинальные текстуры визардов size/Medium Насколько сложно будет апстримить Sprite Изменения добавляют спрайты UI Изменения затрагивают UI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants