Skip to content

Уникальная система условий - #4777

Draft
kanopus952 wants to merge 1 commit into
makura-games:masterfrom
kanopus952:objective_system
Draft

kanopus952 wants to merge 1 commit into
makura-games:masterfrom
kanopus952:objective_system

Conversation

@kanopus952

@kanopus952 kanopus952 commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Краткое описание

Добавлена общая система целей — Objective System.

Цель состоит из набора условий:

  • all -должны выполниться все условия;
  • any - достаточно выполнить одно условие;
  • inverted - результат условия инвертируется.

Система самостоятельно хранит прогресс, проверяет выполнение, подключает наблюдателей (навешивает компоненты на сущности вокруг чтобы слушать их ивенты - ОПЦИОНАЛЬНО. Используется только для туториалов чтобы не нагружать сервер) и очищает их после завершения.

Будут / уже используются в:

  • Tutorial - завершение шагов, предварительные условия туториалов и причины провала;
  • First Shift - активное участие в раунде и полезные задания по профессии.
  • Achievement System - потенциально можно использовать для ачивок

Как описать цель

Условия можно указывать прямо в прототипе использующей их системы:

completion:
  all:
  - !type:FirstShiftParticipationObjectiveCondition
    id: participation

  any:
  - !type:CookMealObjectiveCondition
    id: cook-meal
  - !type:CleanPuddleObjectiveCondition
    id: clean-puddle

Такая цель завершится, когда игрок наберёт необходимое время и приготовит еду либо уберёт лужу.

Для переиспользуемых целей можно создать отдельный objective-прототип.


Как добавить новое условие

Условие, проверяющее текущее состояние

Например, нужно проверить включён ли боевой режим.

Создаётся описание условия:

public sealed partial class CombatModeObjectiveCondition
    : ObjectiveConditionBase<CombatModeObjectiveCondition>
{
}

Затем система, которая получает текущее состояние:

public sealed class CombatModeObjectiveConditionSystem
    : ObjectiveConditionSystem<CombatModeComponent, CombatModeObjectiveCondition>
{
    protected override void Condition(
        Entity<CombatModeComponent> entity,
        ref ObjectiveConditionEvaluateEvent<CombatModeObjectiveCondition> args)
    {
        args.Satisfied = entity.Comp.IsInCombatMode;
    }
}

Такие условия обратимы: если боевой режим выключить, условие снова станет невыполненным.

Условие, запоминающее действие

Например, нужно засчитать приготовление еды.

Создаётся отдельное событие:

[ByRefEvent]
public readonly record struct MealCookedEvent;

Описание условия:

public sealed partial class CookMealObjectiveCondition
    : ObjectiveConditionBase<CookMealObjectiveCondition>
{
}

И система, связывающая событие с условием:

public sealed class CookMealObjectiveConditionSystem
    : ObjectiveConditionSystem<
        CookMealObjectiveCondition,
        MealCookedEvent>
{
}

После успешного приготовления игровая система отправляет событие:

var ev = new MealCookedEvent();
RaiseLocalEvent(cook, ref ev);

Активные цели игрока получат прогресс автоматически.


Как использовать цели в новой системе

Система-потребитель запускает цель для сущности:

var options = new ObjectiveStartOptions
{
    Mode = ObjectiveRunMode.OneShot,
    CompletionRetention = ObjectiveCompletionRetention.Retain,
    SourceIdentifier = "MySystem",
};

_objectives.TryStartObjective(
    player,
    definition,
    options,
    out var objective);

SourceIdentifier позволяет отличать свои цели от целей Tutorial, First Shift и других систем.

После этого можно слушать результат:

SubscribeLocalEvent<ObjectiveCompletedEvent>(OnObjectiveCompleted);
private void OnObjectiveCompleted(ref ObjectiveCompletedEvent args)
{
    if (args.SourceIdentifier != "MySystem")
        return;

    // Цель выполнена.
}

При смене тела прогресс можно перенести:

_objectives.TryTransferObjective(objective, newOwner);

Когда цель больше не нужна:

_objectives.TryStopObjective(objective);

Режимы работы

OneShot

Цель завершается один раз и перестаёт отслеживаться. Подходит для заданий, достижений и шагов обучения. Типа одноразовая цель.

Monitor

Цель продолжает работать и сообщает как о выполнении, так и о возвращении в невыполненное состояние. Подходит для предварительных условий и проверок текущего состояния.


Что остаётся за использующей системой

Objective System отвечает только за условия и их прогресс.

Использующая система по-прежнему отвечает за собственную логику:

  • Tutorial выбирает текущий шаг и показывает подсказки;
  • First Shift регистрирует новичков, считает смены и сохраняет данные в БД;
  • новая система самостоятельно решает, что делать после выполнения цели.

Таким образом, новые условия можно использовать одновременно в Tutorial, First Shift и любых будущих системах без копирования логики.

@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 129 files, which is 29 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 19592c36-b28b-4255-b1f2-a08bbb3b4e34

📥 Commits

Reviewing files that changed from the base of the PR and between ff437e8 and 1ea2c4e.

📒 Files selected for processing (129)
  • Content.Client/_Sunrise/Tutorial/Conditions/UiButtonPressedObjectiveConditionSystem.cs
  • Content.Client/_Sunrise/Tutorial/Conditions/UiControlVisibleObjectiveConditionSystem.cs
  • Content.Client/_Sunrise/Tutorial/Overlays/TutorialPathOverlay.cs
  • Content.IntegrationTests/Tests/_Sunrise/Objectives/ObjectiveSystemTest.cs
  • Content.Server/_Sunrise/Objectives/Conditions/BuiOpenObjectiveConditionSystem.cs
  • Content.Server/_Sunrise/Objectives/Conditions/ChatMessageObjectiveConditionSystem.cs
  • Content.Server/_Sunrise/Objectives/Conditions/MessengerObjectiveConditionSystem.cs
  • Content.Server/_Sunrise/Objectives/Conditions/StorageOpenObjectiveConditionSystem.cs
  • Content.Server/_Sunrise/Objectives/Conditions/SwapHandsObjectiveConditionSystem.cs
  • Content.Server/_Sunrise/Objectives/Conditions/VendingMachineTakeObjectiveConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/BuiOpenListenedConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/ChatMessageListenedConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/MessengerListenedConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/StepDelayConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/StorageOpenListenedConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/UiButtonPressedConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/UiButtonPressedObjectiveConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/UiControlVisibleConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/UiControlVisibleObjectiveConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Conditions/VendingMachineTakeListenedConditionSystem.cs
  • Content.Server/_Sunrise/Tutorial/Systems/TutorialObjectiveSystem.cs
  • Content.Server/_Sunrise/Tutorial/TutorialSystem.cs
  • Content.Shared/_Sunrise/Objectives/Components/ObjectiveEventComponents.cs
  • Content.Shared/_Sunrise/Objectives/Components/ObjectiveProjectileSourceComponent.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ActivateActionObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ActivateInWorldObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ActiveHandContainsObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/AttackObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/BuckledObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/BuiOpenObjectiveCondition.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ChatMessageObjectiveCondition.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/CombatModeObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ConsumeObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/DisarmObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/DoorOpenObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/DropObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ElapsedTimeObjectiveCondition.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/EquipObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ExamineObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/GunShotObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/HealingObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/HealthAnalyzerScanObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/HoldInHandsObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/InteractObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/InternalsEnabledObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/InventorySlotContainsObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ItemHandledObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ItemInsertedObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/LieDownStandUpObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/MeleeHitObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/MessengerObjectiveCondition.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ObjectiveEventCondition.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/PickupObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/PointObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ProjectileHitObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/PullingObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/SitObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/StorageContainsObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/StorageOpenObjectiveCondition.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/SwapHandsObjectiveCondition.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/ThrowObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/TravelDistanceObjectiveCondition.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/UseObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/VendingMachineTakeObjectiveCondition.cs
  • Content.Shared/_Sunrise/Objectives/Conditions/WieldedObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Objectives/ObjectiveCondition.cs
  • Content.Shared/_Sunrise/Objectives/ObjectiveConditionEvents.cs
  • Content.Shared/_Sunrise/Objectives/ObjectiveDefinition.cs
  • Content.Shared/_Sunrise/Objectives/ObjectiveEvents.cs
  • Content.Shared/_Sunrise/Objectives/ObjectivePrototype.cs
  • Content.Shared/_Sunrise/Objectives/ObjectiveRuntimeComponent.cs
  • Content.Shared/_Sunrise/Objectives/ObjectiveRuntimeTypes.cs
  • Content.Shared/_Sunrise/Objectives/ObjectiveSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Components/Trackers/TutorialDistanceTrackerComponent.cs
  • Content.Shared/_Sunrise/Tutorial/Components/Trackers/TutorialTrackerComponent.cs
  • Content.Shared/_Sunrise/Tutorial/Components/TutorialGoalMarkerComponent.cs
  • Content.Shared/_Sunrise/Tutorial/Components/TutorialObservableComponent.cs
  • Content.Shared/_Sunrise/Tutorial/Components/TutorialProjectileSourceComponent.cs
  • Content.Shared/_Sunrise/Tutorial/Components/TutorialStepObjectivesComponent.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ActivateActionListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ActivateInWorldListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/AttackListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/BuiOpenListenedCondition.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ChatMessageListenedCondition.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ConsumeListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/DisarmListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/DoorOpenListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/DropListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/EventListenedCondition.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/EventListenedConditionBase.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ExamineListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/HealthAnalyzerScanListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/InteractListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/InternalsEnabledConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ItemInsertedListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ItemPlacedNearMarkerObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/LieDownStandUpListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/MessengerListenedCondition.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/PickupListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/PointListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ProjectileHitListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ReachMarkerObjectiveConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/SharedTutorialConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/SitListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/StepDelayCondition.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/StorageOpenListenedCondition.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/SwapHandsListenedCondition.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/ThrowListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/TravelDistanceConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/UiButtonPressedObjectiveCondition.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/UiControlVisibleObjectiveCondition.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/UseListenedConditionSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Conditions/VendingMachineTakeListenedCondition.cs
  • Content.Shared/_Sunrise/Tutorial/EntitySystems/SharedTutorialSystem.Flow.cs
  • Content.Shared/_Sunrise/Tutorial/EntitySystems/SharedTutorialSystem.Steps.cs
  • Content.Shared/_Sunrise/Tutorial/EntitySystems/SharedTutorialSystem.Tracking.cs
  • Content.Shared/_Sunrise/Tutorial/EntitySystems/SharedTutorialSystem.cs
  • Content.Shared/_Sunrise/Tutorial/Events/TutorialEvents.cs
  • Content.Shared/_Sunrise/Tutorial/Prototypes/TutorialStepPrototype.cs
  • Resources/Prototypes/_Sunrise/Tutorial/access_tutorial.yml
  • Resources/Prototypes/_Sunrise/Tutorial/combat_tutorial.yml
  • Resources/Prototypes/_Sunrise/Tutorial/communication_tutorial.yml
  • Resources/Prototypes/_Sunrise/Tutorial/food_tutorial.yml
  • Resources/Prototypes/_Sunrise/Tutorial/introduction_tutorial.yml
  • Resources/Prototypes/_Sunrise/Tutorial/inventory_tutorial.yml
  • Resources/Prototypes/_Sunrise/Tutorial/medical_tutorial.yml
  • Resources/Prototypes/_Sunrise/Tutorial/survival_tutorial.yml
  • Resources/Prototypes/_Sunrise/Tutorial/tutorial_step_bases.yml

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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.

@makura-auto-draft

makura-auto-draft Bot commented Sep 10, 2026

Copy link
Copy Markdown

Готовим изменения к ревью

Привет! Здесь видно, что осталось сделать перед проверкой человеком. Пролистай страницу ПР вниз до блока проверок: там видны тесты и их результаты. Галочки в этом списке обновляются автоматически.

  • Разобраться с замечаниями. Исправь код и закрой решённые обсуждения во вкладке Files changed — изменённые файлы. Если не согласен, обсуди это с ревьювером.
  • Решить конфликты слияния в IDE.

Warning

GitHub не разрешит слить ПР, пока есть конфликты. Обнови свою ветку из целевой, открой отмеченные как конфликтующие файлы в IDE, выбери правильные изменения, создай коммит и отправь его.

  • Проверка CodeRabbit: достигнут лимит запросов, поэтому сейчас разрешено продолжить без нового ревью.
    CodeRabbit — искусственный интеллект: он может ошибаться и предлагать бессмысленные исправления. Сам проверь, действительно ли найден баг. Исправляй настоящие ошибки, а с неверным замечанием объясни своё несогласие в обсуждении.
  • Пройти обязательные проверки внизу страницы ПР. Нажми на нужную проверку, чтобы посмотреть результат. Также доступна вкладка Checks — проверки. Жёлтая проверка ещё выполняется; красная завершилась с ошибкой.
Показать обязательные проверки
  • YAML Linter
  • Content Tests
  • Build & Test Debug
  • Test Packaging
  • Integration Tests (shard 0)
  • Integration Tests (shard 1)
  • Integration Tests (shard 2)
  • Integration Tests (shard 3)
  • Integration Tests (shard 4)
  • Integration Tests (shard 5)
  • Integration Tests (shard 6)
  • Integration Tests (shard 7)
  • Build & Test Debug
Как найти список ошибок тестов
  1. Пролистай ПР вниз до блока проверок и нажми на упавший тест. Можно также открыть его во вкладке Checks.
  2. На странице задания нажми Summary — сводка запуска.
  3. В сводке раскрой нужный шард — группу тестов, например Integration Tests (shard 0). Там будет список ошибок.
  4. Исправь причину и отправь изменения в этот ПР. Если сводка не содержит ошибок, открой журнал упавшего шага задания.

Когда все пункты выполнены, бот сам переведёт ПР из черновика в готовое состояние. Обновление иногда занимает несколько минут.

@makura-auto-draft makura-auto-draft Bot added the 🍄 автодрафт: нужны исправления Автоматический черновик: ожидаются исправления или обязательные проверки. label Sep 10, 2026
@makura-auto-draft
makura-auto-draft Bot marked this pull request as draft September 10, 2026 23:51
@ThereDrD0

Copy link
Copy Markdown
Member
image
  1. Что тут делают айди? Не описано и я не понял
  2. Нужен более полный прототип с комментариями
image
  1. Непонятно, когда приходит этот ивент, что за ивент такой, что находится в базовой системе.
  2. Непонятно зачем нужен класс для цели, зачем он используется. Может ли там быть логика или данные
  3. Непонятно, почему в одном примере можно выставить компонент + кондишен, а в другом примере уже кондишен + ивент(как это работае, в чем разница в работе, почему порядок расположения кондишена поменялся)
  4. Тут оказывается есть какие-то ObjectiveStartOptions, но о них ничего не сказано. Он просто появляется в моменте

В целом документация написана понятным языком, но она очень маленькая. Система очень комплексная, нужно написать куда более обшируню документацию.
Без этого тщательное ревью сделать нельзя, я просто не понимаю как работает система. А пытаться понять это из кода это ужас(но я могу попытаться)

@kanopus952

Copy link
Copy Markdown
Contributor Author
image 1. Что тут делают айди? Не описано и я не понял 2. Нужен более полный прототип с комментариями image 3. Непонятно, когда приходит этот ивент, что за ивент такой, что находится в базовой системе. 4. Непонятно зачем нужен класс для цели, зачем он используется. Может ли там быть логика или данные 5. Непонятно, почему в одном примере можно выставить компонент + кондишен, а в другом примере уже кондишен + ивент(как это работае, в чем разница в работе, почему порядок расположения кондишена поменялся) 6. Тут оказывается есть какие-то `ObjectiveStartOptions`, но о них ничего не сказано. Он просто появляется в моменте

В целом документация написана понятным языком, но она очень маленькая. Система очень комплексная, нужно написать куда более обшируню документацию. Без этого тщательное ревью сделать нельзя, я просто не понимаю как работает система. А пытаться понять это из кода это ужас(но я могу попытаться)

  1. Тут ошибка, неправильный пример. Это ID из first shift системы, которое щас уже фактически не используется. В общем считай это как пример, что в каждое условие можно добавить какое-то поле, которое можно заполнить, например target: SomeFood или чет такое

  2. По факту любой прототип туториал условия. Ну например

- type: tutorialStep
  id: IntroTutDropOldClothing
  parent: IntroductionTutorialStepBase
  bubble:
    text: intro-tut-drop-old-clothing-bubble
  chatMessage: intro-tut-drop-old-clothing-chat
  ttsMessage: intro-tut-drop-old-clothing-tts
  completion:
    all: []
    any:
    - !type:DropObjectiveCondition
    - !type:HoldInHandsObjectiveCondition
      inverted: true

Здесь система условий учавствует только в поле completion

  1. ObjectiveConditionEvaluateEvent нужен чтобы система целей могла проверить у условия его текущее состояние.

Оно вызывается на сервере:

  • сразу после запуска цели;
  • каждый серверный тик, пока цель активна;
  • после передачи цели другому владельцу.

Например, для боевого режима:

public sealed class CombatModeObjectiveConditionSystem
    : ObjectiveConditionSystem<
        CombatModeComponent,
        CombatModeObjectiveCondition>
{
    protected override void Condition(
        Entity<CombatModeComponent> entity,
        ref ObjectiveConditionEvaluateEvent<CombatModeObjectiveCondition> args)
    {
        args.Satisfied =
            entity.Comp.IsInCombatMode == args.Condition.Enabled;
    }
}

Базовая ObjectiveConditionSystem делает следующее:

  1. Подписывается на ObjectiveConditionEvaluateEvent.
  2. Ищет необходимый компонент на владельце цели.
  3. Если компонента нет — возвращает false.
  4. Если компонент есть — вызывает Condition() конкретной системы (в нашем случае системы условия комбат мода).
    У Satisfied есть три возможных состояния:
  • true — условие сейчас выполнено;
  • false — условие сейчас не выполнено;
  • null — условие не проверяет текущее состояние.
    null нужен условиям-историям, например «приготовить еду». После приготовления событие уже произошло, и результат должен сохраниться навсегда. Такое условие увеличивает прогресс через TryAddConditionProgress()
  1. Класса для целей два. Сам класс цели хранит статические данные и используется в прототипах, а система уже смотрит выполнено ли условие, может использовать статические данные с класса цели.

  2. Это зависит от того, что требуется отследить. Если нужно просто проверить поле компонента, используется кондишен+компонент, если поднятие ивента - кондишен+ивент. Можно сказать, что первая пара (комп+кондишен) проверяет что сейчас, а вторая пара (кондишен+ивент) проверяет что произошло через подпись на ивент

ObjectiveStartOptions описывает, как конкретный потребитель запускает эту цель.
FirstShift запускает её так:

var options = new ObjectiveStartOptions
{
    // Цель завершается один раз и больше не возвращается
    // в невыполненное состояние.
    Mode = ObjectiveRunMode.OneShot,

    // После завершения сущность цели сохраняется,
    // чтобы FirstShift мог читать её итоговый статус.
    CompletionRetention = ObjectiveCompletionRetention.Retain,

    // FirstShift не нужно искать предметы вокруг игрока,
    // в руках, экипировке и списке действий.
    ObservationScope = ObjectiveObservationScope.None,

    // Метка, позволяющая отличать цель FirstShift
    // от целей Tutorial и других систем.
    SourceIdentifier = FirstShiftConstants.ObjectiveSourceIdentifier,
};

_objectives.TryStartObjective(
    participant.Owner,
    track.Completion,
    options,
    out var objective);

Все параметры:

  • Mode = OneShot — цель завершается навсегда при первом выполнении.
  • Mode = Monitor — цель продолжает работать и может переключаться между true и false.
  • CompletionRetention = Remove — удалить сущность завершённой цели.
  • CompletionRetention = Retain — сохранить её для последующего чтения статуса.
  • ObservationScope — где условия могут искать целевые сущности: рядом, в руках, экипировке или действиях. Например для туториалов надо искать в радиусе, там задаем поиск повсюду (он как Default). В FirstShift мы не просматриваем сущности вокруг и прочее.
  • ObservationRange — Базовый радиус поиска вокруг игрока.
  • SourceIdentifier — метка системы, запустившей цель. Так как систем может быть много, нам нужно их как-то отделять, поэтому оно надо.
    Эти настройки не находятся в YAML цели, потому что одна и та же цель может использоваться по-разному. Tutorial может запустить её как постоянно отслеживаемую проверку, а FirstShift - как одноразовую цель с сохранением результата.

@kanopus952

kanopus952 commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Причем ObjectiveConditionEvaluateEvent используется только в условиях вида компонент+кондишен, чтобы отправить состояние что происходить "сейчас"

Нам не нужен метод RecordEvent как в случае пары ивент+компонент, так как через ObjectiveConditionEvaluateEvent мы мониторим какое-то состояние, а не записываем прогресс

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

Labels

🍄 автодрафт: нужны исправления Автоматический черновик: ожидаются исправления или обязательные проверки.

Projects

Status: НЕ РАЗОБРАНО

Development

Successfully merging this pull request may close these issues.

2 participants