VNLEWIKIСоздавайте истории. Соединяйте миры.
Русский
Руководство VNLE

Правила переходов и игровые действия

← Руководство по интеграции и движки

Эти правила объясняют экспорт для собственных скриптов и интеграций сообщества. JSON содержит данные, а не исполняемый код. Раскладка узлов, выделение и внутреннее устройство интерфейса редактора не управляют игрой.

Перед первым шагом

Проверьте format = vnle.story, containerVersion = 1, поддерживаемую execution.contractVersion и requiredCapabilities. Пример использует 1.1 с core.v1 и substory.call-return.v1. JSON Schema проверяет структуру; для выполнения также нужны проверки ссылок, типов и поддерживаемых команд. Не пропускайте неизвестные типы узлов без сообщения об ошибке.

Справочник полей · JSON Schema

Что означает каждый узел

kindПоведение
dialogueПокажите текст, дождитесь Continue и следуйте continuation.
choiceСледуйте optionOrder, отберите варианты по option.condition, примените effects выбранного варианта один раз и следуйте continuation. Учитывайте whenEmpty.
branchВычислите condition и перейдите по whenTrue или whenFalse.
actionВыполните effects по порядку, затем следуйте continuation.
jumpПерейдите к целевой точке входа, не добавляя точку возврата.
callЗапомните continuation и перейдите к целевой точке входа.
returnПродолжите с последней сохранённой точки. Return без предшествующего Call — ошибка.
commandОцените аргументы, запросите игровое действие, дождитесь его результата и следуйте соответствующему результату.
endЗавершите весь текущий разговор, даже находясь внутри подыстории. Return возвращает управление вызывающему диалогу.

Условия и типизированные значения

Операнд бывает literal с типизированным значением или variable с variableRef. compare поддерживает eq, ne, lt, lte, gt и gte. all требует выполнения всех дочерних условий, any — хотя бы одного, not инвертирует дочернее условие. Не путайте логические значения со строками "true"/"false".

Операции над переменными: set, add и subtract. add/subtract работают с целыми числами от −2147483648 до 2147483647. Вычисляйте эффекты по порядку, но не применяйте частичное обновление, если один из эффектов недопустим. Не перезаписывайте сохранённые значения начальным defaultValue при каждом разговоре.

Jump · Перейдите на склад после покупки

Переход

Если ключ уже куплен, перейдите сразу к точке входа Warehouse. target содержит flowRef и entryRef; execution.entries[entryRef].nodeRef задаёт следующий узел. Jump не открывает сцену или карту движка автоматически: для этого нужно соответствующее игровое действие.

{
  "flowRef": "1f69a7b6-1bdc-4dff-b8ee-9b2819b35168",
  "id": "2e1710dc-c32f-418f-abca-e055d6fd28f3",
  "kind": "jump",
  "target": {
    "entryRef": "a4dd48dc-b0e2-47fc-b102-def52583a8fe",
    "flowRef": "2a0a259c-b76a-4de0-8cee-567713c2d320"
  }
}
Call Substory / Return · Мира рассказывает о складе

Вызов подистории / Возврат

Да, этот переход описан в JSON. После приветствия история вызывает рассказ о запертом складе. Игра помещает continuation в стек и переходит в target. После объяснения Миры выполнение доходит до return, извлекает последнее продолжение из стека и выполняет Already have the key?. Вложенные вызовы работают по тому же правилу.

{
  "continuation": {
    "kind": "node",
    "nodeRef": "95e9a55f-f6b1-4696-9c52-6ea3ea2ac7e5"
  },
  "flowRef": "1f69a7b6-1bdc-4dff-b8ee-9b2819b35168",
  "id": "85b3aadf-2b95-4150-bc44-c0c796337874",
  "kind": "call",
  "target": {
    "entryRef": "2bac8555-3cae-4a21-9b8c-b410ab207ebb",
    "flowRef": "ea13b52e-092a-44ff-b087-0ce65d040c9a"
  }
}
{
  "flowRef": "ea13b52e-092a-44ff-b087-0ce65d040c9a",
  "id": "f8b8673a-cb86-40ae-a4f6-d37a5c1563c3",
  "kind": "return"
}

Все задействованные узлы находятся в экспортированном story.json. Call не означает загрузку другого JSON-файла или скрипта. maxCallDepth ограничивает вложенность. Return при пустом стеке — ошибка. End завершает весь разговор и очищает стек.

Command · Откройте магазин или выдайте ключ

Команда

Подходящий пример — «Открыть магазин»: игра открывает свой магазин и приостанавливает диалог. Только после закрытия магазина она сообщает согласованный результат, например purchased или cancelled. Определите эти имена и аргументы как игровое действие в проекте VNLE; open_shop не является встроенной командой VNLE.

Реальный экспорт гавани использует give_item: команда ссылается на определение, передаёт ID предмета и предлагает два исхода. Игра добавляет ключ в инвентарь или отказывает в приёме. Автор уже задал дальнейший путь для обоих результатов.

{
  "arguments": {
    "3cac6185-4404-4a2a-be5f-14afa0f97137": {
      "kind": "literal",
      "value": {
        "entityType": "item",
        "type": "reference",
        "value": "2d71e57e-9b58-4fdb-a33f-42b89bd8bf04"
      }
    }
  },
  "commandRef": "0723beb0-daba-4602-a665-4efc27511bc3",
  "flowRef": "1f69a7b6-1bdc-4dff-b8ee-9b2819b35168",
  "id": "500c28a1-ed85-4c36-9a38-bedacce1c6b7",
  "kind": "command",
  "outcomes": {
    "12bc86a9-b2eb-4eb4-836c-a9efd936bf1b": {
      "continuation": {
        "kind": "node",
        "nodeRef": "382640aa-5b50-4715-9148-b470bc2f7cd6"
      },
      "resultBindings": {}
    },
    "1c527580-69a6-4e99-8503-1b0de3fc8e78": {
      "continuation": {
        "kind": "node",
        "nodeRef": "221d6b0c-99e1-45a8-bc73-768c4ee679eb"
      },
      "resultBindings": {}
    }
  }
}
{
  "id": "0723beb0-daba-4602-a665-4efc27511bc3",
  "key": "give_item",
  "name": "Give item",
  "category": "custom",
  "inputs": [
    {
      "id": "3cac6185-4404-4a2a-be5f-14afa0f97137",
      "name": "Item",
      "valueType": {
        "entityType": "item",
        "kind": "reference"
      }
    }
  ],
  "outcomes": [
    {
      "id": "12bc86a9-b2eb-4eb4-836c-a9efd936bf1b",
      "name": "Received",
      "results": []
    },
    {
      "id": "1c527580-69a6-4e99-8503-1b0de3fc8e78",
      "name": "Declined",
      "results": []
    }
  ]
}
  1. Найдите commandRef в execution.commands (сигнатура) и content.commandDefinitions (читаемый ключ).
  2. Вычислите аргументы по ID входных параметров. Для отсутствующих необязательных аргументов используйте объявленное defaultValue.
  3. Запросите явно поддерживаемое игровое действие один раз. На время ожидания запретите Continue и повторное выполнение.
  4. Проверьте ID исхода и типизированные возвращаемые значения. outcome.resultBindings присваивает их переменным истории; затем следуйте outcome.continuation.
  5. Техническая ошибка не равнозначна исходу отмены, заданному автором. Покажите ошибку и предусмотрите управляемый повтор или отмену в игре.

В этом проекте отказ в приёме ключа возвращает пять золотых. Это делает экспортированное продолжение, а не автоматическое поведение каждого Command. Инвентарь, журнал заданий и карты — системы вашей игры; сами записи каталога JSON их не создают.

Подстановочные поля · «У вас осталось 5 золотых»

Текст и подстановочные поля

{
  "continuation": {
    "kind": "node",
    "nodeRef": "2e1710dc-c32f-418f-abca-e055d6fd28f3"
  },
  "flowRef": "1f69a7b6-1bdc-4dff-b8ee-9b2819b35168",
  "id": "0d7f959e-8fba-4882-ae98-b66d8416d4d2",
  "kind": "dialogue",
  "speakerRef": "807b2957-7bab-4a28-83a4-1f3d1589bbc2",
  "text": {
    "bindings": {
      "1084cf8e-515e-4b33-92f8-b5c260e88a9e": {
        "kind": "variable",
        "variableRef": "a547610e-661f-4b8d-a25b-21d042f1a2d5"
      }
    },
    "textRef": "fcc775ff-558e-4a41-823d-183aaff03e4b"
  }
}

Сегменты kind: text соединяйте напрямую. Для kind: placeholder найдите определение по placeholderRef в записи текста и привязку в node.text.bindings. Привязка задаёт константу или значение переменной. Получите его при показе реплики и отформатируйте по типу. Типы и параметры форматирования приведены в справочнике полей.

PlaceholderDefinition · Сообщение

Прогресс, ограничения и ошибки

Сохраняйте позицию, переменные истории, стек возврата и ожидающие игровые действия вместе с состоянием игры. Язык — отдельная настройка. storyBuildId помогает сопоставить сохранение с версией исполняемых данных; не угадывайте продолжение для несовместимой истории.

maxAutomaticTransitions, maxConditionDepth, maxConditionTerms и maxCallDepth ограничивают автоматические и глубоко вложенные переходы. Отсутствующие ссылки, отсутствие ответов при whenEmpty: fault, неизвестные команды и недопустимые типы требуют понятных ошибок. Перерисовка интерфейса не должна повторять покупки или изменения переменных.

Передайте интеграцию разработчику или ИИ

Предоставьте реальный экспорт, версию движка, целевую платформу, эти правила переходов и страницу движка. Опишите элементы интерфейса и существующие функции инвентаря или магазина. Попросите использовать реальные поля JSON и документированные API движка, а также проверить случаи ниже.

  1. Десять золотых: ключ получен, осталось пять. Две золотые монеты: ключа нет, деньги не списаны.
  2. Инвентарь отказал в приёме: возврат денег по сюжету, без ложного сообщения об успехе.
  3. Call/Return возвращает к нужному узлу; End внутри Call завершает разговор.
  4. Смена языка сохраняет прогресс; отсутствующие переводы и намеренно пустой текст обрабатываются правильно.
  5. JSON, изображения и шрифты из сборки доступны вне папки разработки; при отсутствии изображения старый портрет не остаётся на экране.