Пять проектов, которые уже показывали прогресс в формате демо-версии или даже полноценного пролога, и ещё один, который пока демонстрирует только скриншоты и арты.
Norland – январь 2024
Симулятор средневекового королевства, вдохновлённый Rimworld и Crusader Kings. Играть предстоит за знатную династию, управляющую городом, населенным всеми сословиями: от простых крестьян до знатных дворян. Особенностью проекта является генерация сложных историй и выстраивание не только производственных цепочек, но и отношений внутри вашего семейства.
Но не интригами едиными: придётся в игре и всерьёз сражаться, ведь другие королевства не прочь наложить лапу на ваши ресурсы и земли. Да и внутри вашего города может назреть бунт: следите за настроениями народных масс и старайтесь удовлетворять хотя бы часть их потребностей.
The Crust – 1 квартал 2024
Представьте себе улучшенный Surviving Mars с упором на организацию производства и возможностью прокладывания конвейеров. И без капризов колонистов, ведь в вашем распоряжении будут вахтовики, которые просто выполняют свою работу. И не на Марсе, а на Луне. Слишком много «не»? Но в остальном игра действительно навевает воспоминания о часах на Марсе: проверено на двух демо-версиях.
Действие будет происходить в ближайшем будущем, а играть предстоит за космическую корпорацию, развернувшую добывающую промышленность на спутнике Земли. Попутно нам обещают рассказать об уже свершившихся к моменту выпуска игры космических достижениях человечества, так что проект обещает быть ещё и познавательным.
Песнь Копья – 28 мая 2024
У этого проекта демо-версия доступна вне фестивалей, так что попробовать её можно прямо сейчас. По геймплею игра представляет собой пошаговую тактику с элементами рогалика. Играть предстоит за отряд богатырей, раз за разом отправляющихся в поход, чтобы очистить землю русскую от различной нечисти.
Каждое прохождение генерирует свою историю, причём бойцы не воскресают: если проиграешь, то придется отправиться заново в поход с новым отрядом. А противостоять будут известные персонажи из сказок: упыри, волколаки, Змей-горыныч, Кощей и многие другие.
Plague Lords – 3 квартал 2024
Пошаговая тактика в средневековом сеттинге, где игроку предстоит разобраться со странной чумой, выкашивающей население поселений, собрать остатки испуганных крестьян и научить их держать в руках оружие. При этом воины не штампуются в кузницах или казармах: с каждым сражением ваши люди становятся всё опытнее и опаснее для врага. Но и потеря ветерана больно бьёт по вашей обороноспособности.
До выхода основной игры планируется выпуск бесплатного пролога, Plague Lords: Witch Hunt, который познакомит с основными механиками проекта и с миром игры.
Broken Arrow – 2024
Зрелищная тактическая стратегия в режиме реального времени о противостоянии России и США (в будущем планируют добавить и другие армии). Сражаться предстоит на земле, в воздухе и на море, причём обещаны как режимы, привычные любителям классических варгеймов, так и что-то новенькое. Отдельный интерес представляет подробная система кастомизации, позволяющая менять пусковые установки, броню, типы боеприпасов или добавлять топливные баки.
Помимо двух кампаний обещан редактор сценариев, который позволит сообществу создавать свои битвы. Релиз ожидается в 2024 году, без уточнения месяца или квартала.
Night is Coming – 2024
В отличии от предыдущих проектов, эта игра ещё не открывала двери демо-версии или пролога.
По жанру это выживание общества в фэнтезийном мире, основанном на славянском фольклоре. Игроку предстоит управлять поселением, осваивать новые просторы, противостоять холодам и тьме, в которой скрываются кикиморы и лешие, оборотни и многие другие чудища. Но и на вашей стороне будут не только обычные люди: ещё в поселения будут приходить герои – древние мастера своего дела, готовые помочь в борьбе против нечисти.
Ранее выход был даже запланирован на 2023 год, но команда была вынуждена сделать перерыв в разработке и перенесла дату релиза на 2024.
Ранее я уже описывал, как я дошёл до того, чтобы заняться геймдевом, как я готовился к этому и как выбирал инструменты. Здесь же я хочу сосредоточиться именно на самой игре, а также Bevy и Rust, как основных инструментах разработки.
Логотипы выбранных инструментов
Итак, игра с незамысловатым названием HackeRPG (Hacker + RPG), экшн, где управление основано на кодинге. Проект, в силу своей специфики, рассчитан на узкую аудиторию или, другими словами, «на своих». Из этого следует, что было бы хорошим тоном добавить пасхалки и привычные разработчикам фичи.
Дабы упростить дальнейшее понимание решений, которые я реализовывал, будет правильно хотя бы немного описать движок Bevy. Главная его особенность - ECS (Entity component system), где
Component - любая сущность игре(будь то спрайт, свет или текст);
Entity - грубо говоря, контейнер, куда мы складываем все компоненты;
System - действия с компонентами, которые выполняются в бесконечном цикле.
Визуализация ECS
Помимо прочего в движке реализованы состояния (для ограничения работы систем), события (для разового вызова систем) и ресурсы (для хранения данных, которые не связаны с какими-либо сущностями в игре и не могут иметь несколько экземпляров, формально этого же можно достичь с помощью компонентов, но этот вариант в некоторых ситуациях удобнее).
За конкретными гайдам по самому движку - на официальный сайт или искать мануалы на YouTube.
UI
В начале работы мне предстояло определиться с визуальным стилем и его реализацией. Для пользовательского ввода я выбрал mouseless подход: каждое меню в игре - симуляция терминала, а основной геймлуп - ввод текста в консоль. Ну и, разумеется весь текст обязательно должен быть зелёным: куда без заезженной хакерской эстетики?
И не говорите мне, что ваш рабочий день выглядит не так
Задача достаточно тривиальная, но с учётом ECS - не самая удобная. Однако после некоторых оптимизации и разбиения функционала и модулей можно добиться вполне сносной архитектуры.
Изначально я создал системы, которые вызываются только один раз и создают нужные нам компоненты, такого вида (здесь и далее код будет упрощён до минимума, чтобы не перегружать лишней информацией):
fn setup_menu_system(
mut commands: Commands,
game_assets: Res<GameAssets>
) {
commands.spawn(
NodeBundle {
style: Style {
width: Val::Percent(100.),
height: Val::Percent(100.),
flex_direction: FlexDirection::Column,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
..default()
}
).with_children(|parent| {
spawn_console(
&game_assets,
parent,
);
});
}
Где структура commands добавляет на экран элемент NodeBundle с дочерними элементами, которые создаёт моя собственная функция spawn_console.
Хотелось бы отметить удобство работы с HUD слоем: в Bevy она реализована на основе концепции FlexBox, которая будет привычна любому, кто более или менее знаком с веб фронтенд разработкой.
Важный нюанс используемой мной концепции UI - input и output зачастую отображаются одним и тем же компонентом. Т.е. при наличии такого меню:
Say hello
>hello█
Где первая строка - output, а вторая (кроме первого символа и символа каретки) - input.
Таким образом для удобства пользовательский ввод хранится в отдельном компоненте, а система, которая выводит текст на экран, уже на лету «приклеивает» его. Такой подход так же позволил довольно удобно реализовать логику каретки и истории ввода, но их я разбирать сегодня не буду. Так, для вывода текста в нашем «терминале», я использую системы вида:
fn menu_output_system(
mut console_query: Query<(&mut Text, &TextInput)>
) {
if let Ok((mut output, input)) = console_query.get_single_mut() {
Где Query используется для того, чтобы получить сущности, у которых присутствуют указанные компоненты, TextInput - мой кастомный компонент, который хранит данные о вводе и автодополнении, а функция get_menu_output - генерит строку для вывода. Довольно минималистично и аккуратно.
Осталось добавить обработку ввода и MVP терминала готово! Для этого я решил использовать две вот такие системы:
Первая функция обрабатывает события типа ReceivedChar, отправляя полученный символ в TextInput по позиции каретки, после чего обновляет положение каретки. Вторая - обрабатывает нажатия клавиши Enter и выходит из приложения, если был введён 0(ноль). Добавляя дополнительные состояния, которые будут характеризовать текущий экран, можно реализовать любую навигацию, обработку ввода и отображение информации, используя вышеописанные конструкции.
Результат проделанной работы
На данный момент в Bevy состояния не могут хранить какую-либо информацию, а представляют собой примитивное перечисление. Это вынуждает связывать их с ресурсами или компонентами, которые хранят информацию о них. Насколько мне известно, в ближайшее время не планируется это менять, поэтому приходится с этим жить.
В остальном UI довольно тривиален: отображение текста, анимация спрайтов, движение - типичный контент самых простых туториалов. Поэтому продолжу описывать именно «прогерские» фичи.
Gameloop
Следующий шаг: реализация главной фичи игры - управления персонажем с помощью команд. Для ввода текста можно без проблем использовать ранее описанную menu_char_input_system, но теперь её можно сделать несколько более глобальной. Уберём из названия слово menu и заставим её работать не только на экране меню, но и в самой игре. Удалось переиспользовать ранее написанный код, значит что-то правильное есть в архитектуре, а это хорошо! А вот control_input_system потребуется реализовать другую. Опустим boilerplate code и сразу к сути:
...
if let Some(command) = command_from_string(input.text.to_string()) {
player_commands.queue.push(command);
}
...
Теперь, когда мы нажимаем Enter, мы пытаемся спарсить команду на основе нашего инпута. В случае успеха - добавляем команду в очередь.
Парсинг осуществляется в функции command_from_string, которая в рамках этой статьи останется чёрным ящиком, который делает какую-то магию с регулярками.
После этого в ход вступает система, которая по одной исполняет команды из очереди, если нет текущей активной команды:
fn handle_command_queue_system(
mut commands_query: Query<&mut PlayerCommands>
) {
for (mut commands) in commands_query.iter_mut() {
if check_in_progress(&commands) {
continue;
}
set_current_command(&mut commands_query);
}
}
Можно заметить, что здесь используется for и iter_mut() вместо if let Ok и get_single_mut(). Таким образом мы обрабатываем компоненты, которых в игре может быть несколько. Этот сниппет - программное олицетворение моего оптимизма, который внушает мне, что проект найдёт интерес и признание и запрос на мультиплеер появится. В остальном - происходит проверка есть ли текущая активная команда с помощью check_in_progress, если её нет, то команда переносится из вектора query в переменную current.
Далее управление принимает довольно большое количество систем, каждая из которых обрабатывает одну конкретную команду. Изначально вся эта конструкция представляла собой один большой match, который со временем стал воистину монструозный, из-за чего был беспощадно разрезан на множество систем катаной рефакторинга. Вот одна из таких систем:
В вышеописанной функции мы проверяем, является ли текущая команда командой move. Если да, то обрабатываем её. Такое разбиение создаёт некоторый boilerplate, однако убирает ад с огромным количеством Query, практика показала, что это решение достаточно удобное.
Результат
Таким образом удалось реализовать управление посредством команд. В конечном итоге можно добавлять новые команды посредством добавления ключевых слов и элементов в enum при парсинге, а так же одной системы, которая будет эту команду обрабатывать. Довольно неплохо и почти чисто.
IDE
А теперь настало время прыгнуть в кроличью нору: время добавить внутриигровую IDE. Описание основных фичей связанных с реализацией терминала уже было ранее. Разве что перемещение каретки не было описано, но это я оставлю, как домашнее задание. Далее же задача весьма тривиальна - рекурсивный парсинг. Но вот проблема: Rust не дружит с использованием рекурсии в регулярных выражениях, а значит решение одно:
Костыли
Пришлось комбинировать парсинг с использованием регулярных выражений с рекурсией на основе функций. Таким образом появилась возможность создавать ифы в ифах и форы в форах. В результате из строки получается структура типа CodeBlock:
#[derive(PartialEq, Debug, Clone)]
pub struct CodeBlock {
pub name: String,
pub block_type: CodeBlockType,
pub content: Vec<CodeBlockContent>,
}
#[derive(PartialEq, Debug, Clone)]
pub enum CodeBlockType {
Function(Vec<String>),
Daemon,
Virus,
}
#[derive(PartialEq, Debug, Clone)]
pub enum CodeBlockContent {
Block(InnerCodeBlock),
Lines(Vec<String>),
}
#[derive(PartialEq, Debug, Clone)]
pub struct InnerCodeBlock {
pub block_type: InnerCodeBlockType,
pub content: Vec<CodeBlockContent>,
}
#[derive(PartialEq, Debug, Clone)]
pub enum InnerCodeBlockType {
If(String),
For(ForLoopInnerCodeBlock),
While(String),
}
#[derive(PartialEq, Debug, Clone)]
pub struct ForLoopInnerCodeBlock {
pub variable_name: String,
pub from: PlayerCommandInput,
pub to: PlayerCommandInput,
}
Каждый блок кода имеет тип (Function, Daemon или Virus) с нужными для его работы параметрами (только у функций есть вектор имён аргументов), а также хранит содержимое его тело в векторе типов CodeBlockContent. Внутренний контент, в свою очередь, может быть либо строками, которые будут парсится ранее упомянутой command_from_string, либо структурами InnerCodeBlock, которые аналогичны CodeBlock, но могут иметь типы If, For или While.
Аналогично случаю с командами, в случае добавления новых сущностей достаточно добавить элементы в перечисления и в ключевых слов в логику парсинга.
Так выглядит IDE в игре
Итоги
Выше я описал лишь небольшой срез проделанной мной работы, помимо этого есть ещё некоторые интересные решения, которые я реализовал в рамках этого проекта (нюансы парсинга, демоны, вирусы, использование ресурсов для запуска кода, древо прокачки в стиле гит, логика обучения и документация), о которых могу рассказать в следующий раз, если будет интерес к этой теме.
Одной из целей игры является поднять навыки программирования у людей и привить любовь к нему. В какой-то степени она уже сейчас достигнута, ведь в процессе разработки я неплохо прокачал свои навыки и по-настоящему полюбил Rust, и теперь стараюсь отдавать ему предпочтение всегда, когда это возможно и имеет смысл. Движок Bevy себя показал крайне хорошо. Да, были ситуации неприятных багов (которые, кстати были пофикшены в следующей же сборке), не совсем удобных решений и неудобной миграции при переходе на новую версию, но!
В контексте разработки видеоигр термин "вижен" (Vision) часто используется для обозначения общего видения или концепции. Это может включать в себя общую идею игры, ее стиль, основные цели и особенности, которые разработчики стремятся воплотить. Вижен-документ в разработке игр может включать в себя описание геймплея, художественного стиля, сюжетных элементов, целевой аудитории, а также другие ключевые моменты, которые определяют общую концепцию игры.
Этот документ служит своеобразным руководством для команды разработчиков, предоставляя им ясное понимание того, какой должна стать игра в результате разработки. Он помогает установить общую направленность и цели проекта, обеспечивая единство в работе всех участников команды.
Если такой документ является основополагающим для разработки любой игры, то почему бы его не использовать при разработке аудио? На самом деле, это довольно распространенный опыт среди опытных разработчиков игр, так как создание аудио-вижена дает нам несколько серьезных преимуществ о которых я расскажу далее.
Таким образом, мы можем дать для аудио-вижена более точное определение - это документ, который соединяет концепцию звучания игры с ее общим видением. В этом документе описываются стиль и атмосфера звучания, а также взаимодействие звуковых элементов с ключевыми механиками. Аудио-вижен определяет основные черты саунд-дизайна, выделяет важные моменты геймплея, где звук играет решающую роль, и обеспечивает согласованность аудиоэлементов с общей концепцией игры.
Эта статья позволит разработчикам игр понять, как аудио-вижен может стать ключом к созданию более эффективного подхода к процессу разработки аудио и предоставлению игрокам более цельного и уникального игрового опыта.
Почему аудио-вижен важен для разработчика игры?
Обеспечение согласованности
Аудио-вижен является мостом между идеями команды разработки и саунд-специалистами. Этот инструмент позволяет создать общее понимание звукового дизайна. Аудио-вижен служит также инструментом для синхронизации ожиданий. Он позволяет донести концепции и идеи звукового дизайна до всех участников процесса, предоставляя общий язык для обсуждения звуковых концепций. Это содействует избежанию недопониманий и уточнению требований еще на ранних стадиях разработки.
Оптимизация бюджета
Одним из важных аспектов аудио-вижена является его влияние на бюджет проекта. Документ помогает определить ключевые части звукового дизайна, на которых следует сосредотачивать ресурсы для достижения максимального эффекта. Оптимизация бюджета через аудио-вижен позволяет распределить ресурсы более эффективно, подчеркивая важные звуковые элементы и уменьшая риск ненужных затрат.
Что включает в себя аудио-вижен?
Для обеспечения достижения всех целей, определенных для аудио-вижена, необходимо детальное исследование различных характеристик, охватывающих звуковой дизайн проекта. Рассмотрим ключевые элементы, которые включаются в аудио-вижен и направлены на достижение высококачественного звукового сопровождения в видеоиграх.
Описания концепции звучания игры
Аудио-вижен начинается с детального описания того, каким образом должна звучать игра в целом. Это включает в себя выделение основных составляющих саунд-дизайна, которые формируют уникальную атмосферу проекта. Определение общей звуковой идентичности игры является важным шагом для создания впечатляющего и запоминающегося звукового опыта.
Определения стиля звучания игры
Аудио-вижен помогает определить стиль звучания игры, включая жанровые особенности, выбор стиля музыки, звуковых эффектов и диалогов. Это создает целостную звуковую картину, которая соответствует общей эстетике и визуальному стилю проекта.
Описания взаимодействия саунд-дизайна с игроком
Аудио-вижен анализирует, как звуковые элементы будут воздействовать на игровой опыт. Это включает в себя подчеркивание ключевых моментов, создание напряжения и активное участие в повествовании. Такой анализ позволяет сориентировать звуковой дизайн на создание максимально вовлекающего опыта для игрока.
Выделения фич саунд-дизайна
Аудио-вижен идентифицирует уникальные аспекты аудио, которые выделяют игру среди других. Выделение таких фич позволяет создать запоминающийся звуковой опыт, который способствует формированию уникального стиля и образа проекта.
Определения наиболее важных частей геймплея
Аудио-вижен выявляет моменты в игре, которые требуют более детальной звуковой проработки, чтобы усилить воздействие на игрока. Он также помогает определить, где можно экономить бюджет, сосредотачиваясь на менее критичных частей звукового дизайна.
Определения способов и методов разработки саунд-дизайна
Включает в себя описание процессов создания и интеграции аудиоэффектов, создания музыки, работы с звуковыми движками и обеспечение согласованности аудио-вижена с общей концепцией игры. Такой подробный анализ позволяет определить, каким образом аудио-вижен будет воплощен в жизнь на различных этапах разработки.
Какие навыки нужны для создания хорошего аудио-вижена?
В мире видеоигр, где опыт игрока, визуал и аудио становятся неразрывно связанными, концепция аудио-вижена видится важным элементом для последующей разработки целостного саунд-дизайна. Наигранность, наслушенность, адаптация аудио-визионерских идей к потребностям проекта, а также понимание игрового дизайна являются существенными для эффективной реализации аудио-вижена.
Во-первых, важную роль играют наигранность и наслушенность. Экспертный разработчик звука должен быть знаком с различными жанрами игр. Это позволяет понимать, какие аспекты звука и музыки влияют на восприятие игрового процесса. Знание и понимание саунд-дизайна успешных проектов помогает разработчику декомпозировать их элементы, извлекая уроки и применяя их в своей работе. Такой подход обогащает опыт разработчика, позволяя создавать аудио, которое не только соответствует техническим стандартам, но и эффективно взаимодействует с игровым миром, обогащая пользовательский опыт.
Во-вторых, существенным фактором для разработчика звука является погружение в процессы и принципы разработки игр. Понимание того, как звук взаимодействует с игроком, а также ожидания игрока от звукового сопровождения, является ключевым элементом. Разработчику важно предвидеть, как различные звуковые приемы будут воздействовать на игрока, мотивировать его к определенным действиям и влиять на общую вовлеченность. Такой подход позволяет создавать не только звуковые эффекты, улучшающие восприятие игровых моментов, но и те, которые согласованно поддерживают геймплейные механики, активно вовлекая игрока в игровой процесс.
И в-третьих, обширный опыт в разработке игрового аудио представляет собой не менее важный компонент для успешного разработчика звука. Этот опыт включает в себя участие в процессах продюсирования проектов, создание аудио ассетов и музыкальных композиций, участие в процессах интеграции в среду разработки, а также глубокое знание звуковых движков. Разносторонний опыт позволяет разработчику более эффективно реагировать на требования проекта, адаптироваться к различным стилям и жанрам игр, а также наилучшим образом воплощать звуковые концепции в жизнь.
Привет пикабу, всегда хотелось стать геймдев разрабом, и вот однажды мы с другом собрались, сидя у бассейна и решили объединить две легендарных механики - тетрис и 2048 в одну. Зацените, чё получилось.
Интересно, что все локации будут генерироваться рандомно, а боссов не удастся победить изучив их паттерн (авторы отмечают, что понадобится нечто большее...). Можно также построить свою базу и сыграть в коопе до 4 человек.
Выход игры планируется этой зимой на ПК и консолях.
Уже довольно продолжительное время работаем над обновлением для Crushed. Приятно видеть как игра преображается и становится лучше с каждой своей версией. На этот раз мы решили сосредоточить свое внимание на крутой и важной фиче − транспорте.
С нуля собрали контроллер для авто. Сделали камеру как в GTA (используя плагин Cinemachine). Все это дело протестили в мультиплеере, и блин, чувствуется все это крайне круто! Сейчас в процессе создание модели, а именно пикапа по референсам старичка Ford F-150 Ranger 1979 года! Уже не терпится выкатить эту фичу и всё обновление, которое в очередной раз улучшит нашу любимую игру.
Уважаю лигу лени, вкратце напомню, что мы делаем текстов-графическую игру в виде современного мобильного приложения. То есть сама концепция игры, не из игростроя, а от мобильных приложений которыми мы пользуемся каждый день, ну там банкинг, такси и всё такое. Открыл, потыкал, закрыл.
Сегодня расскажу немного про механики и как мы ведём документацию.
Так как в игре есть крафт и он эпический. Я завёл ноушен и описал всё что можно, что из чего делается, к чему относится, где добывается и зачем нужен. Выглядит это, как таблица на 400 строк.
Затем были заведены страницы станков, на которы это всё добро крафтится, и уже там залинковано с таблицей, чтоб хоть от туда, хоть отсюда, можно было свести концы с концами.
Часть предметов связаны с локациями, квестами и NPC персонажами. Это всё так же закручивается в ноушене в узелок. Локации связаны с персонажами, те с диалогами, диалоги с квестами, квесты с предметами. Сущий ад.
Диалоги так же описываются в ноушене по каждому персонажу со всеми ответвлениями и ответами ГГ.
В прошлый раз, многие взялись читать тексты со скриншотов, чего я не планировал. Заслуженно получил каментов в духе "В игре, которая базируется на тексте - не должно быть ошибок типа "от туда"." Ну собственно, урок мы не усвоили и написали целую документацию из ошибок с ошибками. То ли будет, когда мы это скодим, муахаха!
Ладно, если без шуток, когда я допишу все диалоги, я найму корректора и редактора. Смысл диалогов сейчас не в их содержании, а в наличии. Они должны отработать ситуацию, взять ГГ и дать ему вектор. Что именно будет в самом диалоге, на данном этапе значения не имеет. Главное, что ГГ выйдет с предметом, квестом, новой открытой локацией или механикой из диалога.
Кстати про механики. Так как в игре эпический крафт говна из говна, задумана механика продажи сего говна любителям говна. У нас всё таки мультиплеер.
Механик торговли аж 4 штуки. Во первых есть Скупщик – главный источник денег в игре, так как они не падают с мобов и ящиков. Прикол его в том, что он покупает что угодно, но только за й монету. В целом можно назвать игру "Инфляция", что будет корректно. На первых порах, денег у игроков не будет совсем. У первых игроков меч будет стоить 3 монеты с рук, что покажется конской ценой. Через год, меч будет стоить 1000 монет, и это будет практически даром.
Вторая механика, призвана покупать, а главное продавать через брокера (возможно не совсем корректно, но другого названия ему я не придумал). Ты открываешь счёт, тебе дают 10 ячеек, ты наваливаешь в них лута по своей цене и он попадает в листинг. В целом такие механики есть в ряде игр, том же ЭлдерСкрол Онлайн. Брокер стрижёт проценты с продаж, изымая монеты из игры.
Если ещё не утомились читать, расскажу про третью, это Блошинный рынок. По факту локальный чат, где можно крикнуть что продаёшь, или чего покупаешь, и поторговать напрямую. Не очень эффективно, но в меру весело.
Четвертая механика "Персональные магазины", там можно продавать предметы которые не берёт Брокер и ещё куча всего, что так быстро одним скрином и не покажешь.
Короче, работа идёт. На меня когда-то подписалось 30-40 человек, после первых постов. Им привет, если они ещё тут.
Телеги нет. Денег лично мне не надо. Но если хотите задонатить школьнице девушке иллюстратору, которая бахнула 400 иконок предметов для этой игры, останавливать вас не стану.