Всем привет!
Сегодня говорим про систему world state — она позволяет делать вариативность, запоминать решения игрока и делать реплики/ответы на основе флагов.
Для меня было несколько удивительно узнать об этой системе — в играх мы обычно видим различные системы, с которыми взаимодействует игрок: различные варианты выбора, наборы умений и бонусов, деревья прокачки или сложное поведение НПЦ. Однако почти во всех играх, как оказалось, присутствует система состояния мира. Но находится она в неявном виде, поэтому существует только в логике игры.
Если вы подойдёте к НПЦ, то некоторые реплики вы захотите разблокировать только после определённой проверки, после сказанной реплики, встречи с кем-то другим или новой обнаруженной информации. Вы хотите создать реактивность игры на действия игрока.
Как сделал:
Создал динамическую структуру — WorldStateMap, которая может добавлять в себя новые значения.
Изначально она полностью пустая, и чем больше ты играешь в игру, тем больше она наполняется значениями, которые игра может использовать.
Для доступа к структуре у каждой реплики НПЦ и у каждого ответа игрока есть 3 поля (они добавлены в шаблонах Articy, и потом мой скрипт-конвертер их обрабатывает):
bRecordToWS — если галочка стоит, то реплика должна записать флаг.
WSFlagName — имя флага. (Пример: SETBOOL(met_person).)
NodeVisibilityCondition — условия видимости. (Пример: GETBOOL(met_person).) Каждая нода проверяется. Если условия возвращают FALSE, то тогда нода не показывается.
Сам цикл записи и получения данных из WS:
SETBOOL(met_person) --> Запись в WS --> GETBOOL(met_person) --> true/false
При самой записи в WS простой парсер разбирает текст на аргументы и отправляет значения на выбор команды: (СКРИН_1)
SETBOOL
GETBOOL
SETINT
GETINT
HAS_VISITED — это специальное поле, которое позволяет затемнять уже прочитанные реплики. (СКРИН_2)
ADD_VISITED — ещё одно поле, которое записывает в список все прочитанные реплики.
Также есть поддержка NOT — это не отдельные команды, а рекурсия с перевёрнутыми значениями true/false.
Для того чтобы записать значение, диалоговый менеджер отправляет значение флага в WS (Process Query). (СКРИН_3)
В случае чтения кнопка или менеджер также обращаются в WS, который возвращает true/false. (СКРИН_4)
Также все активные проверки (навыки/сноски/сноски+навыки) ставят флаг только после успешного броска кубика. Все обычные кнопки ставят его сразу.
Отдельно упомяну, что все посещённые ответы игрока имеют свой уникальный ID, который и записывается в WS, но не в общий пул флагов, а в отдельный VisitedDialogueIDs.
В результате ответы игрока и реплики НПЦ могут скрывать или показывать друг друга. Получаем динамическую систему, которая запоминает все действия игрока, — что и нужно нарративному дизайнеру!
