Skip to content

Децентрализация механик Scp939#981

Open
WardexOfficial wants to merge 28 commits into
space-sunrise:masterfrom
WardexOfficial:refactor-wrdx
Open

Децентрализация механик Scp939#981
WardexOfficial wants to merge 28 commits into
space-sunrise:masterfrom
WardexOfficial:refactor-wrdx

Conversation

@WardexOfficial

@WardexOfficial WardexOfficial commented Apr 26, 2026

Copy link
Copy Markdown
Collaborator

Краткое описание | Short description

Разбитие механик Scp939 на раздельные системы.

TODO

  • Создание отдельной системы видения сущностей, которые двигаются либо издают звук
  • Создание отдельной системы запоминания слов от окружающих сущностей и возможность их воспроизведения
  • Создание отдельной системы сна и регенерации
  • Создание отдельной системы/рефакторинг существующей выпуска газа вокруг

Summary by CodeRabbit

Обновления функциональности

  • Новые возможности

    • Добавлена система обнаружения по звуку для SCP-939
    • SCP-939 теперь запоминает и воспроизводит фразы персонажей
    • Введена механика исцеления во время гибернации
  • Переработка

    • Переработана система видимости SCP-939 для повышения универсальности
    • Переструктурированы системы действий и механики SCP-939

@coderabbitai

coderabbitai Bot commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@WardexOfficial has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 37 minutes and 56 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: dfe9c125-f076-42c0-a529-9baf57c2ed5a

📥 Commits

Reviewing files that changed from the base of the PR and between 3125dbe and dd1dd3f.

⛔ Files ignored due to path filters (3)
  • Resources/Textures/_Scp/Actions/scp-actions.rsi/mimic.png is excluded by !**/*.png
  • Resources/Textures/_Scp/Actions/scp-actions.rsi/sleep.png is excluded by !**/*.png
  • Resources/Textures/_Scp/Actions/scp-actions.rsi/smaug.png is excluded by !**/*.png
📒 Files selected for processing (42)
  • Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.Overlay.cs
  • Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs
  • Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityResetAlphaOverlay.cs
  • Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySetAlphaOverlay.cs
  • Content.Client/_Scp/Scp939/Scp939HudSystem.Visibility.cs
  • Content.Client/_Scp/Scp939/Scp939HudSystem.cs
  • Content.Client/_Scp/Scp939/Scp939Visualizer.cs
  • Content.Server/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepComponent.cs
  • Content.Server/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepSystem.cs
  • Content.Server/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySystem.cs
  • Content.Server/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseSystem.cs
  • Content.Server/_Scp/Research/Artifacts/Effects/_ScpSpecific/Scp939/Sleep/ArtifactScp939SleepComponent.cs
  • Content.Server/_Scp/Research/Artifacts/Effects/_ScpSpecific/Scp939/Sleep/ArtifactScp939SleepSystem.cs
  • Content.Server/_Scp/Scp939/Scp939System.Actions.cs
  • Content.Server/_Scp/Scp939/Scp939System.Visibility.cs
  • Content.Server/_Scp/Scp939/Scp939System.cs
  • Content.Shared/_Scp/Other/Events/ScpSystemsEvents.cs
  • Content.Shared/_Scp/Other/Events/ScpTriggerEvents.cs
  • Content.Shared/_Scp/Other/ScpHealOnSleep/SharedScpHealOnSleepData.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ActiveScpOnSoundVisibilityComponent.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ActiveScpPoorEyesightComponent.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityComponent.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityProtectionComponent.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityViewerComponent.cs
  • Content.Shared/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseComponent.cs
  • Content.Shared/_Scp/Scp939/ActiveScp939VisibilityComponent.cs
  • Content.Shared/_Scp/Scp939/Protection/Scp939ProtectionComponent.cs
  • Content.Shared/_Scp/Scp939/Scp939Component.cs
  • Content.Shared/_Scp/Scp939/Scp939VisabilityComponent.cs
  • Content.Shared/_Scp/Scp939/SharedScp939Data.cs
  • Content.Shared/_Scp/ScpMask/ScpMaskCheckerComponent.cs
  • Content.Shared/_Scp/ScpMask/ScpMaskSystem.Checker.cs
  • Content.Shared/_Scp/ScpMask/ScpMaskSystem.cs
  • Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionListenerComponent.cs
  • Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs
  • Resources/Locale/ru-RU/_prototypes/_scp/actions/scp-actions.ftl
  • Resources/Locale/ru-RU/_prototypes/_scp/actions/scp939.ftl
  • Resources/Prototypes/Entities/Mobs/base.yml
  • Resources/Prototypes/_Scp/Actions/scp939.yml
  • Resources/Prototypes/_Scp/Actions/scp_actions.yml
  • Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml
  • Resources/Textures/_Scp/Actions/scp-actions.rsi/meta.json

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

Walkthrough

Крупный рефакторинг, конвертирующий специфичные для SCP-939 системы видимости, сна и мимикрии в универсальные компоненты и системы. Удалены три основных SCP-939 сервер-клиентских системы; добавлены новые чистые компоненты (ScpOnSoundVisibility, ScpRememberPhrase, ScpHealOnSleep) с соответствующими системами для управления ими. Переработаны прототипы действий и конфигурация SCP-939 для использования новой архитектуры.

Changes

Миграция видимости и HUD с SCP-939 на универсальную систему ScpOnSoundVisibility

Layer / File(s) Summary
Определение компонентов
Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityComponent.cs, ScpOnSoundVisibilityViewerComponent.cs, ScpOnSoundVisibilityProtectionComponent.cs
Content.Shared/_Scp/Other/ScpOnSoundVisibility/ActiveScpOnSoundVisibilityComponent.cs
Новые компоненты для отслеживания видимости сущностей (ScpOnSoundVisibilityComponent), конфигурации наблюдателя (ScpOnSoundVisibilityViewerComponent) с состоянием плохого зрения и диапазоном активации, защиты от видимости и активного накопления видимости. Синхронизируются по сети через AutoNetworkedField.
Инициализация сервера
Content.Server/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySystem.cs
Система управления целями видимости: обновляет набор активных целей в периодическом интервале, синхронизирует компоненты видимости, обрабатывает эффект плохого зрения при вспышке и управляет их истечением.
Логика клиента и HUD
Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs
Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySetAlphaOverlay.cs, ScpOnSoundVisibilityResetAlphaOverlay.cs
Система HUD для управления видимостью целей через наложения (overlays): обрабатывает события движения, столкновения и действий для изменения VisibilityAcc, применяет модификаторы видимости при плохом зрении, вычисляет нормализованную видимость и управляет прозрачностью спрайтов. Переименованы классы Scp939HUD в ScpOnSoundVisibility.
Удаление старых SCP-939 систем
Content.Client/_Scp/Scp939/Scp939HudSystem.cs, Scp939HudSystem.Overlay.cs, Scp939Visualizer.cs
Content.Server/_Scp/Scp939/Scp939System.cs, Scp939System.Visibility.cs, Scp939System.Actions.cs
Удалены все SCP-939-специфичные системы видимости, HUD, визуализации и их действия. Логика мигрирована в новые универсальные системы.
Компонент видимости SCP-939
Content.Shared/_Scp/Scp939/Scp939Component.cs
Content.Shared/_Scp/Scp939/ActiveScp939VisibilityComponent.cs
Scp939Component очищен от полей конфигурации; ActiveScp939VisibilityComponent полностью удален в пользу ActiveScpOnSoundVisibilityComponent.
События и протоколы действий
Content.Shared/_Scp/Scp939/SharedScp939Data.cs
Удалены объявления событий действий SCP-939 (Gas, Sleep, Mimic); сохранены только визуальные перечисления.
Прототипы действий
Resources/Prototypes/_Scp/Actions/scp939.yml
Resources/Prototypes/_Scp/Actions/scp_actions.yml
Действия SCP-939 переведены на наследование базовых прототипов (RememberPhraseAction, ScpSleepAction, ScpSmokeAction) вместо встроенных определений компонентов.
Конфигурация SCP-939
Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml
Обновлена конфигурация SCP-939 для использования новых компонентов: ScpOnSoundVisibilityViewer, ScpHealOnSleep, ScpRememberPhrase, SmokeOnTrigger вместо старых специфичных систем.

Извлечение функциональности сна в универсальную систему ScpHealOnSleep

Layer / File(s) Summary
Определение компонента
Content.Server/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepComponent.cs
Content.Shared/_Scp/Other/ScpHealOnSleep/SharedScpHealOnSleepData.cs
Новый компонент ScpHealOnSleepComponent с конфигурацией сна, исцеления при гибернации, длительности и звуков. Новые перечисления для слоёв спрайтов и визуальных состояний.
Серверная система
Content.Server/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepSystem.cs
Система управления инициированием сна, применением исцеления во время гибернации, управлением действиями и обновлением визуального состояния через события SleepActionEvent и MobStateChangedEvent.
Артефакт интеграция
Content.Server/_Scp/Research/Artifacts/Effects/_ScpSpecific/Scp939/Sleep/ArtifactScp939SleepSystem.cs
ArtifactScp939SleepComponent.cs
Обновлены для использования новой ScpHealOnSleepSystem вместо Scp939System; тип данных MinSleepTime/MaxSleepTime изменён с float на TimeSpan.

Добавление универсальной функциональности запоминания фраз

Layer / File(s) Summary
Определение компонента
Content.Shared/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseComponent.cs
Новый компонент с конфигурацией действия, максимумом запомненных сообщений и структурой RememberedMessage (сообщение, имя говорящего, голос TTS).
Серверная система
Content.Server/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseSystem.cs
Система управления регистрацией действий, прослушиванием и запоминанием сообщений от соседних сущностей, мимикрией с выбором случайного сообщения и отправкой IC-сообщения.
События действий
Content.Shared/_Scp/Other/Events/ScpSystemsEvents.cs
Новые события ScpRememberPhraseActionEvent и ScpSleepActionEvent для замены специфичных SCP-939 событий.

Добавление универсальной системы триггеров и масок

Layer / File(s) Summary
Компоненты и события
Content.Shared/_Scp/Other/Events/ScpTriggerEvents.cs
Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionListenerComponent.cs
Новое событие ScpTriggerOnActionEvent с полем KeyOut для маршрутизации триггеров действий.
Система обработки триггеров
Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs
Система преобразования действий в триггеры через TriggerSystem.
Защита от триггеров
Content.Shared/_Scp/ScpMask/ScpMaskChekerComponent.cs
Content.Shared/_Scp/ScpMask/ScpMaskSystem.Checker.cs, ScpMaskSystem.cs
Новый компонент ScpMaskCheckerComponent и логика в ScpMaskSystem для блокировки триггеров при наличии активной маски.
Базовая интеграция
Resources/Prototypes/Entities/Mobs/base.yml
BaseMob теперь включает ScpOnSoundVisibility для универсального применения видимости.

Sequence Diagram

sequenceDiagram
    participant Entity as Целевая сущность
    participant Viewer as ScpOnSoundVisibilityViewer
    participant System as ScpOnSoundVisibilitySystem
    participant HudSys as ScpOnSoundVisibilityHudSystem
    participant Overlay as SetAlphaOverlay

    Entity->>System: В пределах VisibilityActivationRange
    System->>System: UpdateVisibilityTargets()
    System->>Entity: EnsureActiveVisibility()
    activate Entity
    Entity->>Entity: ActiveScpOnSoundVisibilityComponent создан
    Entity->>Entity: HideTime, MinValue, MaxValue синхронизированы
    deactivate Entity

    loop Каждый UPDATE
        HudSys->>Entity: Проверить событие OnMove/OnCollide
        alt Событие действия (столкновение, движение)
            Entity->>HudSys: VisibilityAcc сброшен в InitialVisibilityAcc
        else Нет события
            HudSys->>HudSys: Incrementally увеличить VisibilityAcc
        end

        HudSys->>HudSys: GetVisibility(ent) вычислить
        HudSys->>Viewer: Проверить PoorEyesight
        alt PoorEyesight активен
            HudSys->>HudSys: Применить модификатор видимости [MinValue, MaxValue]
        end

        Overlay->>HudSys: GetVisibility(ent) для целевой альфы
        Overlay->>Overlay: SetAlphaOverlay: обновить спрайт-альфу
    end

    Viewer->>System: AfterFlashedEvent
    System->>System: PoorEyesight = true, PoorEyesightTimeStart = now
    System->>System: ActiveScpPoorEyesightComponent создан

    loop Истечение
        System->>System: Проверить elapsed > PoorEyesightTime
        alt Истекло
            System->>System: PoorEyesight = false, удалить ActiveScpPoorEyesightComponent
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐰 Вот и пришла пора перемен,
Сути SCP отделены от стен—
Видимость, сон и слова на устах,
Теперь волшебство в компонентах и в фактах!
Системы танцуют в едином строю,
Универсальности дарю я судьбу!


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (4 errors, 1 warning)

Check name Status Explanation Resolution
Ss14 C# Rules ❌ Error Нарушены SS14 правила: отсутствуют локализационные ключи для новых прототипов, KeyOut может быть null, опечатка в имени файла, сетевой компонент без нужных атрибутов, лишний return. Добавить ent-* локализацию для действий; KeyOut сделать required=true; переименовать файл ScpMaskCheker->ScpMaskChecker; добавить [AutoGenerateComponentState] и [AutoNetworkedField]; удалить лишний return.
Ss14 Yaml/Ftl Rules ❌ Error Три новых конкретных прототипа действий (RememberPhraseAction, ScpSmokeAction, ScpSleepAction) с name/description добавлены без соответствующих FTL ent-* локализационных ключей. Добавить FTL ключи ent-RememberPhraseAction, ent-ScpSmokeAction, ent-ScpSleepAction в locale файлы, либо пометить прототипы как abstract: true.
Ss14 Prototype ↔ Ftl Parity ❌ Error Добавлены три новых player-facing действия с названиями и описаниями, но отсутствуют соответствующие FTL локализационные ключи (ent-RememberPhraseAction, ent-ScpSmokeAction, ent-ScpSleepAction). Создайте файл Resources/Locale/en-US/_prototypes/_scp/actions/scp_actions.ftl с локализацией для трёх новых действий, соответствующей их name и description в прототипах.
Ss14 Prediction Safety ❌ Error PR вводит prediction hazard: PopupEntity вызывается из predicted события без IsFirstTimePredicted гарда, вызывая многократное отображение попапа. Добавить IsFirstTimePredicted проверку в TryCreatePopup или заменить PopupEntity на PopupPredicted. Добавить [AutoGenerateComponentState] и [AutoNetworkedField] в ScpMaskCheckerComponent.
Docstring Coverage ⚠️ Warning Docstring coverage is 4.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Название PR ясно и конкретно описывает основное изменение — децентрализацию механик SCP-939, то есть разделение монолитной системы на отдельные компоненты.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Ss14 Bridge Sync ✅ Passed PR не содержит изменений в канонических правилах/навыках (.agent/rules/, .agent/skills/). Все 43 изменённых файла в игровом коде (Content.*/Resources/). Проверка не применима.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@WardexOfficial WardexOfficial changed the title Рефактор Scp939 и Scp173 Рефактор систем Scp939 и Scp173 Apr 26, 2026
@WardexOfficial WardexOfficial changed the title Рефактор систем Scp939 и Scp173 Децентрализация механик Scp939 и Scp173 Apr 26, 2026
@github-actions

github-actions Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

RSI Diff Bot; head commit dd1dd3f merging into 3125dbe
This PR makes changes to 1 or more RSIs. Here is a summary of all changes:
Edit: diff updated after dd1dd3f

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 16

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs`:
- Line 277: Текст TODO в классе ScpOnSoundVisibilityHudSystem (файл
ScpOnSoundVisibilityHudSystem.cs) нужно вынести в трекер задач и заменить в коде
краткой пометкой с идентификатором issue: создайте issue/bug/feature в вашей
системе (описать: "Переделать визуализацию как статус-эффект и добавить его в
панель статус-эффектов"), получите его номер/ссылку и замените TODO-комментарий
на комментарий вида "TODO: see ISSUE-1234" (или аналог с URL), чтобы задача была
отслеживаема; оставьте в issue детали UX-изменения и ожидаемое поведение для
методов и UI, чтобы потом реализовать изменения в ScpOnSoundVisibilityHudSystem.

In
`@Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.Overlay.cs`:
- Around line 23-26: При отключении локального игрока в методе OnPlayerDetached
нужно не только сбрасывать поле _viewerComponent, но и явно удалить все активные
оверлеи: вызовите RemoveOverlays() (или эквивалентный метод очистки) до того,
как присвоите _viewerComponent = null; это гарантирует, что визуальные элементы
удаляются и не остаются активными после детача.

In `@Content.Client/_Scp/Other/ScpSleep/ScpSleepVisualizer.cs`:
- Line 8: Класс в файле ScpSleepVisualizer.cs объявлен как Scp939Visualizer;
переименуйте класс Scp939Visualizer в ScpSleepVisualizer (класс:
Scp939Visualizer, базовый: VisualizerSystem<ScpSleepComponent>) и обновите все
ссылочные использования/именования в проекте, чтобы соответствовать новому имени
ScpSleepVisualizer.
- Around line 20-25: The UpdateSprite method currently declares optional
parameters spriteComponent and mobStateComponent but immediately overwrites them
with TryComp calls; either remove these optional parameters from the
UpdateSprite signature (so only uid and appearanceComponent remain) and keep the
TryComp lookups inside, or change the body to use the Resolve pattern to respect
callers' supplied components (use Resolve(uid, ref spriteComponent, ref
mobStateComponent) or the project's equivalent) before falling back to TryComp;
update references to SpriteComponent, MobStateComponent, TryComp, and the
_spriteSystem.LayerMapTryGet((uid, spriteComponent), ScpSleepLayers.Base, ...)
call accordingly to ensure you pass the resolved variables into LayerMapTryGet.

In
`@Content.Server/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySystem.cs`:
- Around line 74-80: OnMobStartup сейчас всегда добавляет
EnsureComp<ScpOnSoundVisibilityComponent> всем мобам (кроме тех с
ScpOnSoundVisibilityViewerComponent), что создаёт лишние компоненты на большом
количестве NPC; исправьте это, добавив предикат перед вызовом EnsureComp:
например, только если у сущности уже есть маркер интереса
(HasComp<ScpOnSoundVisibilityInterestComponent>(ent)), или если сущность
является игроком/активным юнитом (проверка по компоненту/флагу типа
PlayerComponent/ActiveAiComponent), либо перенесите конфигурацию в
Singleton/SharedResource и вообще не добавляйте компонент всем. Обновите функцию
OnMobStartup, заменив бесконтрольный
EnsureComp<ScpOnSoundVisibilityComponent>(ent) на условный вызов с описанными
проверками или уберите добавление и читайте конфиг из единого места.
- Around line 166-167: Remove the redundant call to
_visibilityCandidates.Clear() at the end of the method in
ScpOnSoundVisibilitySystem since _visibilityCandidates is already cleared inside
the processing loop (the earlier Clear). Locate the method in the
ScpOnSoundVisibilitySystem class where both _visibilityCandidates.Clear() and
_visibilityRemovalQueue.Clear() are called and delete only the trailing
_visibilityCandidates.Clear() call, leaving _visibilityRemovalQueue.Clear()
as-is.

In `@Content.Server/_Scp/Other/ScpReleaseGas/ScpReleaseGasSystem.cs`:
- Around line 28-34: В методе OnGasAction при обнаружении маски через
_scpMask.TryGetScpMask вы делаете ранний return после _scpMask.TryCreatePopup,
но не устанавливаете флаг обработки события; исправьте это, перед возвратом
установить args.Handled = true на объекте ScpReleaseGasActionEvent, чтобы
пометить событие как обработанное и предотвратить дальнейшую обработку другими
системами.
- Line 7: Namespace declaration is incorrect for this file; change the namespace
from Content.Server._Scp.Scp939 to match the folder hierarchy (e.g.,
Content.Server._Scp.Other.ScpReleaseGas) so the ScpReleaseGasSystem class and
any related types live in the correct namespace and follow project conventions.
- Around line 23-26: The component event handler OnInit in ScpReleaseGasSystem
is declared public but should be private by SS14 convention; change the method
signature from public void OnInit(Entity<ScpReleaseGasComponent> ent, ref
ComponentInit args) to private void OnInit(Entity<ScpReleaseGasComponent> ent,
ref ComponentInit args) (leave the body unchanged, still calling
_actionsSystem.AddAction(ent, ent.Comp.ActionProto)) so the handler remains
functional but uses the correct access level.
- Around line 19-21: В компоненте ScpReleaseGasComponent вы подписываете
действие в Initialize() через обработчик OnInit (ComponentInit) но не удаляете
его при уничтожении, что ведёт к orphaned actions; добавьте подписку на
ComponentShutdown в Initialize() и реализуйте обработчик (например OnShutdown)
который найдёт и удалит ранее зарегистрированное действие для
ScpReleaseGasComponent (тот же идентификатор/тип, что используете в
OnInit/OnGasAction) — убрать действие из ActionSystem/Owner или вызвать
соответствующий метод удаления, чтобы гарантировать очистку при
ComponentShutdown.

In `@Content.Server/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseSystem.cs`:
- Around line 84-88: The current removal picks a random key via
_random.Pick(rememberEnt.Comp.RememberedMessages.Keys) which iterates keys and
then Remove does another lookup; to optimize, change the component storage to
maintain a parallel List<TKey> (e.g., RememberedMessageKeys) alongside the
Dictionary RememberedMessages and use _random.Next(0,
RememberedMessageKeys.Count) to pick an index then get the key by index and
remove by key from the Dictionary and RemoveAt from the List; ensure all places
that add or remove entries (where RememberedMessages is modified) also update
RememberedMessageKeys so the two stay in sync and use the new index-based
removal in the block currently using _random.Pick.
- Line 70: The GetEntitiesInRange call uses a hardcoded radius (16f); add a
DataField to ScpRememberPhraseComponent: [DataField] public float ListenRange =
16f; then replace the literal 16f in the _entityLookup.GetEntitiesInRange(...)
invocation with the component's ListenRange (i.e., use rememberSet.ListenRange
or the ScpRememberPhraseComponent instance associated with ent) so the radius is
configurable via prototypes.

In `@Content.Server/_Scp/Other/ScpSleep/ScpSleepSystem.cs`:
- Around line 56-69: The method OnSleepChanged currently uses magic numbers 20
and 1 to set bloodstreamComponent.BloodRefreshAmount; add two DataField
properties to ScpSleepComponent (e.g., public float SleepingBloodRefreshAmount =
20f; public float DefaultBloodRefreshAmount = 1f;) and then update
OnSleepChanged to read those fields from the entity's ScpSleepComponent instance
instead of the hardcoded literals (use the component on the same entity to set
bloodstreamComponent.BloodRefreshAmount to SleepingBloodRefreshAmount when
args.FellAsleep is true and to DefaultBloodRefreshAmount otherwise, then call
Dirty as before).

In
`@Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityViewerComponent.cs`:
- Line 17: The inline comment on the public field PoorEyesightTime in
ScpOnSoundVisibilityViewerComponent.cs is in Russian ("// Секунды"); change it
to English by replacing it with "// Seconds" so it matches the project's English
comment standards and clearly documents the unit for PoorEyesightTime.

In `@Content.Shared/_Scp/Other/ScpReleaseGas/ScpReleaseGasComponent.cs`:
- Around line 9-10: Класс ScpReleaseGasComponent помечен атрибутом
[NetworkedComponent], но в нём нет полей с [AutoNetworkedField]; либо удалите
атрибут [NetworkedComponent] из объявления класса ScpReleaseGasComponent, либо
добавьте необходимые сетевые поля, пометив их [AutoNetworkedField] (и настроив
идентификаторы/версии), чтобы отражать реальную потребность в синхронизации.

In `@Content.Shared/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseComponent.cs`:
- Around line 8-22: The ScpRememberPhraseComponent is incorrectly marked with
[NetworkedComponent] even though its state (notably the RememberedMessages
dictionary) is server-only; remove the [NetworkedComponent] attribute from the
ScpRememberPhraseComponent declaration so the component is not
network-synchronized and remains server-side only, leaving other attributes
(e.g., [RegisterComponent]) and fields (ActionProto, MaxRememberedMessages,
RememberedMessages) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d3590131-6c0a-42a0-ba4b-e76554c419c3

📥 Commits

Reviewing files that changed from the base of the PR and between ad22943 and 902f1e5.

⛔ Files ignored due to path filters (3)
  • Resources/Textures/_Scp/Actions/scp-actions.rsi/mimic.png is excluded by !**/*.png
  • Resources/Textures/_Scp/Actions/scp-actions.rsi/sleep.png is excluded by !**/*.png
  • Resources/Textures/_Scp/Actions/scp-actions.rsi/smaug.png is excluded by !**/*.png
📒 Files selected for processing (35)
  • Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.Overlay.cs
  • Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs
  • Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityResetAlphaOverlay.cs
  • Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySetAlphaOverlay.cs
  • Content.Client/_Scp/Other/ScpSleep/ScpSleepVisualizer.cs
  • Content.Client/_Scp/Scp939/Scp939HudSystem.Visibility.cs
  • Content.Client/_Scp/Scp939/Scp939HudSystem.cs
  • Content.Client/_Scp/Scp939/Scp939Visualizer.cs
  • Content.Server/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySystem.cs
  • Content.Server/_Scp/Other/ScpReleaseGas/ScpReleaseGasSystem.cs
  • Content.Server/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseSystem.cs
  • Content.Server/_Scp/Other/ScpSleep/ScpSleepSystem.cs
  • Content.Server/_Scp/Research/Artifacts/Effects/_ScpSpecific/Scp939/Sleep/ArtifactScp939SleepSystem.cs
  • Content.Server/_Scp/Scp939/Scp939System.Actions.cs
  • Content.Server/_Scp/Scp939/Scp939System.Visibility.cs
  • Content.Server/_Scp/Scp939/Scp939System.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ActiveScpOnSoundVisibilityComponent.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityComponent.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityProtectionComponent.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityViewerComponent.cs
  • Content.Shared/_Scp/Other/ScpReleaseGas/ScpReleaseGasActionEvent.cs
  • Content.Shared/_Scp/Other/ScpReleaseGas/ScpReleaseGasComponent.cs
  • Content.Shared/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseActionEvent.cs
  • Content.Shared/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseComponent.cs
  • Content.Shared/_Scp/Other/ScpSleep/ScpSleepActionEvent.cs
  • Content.Shared/_Scp/Other/ScpSleep/ScpSleepComponent.cs
  • Content.Shared/_Scp/Other/ScpSleep/SharedScpSleepData.cs
  • Content.Shared/_Scp/Scp939/ActiveScp939VisibilityComponent.cs
  • Content.Shared/_Scp/Scp939/Protection/Scp939ProtectionComponent.cs
  • Content.Shared/_Scp/Scp939/Scp939Component.cs
  • Content.Shared/_Scp/Scp939/SharedScp939Data.cs
  • Resources/Prototypes/_Scp/Actions/scp939.yml
  • Resources/Prototypes/_Scp/Actions/scp_actions.yml
  • Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml
  • Resources/Textures/_Scp/Actions/scp-actions.rsi/meta.json
💤 Files with no reviewable changes (8)
  • Content.Shared/_Scp/Scp939/ActiveScp939VisibilityComponent.cs
  • Content.Client/_Scp/Scp939/Scp939Visualizer.cs
  • Content.Shared/_Scp/Scp939/SharedScp939Data.cs
  • Content.Server/_Scp/Scp939/Scp939System.Actions.cs
  • Content.Client/_Scp/Scp939/Scp939HudSystem.cs
  • Content.Server/_Scp/Scp939/Scp939System.cs
  • Content.Client/_Scp/Scp939/Scp939HudSystem.Visibility.cs
  • Content.Server/_Scp/Scp939/Scp939System.Visibility.cs

Comment thread Content.Client/_Scp/Other/ScpSleep/ScpSleepVisualizer.cs Outdated
Comment thread Content.Client/_Scp/Other/ScpSleep/ScpSleepVisualizer.cs Outdated
Comment thread Content.Server/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySystem.cs Outdated
Comment thread Content.Server/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseSystem.cs Outdated
Comment thread Content.Server/_Scp/Other/ScpSleep/ScpSleepSystem.cs Outdated
Comment thread Content.Shared/_Scp/Other/ScpReleaseGas/ScpReleaseGasComponent.cs Outdated
@ThereDrD0 ThereDrD0 marked this pull request as draft April 28, 2026 07:55
@ThereDrD0

Copy link
Copy Markdown
Collaborator

Пока не доделал пусть будет в драфте

@ThereDrD0

Copy link
Copy Markdown
Collaborator

Также выдели 173 в отдельный ПР для удобства ревью. Начни только с 939, потому что я уверен тут будет много замечаний и будет тяжело ориентироваться

@WardexOfficial WardexOfficial marked this pull request as ready for review April 28, 2026 08:50
@WardexOfficial

Copy link
Copy Markdown
Collaborator Author

В принципе готово для ревью

Comment thread Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs Outdated
Comment thread Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs Outdated
Comment thread Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs Outdated
Comment thread Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs Outdated
Comment thread Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs Outdated
Comment thread Content.Shared/_Scp/Other/ScpReleaseGas/ScpReleaseGasComponent.cs Outdated
Comment thread Content.Shared/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseComponent.cs Outdated
Comment thread Content.Shared/_Scp/Other/ScpSleep/ScpSleepActionEvent.cs Outdated
Comment thread Content.Shared/_Scp/Other/ScpSleep/ScpSleepComponent.cs Outdated
@WardexOfficial

Copy link
Copy Markdown
Collaborator Author

Нужно будет не забыть изменить ключи локализации, где они содержат в себе "939"

@WardexOfficial

Copy link
Copy Markdown
Collaborator Author

@ThereDrD0 готово к ревью

Comment thread Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs Outdated
Comment thread Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs Outdated
Comment thread Content.Server/_Scp/Other/ScpReleaseGas/ScpReleaseGasSystem.cs Outdated
Comment thread Content.Server/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepSystem.cs
Comment thread Content.Server/_Scp/Other/ScpSleep/ScpSleepSystem.cs Outdated
Comment thread Content.Shared/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseComponent.cs Outdated
Comment thread Content.Shared/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseComponent.cs Outdated
Comment thread Resources/Prototypes/Entities/Mobs/base.yml Outdated
Comment thread Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml Outdated
Comment thread Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml Outdated
@WardexOfficial WardexOfficial requested a review from ThereDrD0 May 2, 2026 17:03
@WardexOfficial

Copy link
Copy Markdown
Collaborator Author

Ммм, забей, я не тот компонент указал для акшиона, мдэ

@WardexOfficial

Copy link
Copy Markdown
Collaborator Author

@ThereDrD0
Не могу найти что-то на подобии TriggerOnAction, подскажешь?
Я так понимаю, что придётся впихивать Trigger-ивент в InstantAction, если TriggerOnAction не будет

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Content.Server/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepSystem.cs`:
- Around line 92-96: Сделайте операцию атомарной: либо сначала попытайтесь
добавить эффект сна, а только потом вызвать _sleeping.TrySleeping(owner) (т.е.
поменяйте порядок вызовов и вызвать TryAddStatusEffectDuration(ent,
ent.Comp.StatusEffect, hibernationDuration) перед
_sleeping.TrySleeping(ent.Owner)), либо если порядок нужен таким как сейчас —
реализуйте откат: если _statusEffects.TryAddStatusEffectDuration(...) вернул
false, отменяйте состояние сна вызовом соответствующего метода
отмены/пробуждения у _sleeping (например _sleeping.TryWake(ent.Owner) или
эквивалент), чтобы не оставить полукачественное состояние; обновите логирование
и тесты для покрытия обоих путей.

In
`@Content.Server/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySystem.cs`:
- Around line 91-127: Сейчас _visibilityActiveTargets собирает объединение целей
всех ScpOnSoundVisibilityViewerComponent и вешает глобальный
ActiveScpOnSoundVisibilityComponent, из‑за чего видимость делится между
зрителями; нужно менять это на per‑viewer логику: вместо добавления всех целей в
общий _visibilityActiveTargets и массового EnsureActiveVisibility,
фильтровать/вешать компонент в контексте конкретного viewer — то есть внутри
цикла по scpQuery для каждого viewer пройти по _visibilityCandidates и вызывать
EnsureActiveVisibility только для тех target, которые проходят локальную
проверку (или хранить временную коллекцию targetsForViewer и потом привязывать
ActiveScpOnSoundVisibilityComponent с учётом viewer id), не используя глобальное
объединение; используйте имена ScpOnSoundVisibilityViewerComponent,
_visibilityCandidates, _visibilityActiveTargets, EnsureActiveVisibility и
ActiveScpOnSoundVisibilityComponent чтобы найти и заменить текущую глобальную
логику на per‑viewer фильтрацию/привязку.

In `@Content.Server/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseSystem.cs`:
- Around line 57-68: Сохраните текущий голос перед подменой и восстановите его
после отправки сообщения: в блоке где вызывается TryComp<TTSComponent> возьмите
оригинальный voice (например originalVoice = ttsComponent.VoicePrototypeId),
присвойте messagePair.TtsVoice, вызовите _chat.TrySendInGameICMessage(...),
затем верните ttsComponent.VoicePrototypeId = originalVoice и пометьте компонент
как изменённый через Dirty(ent, ttsComponent) — это гарантирует, что временная
подмена голоса на TTSComponent не останется после отправки.

In `@Content.Shared/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepComponent.cs`:
- Around line 10-11: The ScpHealOnSleepComponent is marked with
[NetworkedComponent] but has no [AutoNetworkedField] nor
[AutoGenerateComponentState], indicating it’s a server-only component; remove
the [NetworkedComponent] attribute from the ScpHealOnSleepComponent declaration
(leave [RegisterComponent] and the class ScpHealOnSleepComponent as-is) so it is
not treated as networked, or alternatively if it actually needs networking add
[AutoGenerateComponentState] and mark mutable fields with [AutoNetworkedField];
prefer removing [NetworkedComponent] here if clients never read or update its
fields.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a17e8596-1c38-4f68-8c6b-69da6eee5e18

📥 Commits

Reviewing files that changed from the base of the PR and between 9bfeb32 and c45219a.

📒 Files selected for processing (16)
  • Content.Client/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityHudSystem.cs
  • Content.Server/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepSystem.cs
  • Content.Server/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilitySystem.cs
  • Content.Server/_Scp/Other/ScpReleaseGas/ScpReleaseGasSystem.cs
  • Content.Server/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseSystem.cs
  • Content.Server/_Scp/Research/Artifacts/Effects/_ScpSpecific/Scp939/Sleep/ArtifactScp939SleepSystem.cs
  • Content.Shared/_Scp/Other/Events/ScpSystemsEvents.cs
  • Content.Shared/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepComponent.cs
  • Content.Shared/_Scp/Other/ScpHealOnSleep/SharedScpHealOnSleepData.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityComponent.cs
  • Content.Shared/_Scp/Other/ScpOnSoundVisibility/ScpOnSoundVisibilityViewerComponent.cs
  • Content.Shared/_Scp/Other/ScpReleaseGas/ScpReleaseGasComponent.cs
  • Content.Shared/_Scp/Other/ScpRememberPhrase/ScpRememberPhraseComponent.cs
  • Resources/Prototypes/Entities/Mobs/base.yml
  • Resources/Prototypes/_Scp/Actions/scp_actions.yml
  • Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml

Comment thread Content.Server/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepSystem.cs
Comment thread Content.Shared/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepComponent.cs Outdated
@ThereDrD0

Copy link
Copy Markdown
Collaborator

Не могу найти что-то на подобии TriggerOnAction, подскажешь?

Ты должен его сделать

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Content.Server/_Scp/Other/ScpReleaseGas/ScpReleaseGasSystem.cs`:
- Around line 18-36: The handler OnAttemptTriggerEvent is subscribed to
ScpReleaseGasComponent (bearer) but AttemptTriggerEvent is raised on the action
entity (see ScpTriggerOnActionSystem.OnAction()), so the subscription will never
fire and the handler body is empty; change the subscription to listen on the
action entity created in OnMapInit (ent.Comp.ActionEnt) — e.g. subscribe to
AttemptTriggerEvent for the action entity when you call _actionsSystem.AddAction
and remove that subscription on OnShutdown (or forward the AttemptTriggerEvent
from the action entity to the bearer in ScpTriggerOnActionSystem.OnAction());
then implement the gas release logic inside OnAttemptTriggerEvent using the
bearer component (ScpReleaseGasComponent) fields. Ensure you reference and
update ActionEnt when subscribing/unsubscribing so the correct entity receives
AttemptTriggerEvent.

In `@Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs`:
- Around line 34-46: В методе OnTriggerAttempt используйте активатора из
события: замените вызовы _scpMask.TryGetScpMask(ent, out var scpMask) и
_scpMask.TryCreatePopup(ent, scpMask) на проверку и popup с использованием
args.User (AttemptTriggerEvent.User) вместо ent, и пометьте args.Cancelled =
true когда маска сработала; в методе OnAction замените второй аргумент
_trigger.Trigger(ent, ent, ent.Comp.KeyOut) на активатора (тот же объект, что и
в AttemptTriggerEvent) — если ScpActionTriggerAttemptEvent не содержит поля
пользователя, расширьте событие (или добавьте поле/механизм передачи) чтобы
передавать инициатора и используйте его в _trigger.Trigger; обновите
соответствующие места, где создаётся и шлётся ScpActionTriggerAttemptEvent,
чтобы включать пользователя.

In `@Content.Shared/Actions/SharedActionsSystem.cs`:
- Around line 302-308: Переместите вызов хука ScpActionTriggerAttemptEvent так,
чтобы он выполнялся после стандартной валидации (проверок Enabled, cooldown,
вызовов ActionAttempt и ActionValidate) и вызывался на сущности действия, а не
на user: удалите текущую отправку RaiseLocalEvent(user, ref checkEv) до
валидации и добавьте RaiseLocalEvent(actionEntity, ref checkEv) после блоков,
содержащих Enabled, cooldown, ActionAttempt и ActionValidate; убедитесь, что
обработчики ScpTriggerOnActionComponent подписываются на событие на
action-сущности и что метод по-прежнему проверяет checkEv.Cancelled и корректно
прерывает выполнение при отмене.

In `@Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml`:
- Around line 71-74: В файле указан реагент с кириллическим ID "АМН-С227", но в
других местах используются латинские варианты "AMH-C227" и "amhc227"; замените
все вхождения латинских форм на единый кириллический идентификатор "АМН-С227" по
всему репозиторию (включая записи в ignore_list и ключи/значения локализации),
убедитесь, что поля ReagentId и smokePrototype (и любые локализованные ключи)
теперь используют ровно "АМН-С227", и сделайте поисковую замену по всему
коду/локалям с проверкой кодировки/энкодинга файлов, чтобы не ввести смешанные
символы.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 950ba50a-1ded-4ebb-a560-af8069be3087

📥 Commits

Reviewing files that changed from the base of the PR and between c45219a and ea9c550.

📒 Files selected for processing (9)
  • Content.Server/_Scp/Other/ScpHealOnSleep/ScpHealOnSleepComponent.cs
  • Content.Server/_Scp/Other/ScpReleaseGas/ScpReleaseGasSystem.cs
  • Content.Shared/Actions/SharedActionsSystem.cs
  • Content.Shared/_Scp/Other/Events/ScpTriggerEvents.cs
  • Content.Shared/_Scp/Other/ScpReleaseGas/ScpReleaseGasComponent.cs
  • Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionComponent.cs
  • Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs
  • Resources/Prototypes/_Scp/Actions/scp_actions.yml
  • Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml

Comment thread Content.Server/_Scp/Other/ScpReleaseGas/ScpReleaseGasSystem.cs Outdated
Comment thread Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs Outdated
Comment thread Content.Shared/Actions/SharedActionsSystem.cs Outdated
Comment thread Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

♻️ Duplicate comments (1)
Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs (1)

16-18: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Передавайте в триггер реального исполнителя action-события.

_trigger.Trigger(ent, ent, args.KeyOut) всегда подставляет самого носителя компонента как user и затирает контекст активатора. Любая триггер-логика, завязанная на инициатора, здесь получит неверную сущность.

#!/bin/bash
# Проверить, какое поле InstantActionEvent несет исполнителя,
# и подтвердить сигнатуру TriggerSystem.Trigger.

rg -n -C3 'class InstantActionEvent|record InstantActionEvent|struct InstantActionEvent|\b(Performer|User)\b' --type cs Content.Shared Robust.Shared
rg -n -C3 'public .* Trigger\s*\(' --type cs Content.Shared/Trigger/Systems/TriggerSystem.cs

Ожидаемый результат: найти поле исполнителя в InstantActionEvent и передавать именно его вторым аргументом в _trigger.Trigger(...).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs`
around lines 16 - 18, OnAction in ScpTriggerOnActionSystem currently calls
_trigger.Trigger(ent, ent, args.KeyOut) which incorrectly uses the component
holder as the action performer; change the second argument to the real performer
from the action event (inspect ScpTriggerOnActionEvent / underlying
InstantActionEvent for the performer field named e.g. Performer or User) and
pass that entity as the user to _trigger.Trigger(...) instead of ent so trigger
logic receives the true initiator.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Content.Shared/_Scp/Other/Events/ScpTriggerEvents.cs`:
- Around line 7-8: Поле KeyOut должно быть обязательным и не-null: в объявлении
поля `KeyOut` в классе (в файле ScpTriggerEvents.cs) уберите
nullable-модификатор и пометьте DataField как обязательное (например через
параметр required либо аналогичный атрибут в вашем кодогенераторе), либо
инициализируйте поле безопасным значением (например пустой строкой или
`default!`) чтобы подавить предупреждение; это гарантирует раннюю ошибку при
отсутствующем или опечатанном YAML-поле и совместимо с обработчиком, который
передаёт `KeyOut` в `TriggerSystem`.

In `@Content.Shared/_Scp/ScpMask/ScpMaskChekerComponent.cs`:
- Around line 1-10: The file name has a typo: rename the file from
ScpMaskChekerComponent.cs to ScpMaskCheckerComponent.cs so it matches the public
class ScpMaskCheckerComponent; after renaming, update any references/imports or
project file entries if present (e.g., in solution/project or build scripts) to
the new file name to keep IDE navigation and SS14 naming conventions consistent.
- Around line 5-9: Класс ScpMaskCheckerComponent помечен как
[NetworkedComponent], но поле BlockTriggers не помечено для авто-сериализации;
добавьте атрибут [AutoGenerateComponentState] на класс ScpMaskCheckerComponent и
атрибут [AutoNetworkedField] на поле BlockTriggers (указывая при необходимости
порядковый id), чтобы состояние BlockTriggers сериализовалось и отправлялось
клиентам для корректного предсказания AttemptTriggerEvent.

In `@Content.Shared/_Scp/ScpMask/ScpMaskSystem.Checker.cs`:
- Around line 12-23: В методе OnAttemptTrigger найден лишний завершающий
оператор return в конце блока if; удалите последний "return;" (внутри ветки, где
успешно найден маск — после вызова TryCreatePopup(ent, scpMask) и установки
args.Cancelled = true) поскольку метод и так завершается, оставив только вызов
TryCreatePopup и присвоение args.Cancelled = true; убедитесь, что логика с
проверкой ent.Comp.BlockTriggers, вызовом TryGetScpMask и установкой
args.Cancelled остаётся без изменений.

In `@Resources/Prototypes/_Scp/Actions/scp_actions.yml`:
- Around line 1-38: The three new entity prototypes RememberPhraseAction,
ScpSmokeAction, and ScpSleepAction were added as concrete, player-facing
prototypes but lack matching localization keys; either add corresponding
ent-<PrototypeId> localization entries for each ID in the touched locale files
(e.g., ent-RememberPhraseAction, ent-ScpSmokeAction, ent-ScpSleepAction with
name/description strings) or change each prototype to be non-concrete by adding
abstract: true to RememberPhraseAction, ScpSmokeAction, and ScpSleepAction so
they are only base prototypes.

---

Duplicate comments:
In `@Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs`:
- Around line 16-18: OnAction in ScpTriggerOnActionSystem currently calls
_trigger.Trigger(ent, ent, args.KeyOut) which incorrectly uses the component
holder as the action performer; change the second argument to the real performer
from the action event (inspect ScpTriggerOnActionEvent / underlying
InstantActionEvent for the performer field named e.g. Performer or User) and
pass that entity as the user to _trigger.Trigger(...) instead of ent so trigger
logic receives the true initiator.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 586944ba-8a0b-439e-93d2-e83515d99768

📥 Commits

Reviewing files that changed from the base of the PR and between ea9c550 and 6530359.

📒 Files selected for processing (9)
  • Content.Shared/_Scp/Other/Events/ScpTriggerEvents.cs
  • Content.Shared/_Scp/ScpMask/ScpMaskChekerComponent.cs
  • Content.Shared/_Scp/ScpMask/ScpMaskSystem.Checker.cs
  • Content.Shared/_Scp/ScpMask/ScpMaskSystem.cs
  • Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionListenerComponent.cs
  • Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs
  • Resources/Prototypes/_Scp/Actions/scp939.yml
  • Resources/Prototypes/_Scp/Actions/scp_actions.yml
  • Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml

Comment thread Content.Shared/_Scp/Other/Events/ScpTriggerEvents.cs
Comment thread Content.Shared/_Scp/ScpMask/ScpMaskCheckerComponent.cs
Comment thread Content.Shared/_Scp/ScpMask/ScpMaskCheckerComponent.cs
Comment thread Content.Shared/_Scp/ScpMask/ScpMaskSystem.Checker.cs
Comment thread Resources/Prototypes/_Scp/Actions/scp_actions.yml
@github-actions

Copy link
Copy Markdown
Contributor

Этот PR содержит конфликты, пожалуйста, разрешите их, прежде чем мы сможем его оценить.

@WardexOfficial

Copy link
Copy Markdown
Collaborator Author

@coderabbitai сделай ревью

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for any remaining references to old Scp939 components/systems that may be broken
echo "=== Remaining references to ActiveScp939VisibilityComponent ==="
rg -n "ActiveScp939VisibilityComponent" --type cs

echo "=== Remaining references to Scp939System ==="
rg -n "Scp939System" --type cs

echo "=== Remaining references to Scp939HudSystem ==="
rg -n "Scp939HudSystem" --type cs

echo "=== ScpTriggerOnActionSystem - check if it's shared or server ==="
fd "ScpTriggerOnActionSystem.cs" --exec cat {}

echo "=== ScpTriggerOnActionListenerComponent - check YAML usage ==="
rg -n "ScpTriggerOnActionListener" --type yaml

echo "=== BaseMob ScpOnSoundVisibility - check the base.yml ==="
rg -n -A5 -B5 "ScpOnSoundVisibility" Resources/Prototypes/Entities/Mobs/base.yml

echo "=== Check localization keys with 939 ==="
rg -rn "939" Resources/Locale/ 2>/dev/null | head -50

echo "=== ScpSmokeAction / SmokeOnTrigger system ==="
rg -n "SmokeOnTrigger" --type cs | head -20
rg -n "SmokeOnTrigger" --type yaml | head -20

echo "=== Check ScpTriggerOnActionEvent handler on server ==="
rg -n "ScpTriggerOnActionEvent" --type cs

echo "=== Check ScpSleepActionEvent handler ==="
rg -n "ScpSleepActionEvent" --type cs

echo "=== Check ArtifactScp939SleepComponent YAML ==="
fd "ArtifactScp939Sleep" --type f

echo "=== Check ScpHealOnSleep YAML prototype ==="
rg -rn "ScpHealOnSleep" --type yaml | head -30

echo "=== Check ScpRememberPhraseAction YAML ==="
rg -rn "RememberPhraseAction" --type yaml | head -20

echo "=== Check Scp939 YAML for SmokeOnTrigger component ==="
cat Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml 2>/dev/null | head -120

echo "=== Check scp_actions.yml ==="
cat Resources/Prototypes/_Scp/Actions/scp_actions.yml 2>/dev/null

echo "=== Check scp939.yml actions ==="  
cat Resources/Prototypes/_Scp/Actions/scp939.yml 2>/dev/null

echo "=== Shared ScpTriggerOnActionSystem - full content ==="
fd "ScpTriggerOnActionSystem.cs" --exec cat {}

echo "=== Check if ScpSleepActionEvent is handled anywhere ==="
rg -n "ScpSleepActionEvent" 

echo "=== Check GenericVisualizer usage in scp939.yml ==="
rg -n "GenericVisualizer" Resources/Prototypes/_Scp/Entities/Mobs/Player/Scp/Main/scp939.yml

echo "=== Check ScpOnSoundVisibilitySystem full content ==="
fd "ScpOnSoundVisibilitySystem.cs" --exec cat {}

Length of output: 24026


@WardexOfficial Провожу ревью PR #981 — Децентрализация механик SCP-939.


Общий итог

Рефакторинг выполнен качественно: старые системы (Scp939System, Scp939HudSystem, Scp939Visualizer) убраны без висящих ссылок, новые системы (ScpOnSoundVisibility, ScpRememberPhrase, ScpHealOnSleep, ScpTriggerOnAction) хорошо изолированы. Ниже — найденные проблемы по приоритету.


🔴 Критично

1. Несоответствие ключа локализации scp939-flashed

В scp939.yml указан:

onFlashMessage: scp939-flashed

Но в Resources/Locale/en-US/_strings/_scp/scp/scp939.ftlru-RU) ключ называется scpn-flashed, а не scp939-flashed. Это вызовет пустое/сломанное сообщение при ослеплении SCP-939. Нужно либо переименовать ключ в .ftl, либо исправить ссылку в YAML.


🟠 Важно

2. ScpTriggerOnActionSystem в Shared — потенциальный двойной тригер

Content.Shared/_Scp/Trigger/ScpTriggerOnAction/ScpTriggerOnActionSystem.cs живёт в Shared и напрямую вызывает TriggerSystem.Trigger(...). TriggerSystem — серверная система; вызов с клиента либо будет проигнорирован, либо вызовет null-исключение на клиентском раннере. Рекомендуется перенести систему в Content.Server/ или добавить guard if (!_net.IsServer) return;.

private void OnAction(Entity<ScpTriggerOnActionListenerComponent> ent, ref ScpTriggerOnActionEvent args)
{
+   if (!IsServer) return; // или dependency на INetManager
    if (_trigger.Trigger(ent, ent, args.KeyOut))
        args.Handled = true;
}

3. BaseMob теперь несёт ScpOnSoundVisibility — ECS-нагрузка

# Resources/Prototypes/Entities/Mobs/base.yml
- type: ScpOnSoundVisibility # Fire edit

Поскольку ScpOnSoundVisibilitySystem.UpdateVisibilityTargets() каждые 0.2 с делает GetEntitiesInRange и вызывает EnsureActiveVisibility / RemCompDeferred для всех мобов в радиусе любого ScpOnSoundVisibilityViewer, каждый моб (игроки, NPC, животные) вблизи SCP-939 будет постоянно получать и снимать ActiveScpOnSoundVisibilityComponent. При большом числе мобов это создаёт заметный ECS-churn. Стоит рассмотреть более селективный подход (например, добавлять компонент только игровым персонажам / гуманоидам) или убедиться, что это ожидаемое поведение по дизайну.

4. ArtifactScp939SleepComponent — смена типа полей floatTimeSpan

Поля MinSleepTime / MaxSleepTime изменили тип с float на TimeSpan. Любой существующий YAML-прототип артефакта, где эти значения заданы как числа (minSleepTime: 10), перестанет работать — нужно обновить формат на !type:TimeSpan { seconds: 10 } или убедиться, что таких прототипов нет.


🟡 Средней важности

5. Лишний _visibilityCandidates.Clear() в конце UpdateVisibilityTargets()

// ScpOnSoundVisibilitySystem.cs
// уже очищается в начале каждой итерации внутри цикла (строка _visibilityCandidates.Clear())
// ...
_visibilityCandidates.Clear(); // ← конец метода - избыточно, но безвредно
_visibilityRemovalQueue.Clear();

Это не ошибка, но добавляет визуальный «шум». Достаточно одной очистки.

6. Ключи локализации с "939" (уже отмечено автором)

Из .ftl-файлов видно, что часть ключей ещё использует паттерн scpn-* вместо принятого нового формата. Рекомендуется пройтись по всем файлам в Resources/Locale/ и привести к единому стилю перед мёрджем.


🟢 Хорошо сделано

  • Полное удаление ActiveScp939VisibilityComponent, Scp939System, Scp939HudSystem без висящих C#-ссылок — чисто.
  • Унаследование действий в YAML через parent: RememberPhraseAction / parent: ScpSmokeAction — элегантный подход.
  • Разделение на отдельные компоненты (ScpHealOnSleep, ScpRememberPhrase, ScpOnSoundVisibility) позволит переиспользовать механики на других SCP.
  • GenericVisualizer в YAML вместо отдельного Scp939Visualizer.cs — правильное направление.
  • ScpOnSoundVisibilitySystem.EnsureActiveVisibility корректно использует MathHelper.CloseTo для float-сравнения.

Итог: Два критичных пункта (ключ локализации и Shared-тригер) нужно закрыть до мёрджа. Вопрос с BaseMob желательно обсудить с @ThereDrD0 на предмет нагрузки.

✅ Actions performed

Full review triggered.

@666XxttimurkaxX666

Copy link
Copy Markdown
Contributor

5. Лишний _visibilityCandidates.Clear() в конце UpdateVisibilityTargets()

// ScpOnSoundVisibilitySystem.cs
// уже очищается в начале каждой итерации внутри цикла (строка _visibilityCandidates.Clear())
// ...
_visibilityCandidates.Clear(); // ← конец метода - избыточно, но безвредно
_visibilityRemovalQueue.Clear();

Это не ошибка, но добавляет визуальный «шум». Достаточно одной очистки.

6. Ключи локализации с "939" (уже отмечено автором)

Из .ftl-файлов видно, что часть ключей ещё использует паттерн scpn-* вместо принятого нового формата. Рекомендуется пройтись по всем файлам в Resources/Locale/ и привести к единому стилю перед мёрджем.

🟢 Хорошо сделано

  • Полное удаление ActiveScp939VisibilityComponent, Scp939System, Scp939HudSystem без висящих C#-ссылок — чисто.
  • Унаследование действий в YAML через parent: RememberPhraseAction / parent: ScpSmokeAction — элегантный подход.
  • Разделение на отдельные компоненты (ScpHealOnSleep, ScpRememberPhrase, ScpOnSoundVisibility) позволит переиспользовать механики на других SCP.
  • GenericVisualizer в YAML вместо отдельного Scp939Visualizer.cs — правильное направление.
  • ScpOnSoundVisibilitySystem.EnsureActiveVisibility корректно использует MathHelper.CloseTo для float-сравнения.

Итог: Два критичных пункта (ключ локализации и Shared-тригер) нужно закрыть до мёрджа. Вопрос с BaseMob желательно обсудить с @ThereDrD0 на предмет нагрузки.

✅ Actions performed

"желательно обсудить с @ThereDrD0 на предмет нагрузки." 🫩

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@helper342 Понял, учту! В таком случае вопрос с BaseMob + ScpOnSoundVisibility (пункт 3) нужно решать самостоятельно или с кем-то другим из команды — стоит ли добавлять компонент всем мобам или ограничить более узкой группой сущностей.

Критичные пункты (ключ локализации scp939-flashed и ScpTriggerOnActionSystem в Shared) по-прежнему актуальны и требуют исправления до мёрджа независимо от наличия ревьюера. 🐇

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@helper342 Понял, запомнил! Теперь актуальный ревьюер — @WardexOfficial. Все замечания по PR #981 адресую ему.

(=^ ◡ ^=)


✏️ Learnings added
Learnt from: helper342
URL: https://github.com/space-sunrise/project-fire/pull/981

Timestamp: 2026-05-15T15:48:42.243Z
Learning: In the project-fire repository (github.com/space-sunrise/project-fire), the reviewer ThereDrD0 is no longer active. The new reviewer replacing ThereDrD0 is WardexOfficial. All code review feedback and questions should be directed to WardexOfficial.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@666XxttimurkaxX666

Copy link
Copy Markdown
Contributor

как писать кролику

@WardexOfficial

Copy link
Copy Markdown
Collaborator Author

как писать кролику

упоминаешь его и пишешь

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants