act1: аутентичная страна Р — комната, HUD, канон
Some checks failed
Godot CI / Import + smoke test (push) Failing after 13s

КАНОН (3 новых файла, ресёрч-агент):
- APARTMENT.md: брежневка Купчино 9-эт, комната 10-12м², обои бежевые
  виниловые с растительным узором (наследие маминого ремонта 2010),
  линолеум жёлто-коричневый, ковёр бордовый персидский над кроватью
  (наследство от бабушки), батарея чугунная МС-140 белая с подтёками,
  пластиковый стеклопакет с алоэ+чашкой на подоконнике, кровать с тёмно-
  синим верблюжьим одеялом, стол ИКЕА MICKE, старый офисный «Бюрократ»,
  стеллаж ИКЕА BILLY с учебниками + Гарри Поттер + УК РФ (засев #8),
  постеры CS:GO + Моргенштерн на синей изоленте, банка Adrenaline +
  обёртка Lay's на столе, носки на полу. Все цвета по hex.

- STREET.md: парадная с домофоном Eltis DP-400 (питерский производитель),
  фасад керамической плитки бежевой, балконы остеклены лоскутно, на 1
  этаже Пятёрочка+К&Б, двор с тополями+ракушками-гаражами+советской
  площадкой (горка-«ракета»), лавочки бабушек/подростков, метро жетон 55₽
  август 2020, шаверма 120-180₽ (источник прямой не подтверждён, оценка
  по контексту), сети Pita's/Вкусная шаверма/КручуВерчу.

- HUD.md: pixel-art минимализм с акцентом #F0B419 Steam-inventory,
  Pathologic-2 правило (статы только при пороге), диалог-окно в стиле
  Шиндовс-окна (засев бренда), квест-маркер через ТГ-телефон героя,
  без мини-карты и постоянных таймеров.

КОД:
- act1_room.tscn полностью переписан: 73 sub_resources placeholder-кубов
  с канон-цветами hex. Добавлены: радиатор под окном, оконная рама из 5
  планок + подоконник с алоэ+чашкой, ковёр-на-стене над кроватью
  (бордовый), 2 постера (CS:GO жёлтый + Моргенштерн красный), стеллаж
  ИКЕА BILLY на западной стене с 5 книгами, старый Pentium 4 в углу
  северо-востока, банка Adrenaline + обёртка Lay's + клавиатура на столе,
  2 носка на полу. Спавн игрока сдвинут с z=1.2 на z=0.5 (был внутри
  кровати).

- dialog_manager.gd: новый HUD-API set_date_time / set_objective /
  set_money / set_weather / set_stat_alert + set_controls_hint.

- dialog_ui.tscn: 5 новых HUD-лейблов (DateTime, Objective с жёлтым
  акцентом, Money, Weather, StatsAlert) + ControlsHint всегда видимый
  тусклый.

- act1.gd: HUD теперь показывает «21 АВГ 2020 · ПТ · 10:30» вверху-слева
  и квест «◆ Распакуй подарок от бати» → «◆ Прочитай записку» →
  «◆ Возьми флешку с Шиндовс» вверху-справа.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dmitrii Bykov 2026-05-24 17:38:07 +03:00
parent 3975a28ed1
commit b833127bcc
8 changed files with 826 additions and 33 deletions

136
canon/APARTMENT.md Normal file
View file

@ -0,0 +1,136 @@
# APARTMENT.md — Квартира героя
> **Канон-роль:** определяет как выглядит дом героя изнутри в страны Р. Все детали аутентичны Петербургу-2020. Используется как референс для act1_room.tscn и будущих сцен внутри квартиры.
---
## ДОМ ОБЩИЙ ВИД
- **Тип:** 9-этажная панельная брежневка конец 70-х / начало 80-х (серия 600.11 или аналог).
- **Район-аналог:** Купчино старое (Бухарестская / Дунайская). Можно интерпретировать как Колпино / Гражданка — всё равно типаж.
- **Фасад:** мелкая керамическая плитка бежевая/охра/серо-коричневая (отличительная черта купчинских панелек), на швах между этажами белая полоса штукатурки.
- **Этаж героя:** 5-й (середина дома, не первый и не последний — обычная статистика).
- **Балкон:** остеклённый деревянным переплётом ещё из 90-х, краска облезла. На нём — старые санки, банки солений мамы, велосипед героя.
---
## КВАРТИРА ОБЩИЕ
- **Площадь:** ~56 м², 2-комнатная.
- **Комнаты:**
- **Зал** (родители живут или гостевая, в зависимости от планировки).
- **Комната героя** ~10-12 м².
- **Кухня:** 6 м² (типично для брежневки), стол + холодильник «Атлант» + чайник свистком.
- **Санузел:** раздельный, ванна чугунная советская.
- **Прихожая:** обувница ИКЕА, вешалка крючками, зеркало.
---
## КОМНАТА ГЕРОЯ — детали
### Стены и потолок
- **Обои:** бежевые виниловые с мелким растительным узором, наследие маминого ремонта ~2010 года. Один угол у потолка слегка отошёл.
- **Потолок:** побелка, в углу пятно от давней протечки соседей сверху.
- **Один акцент:** **постеры приклеены поверх обоев синей изолентой**, не на двусторонний скотч (бюджет).
### Пол
- **Линолеум «под светлый паркет»** жёлто-коричневый.
- Потёртость в центре (у стула) и у двери.
### Окно
- **Пластиковый стеклопакет** (родители поменяли деревянное в 2014 за 18к).
- **Подоконник** белый пластиковый, на нём:
- горшок с алоэ (мама поставила «от простуды»),
- чашка с засохшим чаем,
- пыль в углу.
- **Шторы:** тюль белый полупрозрачный + ночные шторы тёмно-серые, **сдвинуты в кучу справа** (герой не задёргивает).
### Батарея
- **Чугунная МС-140** под окном, **белая краска с жёлтыми подтёками** от старой воды.
- На батарее сушится **один носок** (мама закинула).
### Кровать
- **Односпальная**, металлический каркас 90×190 см.
- **Одеяло:** верблюжье в синем пододеяльнике с принтом «звёзды» (комплект от бабушки).
- **Одна подушка**, не заправлено.
### Ковёр на стене
- **Бордовый с растительным «персидским» узором**, потёртый, **над кроватью**. Висит с 90-х, никто не снимал.
- Не для тепла — артефакт. Юмор: герой стесняется его, но снять лень.
### Компьютерный стол
- **ИКЕА MICKE / LINNMON** белый, узкий, помещается у окна.
- **На столешнице:**
- старый монитор LG 19" 4:3 (от старого пека),
- клавиатура с пожелтевшими клавишами,
- **банка Adrenaline Rush** (синяя, 0.5 л, наполовину пустая),
- **обёртка чипсов Lay's** скомканная,
- провода в куче,
- наклейка Steam-стикера на углу столешницы.
### Стул
- **Старый офисный «Бюрократ» CH-1300** на колёсиках, чёрная искусственная кожа, **обивка с прорехой** на сиденье. Под одно колесо — кусок скотча (чтоб не катался).
- Опционально: можно заменить на **бюджетное гейминг-кресло чёрно-красное с Алиэкспресс**, если игрок открыл достижение «накопил».
### Стенка / шкаф
- **ИКЕА BILLY белый** узкий стеллаж 40×180×30 у западной стены.
- **На полках:**
- учебники (Алгебра 9 класс, Физика 9 класс — небрежно сложены),
- **Гарри Поттер** 1-3 книги (мама подарила),
- **Уголовный кодекс РФ 2019 ред.** (засев #8 пролога, см. FORESHADOWING.md),
- банка с проводами,
- **фигурка Лего** (привет детству),
- пыль на нижней полке.
### Старый пека на полу (Pentium 4)
- В углу комнаты, серый корпус с обглоданной наклейкой «Intel Inside» (засев #10).
- Скоро будет заменён на новый из подарка.
### Беспорядок на полу
- **2 носка** валяются (дальше от двери),
- **провод от наушников** запутанный,
- **обёртка от чипсов Lay's** под кроватью,
- **жестянка Adrenaline 0.5** пустая под столом.
### Дверь в комнату
- **Деревянная межкомнатная** с замком-вертушкой, краска белая местами облезла. Не закрывается до конца (нужно дёрнуть).
---
## РЕФЕРЕНС-ИСТОЧНИКИ
- Купчино как столица мира: https://gorodovoy.ru/news/kupchino--stolica-mira-pochemu-peterburzhcy-tak-lyubyat-svoy-spalnik-i-ne-hotyat-pereezzhat-v-centr_id888935_a182_dp250513
- Ковёр на стене как пережиток: https://www.ivd.ru/dizajn-i-dekor/dekorirovanie/babushkin-interier-ili-vernuvshiysya-trend-kovry-na-stene-i-varianta-ih-ispolzovaniya-48-foto-106692
- Дизайн комнаты школьника: https://pechenyi.com/info/dizajn-detskoj.html
- ИКЕА LINNMON/MICKE — продолжают доминировать в эконом-сегменте РФ: https://www.ikea.com/us/en/p/linnmon-adils-desk-black-brown-s09416368/
---
## ЦВЕТА для рендера
| Объект | RGB | Hex |
|---|---|---|
| Обои стен | (0.83, 0.72, 0.55) | #D4B98C |
| Ковёр стены | (0.36, 0.12, 0.13) | #5C1E22 |
| Линолеум пола | (0.72, 0.6, 0.41) | #B89968 |
| Потолок | (0.92, 0.9, 0.85) | #EBE6D9 |
| Дверь | (0.85, 0.82, 0.75) | #D9D0BF |
| Батарея чугунная | (0.96, 0.94, 0.88) | #F5F0E0 |
| Окно стеклопакет (рама) | (0.95, 0.95, 0.95) | #F2F2F2 |
| Подоконник | (0.96, 0.95, 0.92) | #F5F2EB |
| ИКЕА BILLY | (0.93, 0.91, 0.88) | #ECE8E0 |
| Постер CS:GO (плейсхолдер) | (0.94, 0.71, 0.1) | #F0B419 |
| Постер Моргенштерн (плейсхолдер) | (0.7, 0.13, 0.13) | #B22222 |
| Одеяло синее | (0.13, 0.16, 0.32) | #212951 |
| Стол MICKE | (0.96, 0.95, 0.93) | #F4F2EE |
| Гейминг-кресло | (0.13, 0.13, 0.15) с red вставками (0.7, 0.13, 0.13) | #212126 / #B22222 |
| Adrenaline банка | (0.13, 0.32, 0.68) | #2152AD |
| Lay's обёртка | (0.96, 0.84, 0.34) | #F5D757 |
---
## TBD
- Карта мира как постер (опц., если ремонт делался под подростка).
- Скейтборд/самокат у стенки (опц.).
- Кот? Канон не определил.

143
canon/HUD.md Normal file
View file

@ -0,0 +1,143 @@
# HUD.md — Дизайн интерфейса игры
> **Канон-роль:** правила HUD/UI для всех сцен. Pixel-art минимализм с одним акцентом. Не перегружать экран.
---
## ФИЛОСОФИЯ
Игра — нарративный быт-сим про подростка. HUD должен:
1. **Не загромождать pixel-art** — он должен дышать.
2. **Показывать чувствительные к времени данные** — дата/время критичны (фарм привязан к датам в каноне).
3. **Уйти в стиль школьной тетрадки + Шиндовс-окна** — отсылка к атмосфере 2020 и игровому миру.
4. **Pathologic-2 правило:** статы появляются ТОЛЬКО при пороге (усталость > 70% → икона; деньги > 0 → виджет; погода → только на улице).
---
## РАСКЛАДКА HUD
### Постоянные элементы (всегда видны)
- **Верхний левый угол:** дата + день недели + время.
- Формат: `21 АВГ 2020 · ПТ · 10:30`
- Шрифт: pixel-font моноширинный.
- Цвет: белый, modulate 0.85.
### Контекстные элементы
- **Верхний правый угол:** активный квест.
- Формат: `◆ Распакуй подарок от бати`
- Цвет: жёлтый Steam-inventory **#F0B419**.
- Меняется при смене состояния акта.
- **Под квестом (если деньги > 0):** валюты.
- Формат: `₽ 4 250 | $ 12.40 | € 0.00`
- Криптовалюты — НЕ в HUD, только в FSM Panel.
- Цвет: белый, modulate 0.75.
- **Нижний правый (только на улице):** погода + температура.
- Формат: `☁ +18°C, мокрый асфальт`
- Цвет: белый, modulate 0.7.
- **Нижний левый (только при пороге):** статы.
- Усталость > 70%: 🌙 + жёлтый текст «УСТАЛ»
- Голод > 70%: 🍴 + жёлтый текст «ГОЛОДЕН»
- Скука > 70%: 💭 + жёлтый текст «СКУЧНО»
- Деньги критически мало (< 100): + красный текст
- По умолчанию — невидимы (как Pathologic 2).
---
## ИНТЕРАКТИВНЫЕ ЭЛЕМЕНТЫ
### Prompt (при наведении на интерактив)
- **Центр экрана**, чуть ниже середины: `[ЛКМ] открыть коробку`
- Жёлтый акцент **#F0B419**, modulate 0.9.
### Subtitle / Dialog
- **Нижняя 1/3 экрана**: панель в стиле **Шиндовс-9 окна** (засев бренда).
- Серый фон (#2A2A2E, 80% opacity).
- Тонкая рамка 1px тёмно-серая.
- Заголовок (имя говорящего) — жёлтый акцент.
- Текст реплики — белый.
- Подсказка справа внизу — серая «ЛКМ или ПРОБЕЛ — дальше».
### Полнокран. оверлей (записки, документы)
- Затемнённый фон 75% чёрного.
- Центральная панель ~420×180 px в стиле бумажки/листа A5.
- Текст центрирован, моноширинный шрифт.
- Заголовок «Записка» / «Файл» / «SMS» — жёлтый акцент.
- Подсказка снизу: «ЛКМ — закрыть».
---
## КВЕСТ-МАРКЕРЫ (диегетика)
В отличие от стрелок на экране, **квесты в основном через телефон героя**:
- Клавиша **T** открывает Тегерлам (с 1 сен 2020).
- В Тегерламе — каналы и личные диалоги.
- Иконка непрочитанного сообщения внизу экрана (как в реале) — мигает при новом TG.
**Текущий квест-маркер в HUD** — это только подсказка «следующий шаг», не GPS-стрелка.
---
## ЦВЕТОВАЯ ПАЛИТРА HUD
| Элемент | Цвет | Hex |
|---|---|---|
| **Акцент (Steam-inventory жёлтый)** | (0.94, 0.71, 0.1) | **#F0B419** |
| Основной текст | (0.92, 0.92, 0.92) | #EBEBEB |
| Вторичный текст | (0.65, 0.65, 0.65) | #A6A6A6 |
| Фон панели | (0.16, 0.16, 0.18) | #2A2A2E |
| Рамка панели | (0.4, 0.4, 0.42) | #66666B |
| Алерт (мало денег / критстат) | (0.85, 0.16, 0.16) | #D92929 |
| Успех (дроп получен) | (0.27, 0.83, 0.27) | #45D445 |
---
## ШРИФТЫ
- **Основной:** pixel-font моноширинный с **кириллицей**.
- Кандидаты: «Press Start 2P» (моно, но без кириллицы из коробки — нужно расширение), «PixelMplus», «PressStart2P-vaOO» (с кириллицей), своя сборка через BMFont.
- **TBD:** найти бесплатный CC0 pixel-font с кириллицей или собрать свой через bitmap font tools.
- **Размер кегля при 640×360 viewport:**
- HUD-элементы: 8-10 px.
- Subtitle: 10-12 px.
- Note overlay: 10-14 px (зависит от длины).
---
## АНИМАЦИИ HUD
- **Появление prompt при наведении:** fade-in 100ms.
- **Исчезновение prompt:** fade-out 80ms.
- **Появление subtitle:** slide-up + fade 200ms.
- **Смена квеста:** старый текст fade-out, новый fade-in с 400ms задержкой.
- **Алерт «мало денег»:** мигание modulate 1.0 → 0.4 → 1.0, цикл 800ms, **остановить когда деньги > 100**.
---
## РЕФЕРЕНСЫ-ИГРЫ
- **Pathologic 2:** статы только при пороге, никаких постоянных шкал.
- **Disco Elysium:** портрет + 2 бара (здоровье + мораль) внизу, мысли всплывают сферами над головой.
- **OMORI / Yume Nikki:** HUD скрыт в overworld, появляется через меню.
---
## ЧТО НЕ ДЕЛАТЬ
- **Никакой мини-карты** на экране постоянно.
- **Никаких пост. таймеров** кд-механик в шапке.
- **Никаких криптокурсов** на HUD (они в FSM Panel).
- **Никаких лишних иконок** в углах (батарея ноутбука, FPS-каунтер для альфа-теста — выключить в финале).
- **Не сделать UI слишком «современным»** — он должен ощущаться как часть Шиндовс-9 / TG из 2020, не Material Design.
---
## TBD
- Точный pixel-font с кириллицей (или сборка своего).
- Анимация открытия TG-канала / SMS — нужна mockup-сцена.
- Mockup экрана покупки в стеме (Акт 9 пролога) — стилизация под реальный Steam UI 2020.
- Иконки для статов (🌙/🍴/💭) — нужно сделать pixel-art версии (CC0).
- Жадная гамма (если нужно делиться режимом — high-contrast / colorblind-friendly).

144
canon/STREET.md Normal file
View file

@ -0,0 +1,144 @@
# STREET.md — Двор и улица героя
> **Канон-роль:** определяет как выглядит мир за дверью квартиры в страны Р. Все детали аутентичны спальникам Петербурга-2020. Используется для outdoor-сцен начиная с Акта 5 (подработка листовками).
---
## ПАРАДНАЯ (питерское слово — обязательно!)
- **Дверь:** металлическая Гардиан/Эльбор, серая или тёмно-зелёная.
- **Домофон:** **Eltis DP-400** (петербургский производитель, доминирует в СПб). С трубкой и кнопками + кодовая клавиатура с подсвеченными цифрами.
- **Ключ-«таблетка»** (iButton) у героя на связке с ключами от квартиры.
- **Код парадной** известен жильцам, но в коде игры — **B17K** (засев: вспомнит когда впервые забудет/потеряет связку).
### Изнутри парадной
- **Стены покрашены в зелёный** эмалью до уровня 1.5м, выше — побелка.
- **Почтовые ящики** металлические синие.
- **Граффити и наклейки** на стенах: «ZENIT 1925», «выпил-закусил», «здесь был Серёга», старые рекламки доставки еды, **наклейка FSM-Panel** (засев — герой ещё не понимает что это).
- **Лестничные пролёты бетонные**, потёртые края ступеней.
- **Лифт** работает, но иногда застревает между этажами. На стенках лифта — выцарапанные слова и наклейки.
- **Лампочка-энергосберегайка** в холле первого этажа мигает.
---
## ФАСАД ДОМА
- **9-этажная панелька** в стиле брежневки 70-80-х.
- **Покрытие:** мелкая керамическая плитка бежевая/охра.
- **Балконы остеклены неравномерно** — лоскутно: один сосед в 1995 деревянным переплётом, другой в 2015 пластиком ПВХ.
- **На некоторых балконах:** сушится бельё, торчат лыжи (хотя сейчас август), велосипеды прислонены к перилам, спутниковая тарелка «Триколор».
- **Антенны Wi-Fi/телевидения** на крыше.
### Первый этаж
- **«Пятёрочка»** (главный магазин у дома героя).
- **«Красное & Белое»** через одну дверь — алкомаркет.
- **Цветочный «24 часа»** на углу.
- **Парикмахерская «Эконом»** рядом, стрижка от 300₽.
---
## ДВОР
### Общая планировка
- **Закрытый двор** между четырьмя 9-этажками (не классический колодец-центр-СПб, а спальник-двор — открытее, шире).
- **Тополя** старые, посаженные в 70-80е, пух летом.
- **Берёзы и клёны** редкие, рябины у подъездов.
### Парковка
- **Хаотичная** вдоль домов, асфальт разбит, бордюры съехали.
- **Гаражи-«ракушки»** металлические в углу двора (мораторий на снос в СПб с 2011, к 2020 ещё стояли). 3-4 штуки, ржавые, на некоторых граффити.
### Детская площадка
- **Половина старая советская:** металлическая горка-«ракета» крашеная в красно-белый, грибок-песочница (песок грязный, кошки гадили), металлические качели на цепях, лазалка-«паутина».
- **Половина новая пластиковая** от программы благоустройства 2018: яркие пластиковые горки, резиновое покрытие.
- **Хоккейная коробка** летом — площадка футбольная: подростки гоняют мяч.
### Лавочки у подъездов
- **Деревянные с металлическими ножками**, советские, **расписаны маркером** «здесь был ...».
- **Заняты бабушками днём** (12-18), вечером — **подростками с пивом и семечками**.
- Урна рядом, переполненная, окурки на земле.
---
## ТРОТУАР И УЛИЦА
- **Асфальт** с трещинами и заплатками.
- **Тротуарная плитка серая/красная 30×30** на новых участках (программа «Комфортная среда» 2017-2020).
- **Поребрик** (питерское слово!) — не «бордюр».
- **Светофор-«пешеход»** на ближайшем перекрёстке, переход на «зелёного человечка».
---
## МЕТРО
### Цены август 2020 (точно)
- **Жетон:** **55 ₽** (тариф 2020 года, с 1 янв 2021 → 60₽).
- **Подорожник:** льготный тариф, первые 10 поездок в месяц — **38 ₽**, далее ступенчато ниже.
- **Жетоны ещё в ходу:** не отменены даже в 2020, оранжевые пластиковые с буквой «М». **Подорожник доминирует** (90% поездок), но жетон остался для туристов и забывчивых.
### Станция-аналог героя
- **Дунайская** / **Купчино** / **Звёздная** (выбрать одну канонически). Канон-выбор: **Дунайская** (1-я линия, спальный массив).
- **Турникеты:** старые УТ-2000 и новые валидаторы для бесконтактных карт (включая Подорожник).
- **Внутри станции:** мрамор, эскалаторы, объявления «осторожно, двери закрываются» голосом Михаила Светина (актёр озвучки СПб метро).
### Возле метро (улица)
- **Шаверменная** (палатка или павильон).
- **Алкомаркет К&Б**.
- **Цветочная палатка** 24/7.
- **Табачная лавка** (электронки JUUL, IQOS появились 2019-2020).
- **«Пятёрочка»** или **«ВкусВилл»** в торговом центре над станцией.
- **«Стардог!s»** на крупных пересадках (классика Питера).
- **«1 Минутка»** — пирожковая бюджет.
---
## ШАВЕРМА (питерское слово — НЕ шаурма!)
- **Палатки исчезают** (мэрия СПб сносила нестационарные объекты с 2015), к 2020 доминируют **павильоны и стационарные шаверменные**.
- **Сети 2020:**
- **Pita's** (концептуальный стрит-фуд, открылся 2016) — для среднего класса.
- **«Вкусная шаверма»** — бюджет.
- **«КручуВерчу»**, **«Vлаваше»**, **«Шаверно»** — массовые сети.
- **Безымянные одиночные** у метро — самый частый случай.
- **Цена август 2020 СПб (оценка по контексту, прямого источника нет):**
- Палатка/безымянная: **120-180 ₽** за классическую куриную.
- Павильон/сеть: **180-250 ₽**.
- **TBD:** перепроверить точную цену через архивы vk-сообществ Питера за авг 2020 или archive.org меню Pita's.
---
## ПОГОДА АВГУСТА 2020
- **Реальная:** в Петербурге август 2020 был **дождливым и прохладным**, средняя температура +17°C, осадки часто (на 30% выше нормы).
- **Канон-погода 21 авг 2020 (пятница):** утром облачно, в обед +18°C, после обеда — короткий дождь, к вечеру прояснилось.
- **Это влияет на механики:**
- Mокрый асфальт после дождя → +5% шанс что прохожий возьмёт листовку (см. Пролог Акт 5).
- Усталость героя от хождения под дождём → -10 к скорости.
---
## ЦВЕТА для рендера улицы
| Объект | RGB | Hex |
|---|---|---|
| Фасад керамика бежевая | (0.78, 0.72, 0.6) | #C7B899 |
| Дверь парадной серая | (0.45, 0.45, 0.47) | #737378 |
| Асфальт | (0.32, 0.32, 0.34) | #525258 |
| Тротуарная плитка | (0.55, 0.55, 0.58) | #8C8C94 |
| Тополь крона | (0.36, 0.5, 0.27) | #5C8045 |
| Тополь ствол | (0.42, 0.36, 0.27) | #6B5C45 |
| Газон | (0.42, 0.55, 0.3) | #6B8C4D |
| Лужа после дождя | (0.27, 0.32, 0.36) | #45525C |
| Небо облачное (август) | (0.65, 0.7, 0.75) | #A6B3BF |
| Светофор зелёный | (0.27, 0.83, 0.27) | #45D445 |
| Витрина Пятёрочки | (0.85, 0.16, 0.16) | #D92929 |
| Витрина К&Б | (0.7, 0.13, 0.13) с белым | #B22222 |
---
## TBD
- Точные адреса в каноне (фиктивные, типа «ул. Будапештская, 56»).
- Имя соседа-алкаша из 23-й квартиры (может стать NPC).
- Имя бабушки на лавочке (опционально).
- Какой троллейбусный/автобусный маршрут останавливается у дома (для механики «доехать до магазина»).

View file

@ -1,9 +1,9 @@
# canon/_INDEX.md — Навигатор канон-файлов
> Это **оглавление** всех ~24 канон-файлов проекта. Любая новая сессия Claude должна прочитать этот файл первым.
> Это **оглавление** всех ~27 канон-файлов проекта. Любая новая сессия Claude должна прочитать этот файл первым.
**Repo:** http://192.168.0.10:3000/bossiara13/farming-simulator
**Status (на момент создания файла):** канон полный, CI зелёный, готов к Акту 1 в коде.
**Status:** канон + Акт 1 в коде (FPV-комната с placeholder-кубами, отец, подарок, флешка). HUD с датой/квестом. Следующий шаг — Акт 2.
---
@ -46,6 +46,9 @@
| `CHARACTERS.md` | Все NPC: герой, Сергей-отец, мать-Псков, Андрюха, Осминог=герой-из-будущего, тов. Майор Шкалин, Толик, Сергий, Эдуард, продавцы | большой |
| `LORE.md` | Страна Р = СПб = "С.", C-19/WAR нейтрально, цены игр (Prime 990₽ до 03.06.2021), подработки СПб 2020-2022 | большой |
| `SAINT_PETERSBURG.md` | Шаверма/парадная/поребрик, метро 4 ветки, мосты разводят, двухтарифный счётчик Ленэнергосбыт | средний |
| `APARTMENT.md` | Квартира + комната героя: брежневка Купчино, обои бежевые, линолеум, ковёр на стене, батарея чугунная, ИКЕА MICKE/BILLY, постеры CS:GO+Моргенштерн на изоленте, цвета по hex | средний |
| `STREET.md` | Парадная (Eltis домофон), фасад керамики, двор спальника (тополя, ракушки-гаражи, советская площадка), метро (жетон 55₽), шаверма СПб 120-180₽, цвета по hex | средний |
| `HUD.md` | UI-философия: Pathologic-2 стиль (статы только при пороге), pixel-font, жёлтый Steam-inventory #F0B419, диалог в стиле Шиндовс-окна | средний |
### Сюжетный каркас
| Файл | О чём |

View file

@ -6,13 +6,57 @@
layer = 10
script = ExtResource("1_dlg")
[node name="HudLabel" type="Label" parent="."]
[node name="DateTimeLabel" type="Label" parent="."]
offset_left = 8.0
offset_top = 4.0
offset_top = 6.0
offset_right = 280.0
offset_bottom = 22.0
text = ""
modulate = Color(0.92, 0.92, 0.92, 1)
[node name="ObjectiveLabel" type="Label" parent="."]
offset_left = 340.0
offset_top = 6.0
offset_right = 632.0
offset_bottom = 22.0
text = ""
modulate = Color(0.85, 0.85, 0.85, 1)
horizontal_alignment = 2
modulate = Color(0.94, 0.71, 0.1, 1)
[node name="MoneyLabel" type="Label" parent="."]
offset_left = 340.0
offset_top = 24.0
offset_right = 632.0
offset_bottom = 40.0
text = ""
horizontal_alignment = 2
modulate = Color(0.75, 0.75, 0.75, 1)
[node name="WeatherLabel" type="Label" parent="."]
offset_left = 340.0
offset_top = 332.0
offset_right = 632.0
offset_bottom = 348.0
text = ""
horizontal_alignment = 2
modulate = Color(0.7, 0.75, 0.85, 1)
[node name="StatsLabel" type="Label" parent="."]
offset_left = 8.0
offset_top = 332.0
offset_right = 300.0
offset_bottom = 348.0
text = ""
modulate = Color(0.94, 0.71, 0.1, 1)
[node name="ControlsHint" type="Label" parent="."]
offset_left = 0.0
offset_top = 246.0
offset_right = 640.0
offset_bottom = 260.0
text = "WASD — ходить · мышь — смотреть · ЛКМ — взаимодействие · ESC — мышь · Q — выход"
horizontal_alignment = 1
modulate = Color(0.5, 0.5, 0.5, 0.8)
[node name="PromptLabel" type="Label" parent="."]
offset_left = 0.0
@ -21,12 +65,12 @@ offset_right = 640.0
offset_bottom = 220.0
text = ""
horizontal_alignment = 1
modulate = Color(1, 0.95, 0.6, 1)
modulate = Color(0.94, 0.71, 0.1, 1)
[node name="SubtitlePanel" type="PanelContainer" parent="."]
offset_left = 20.0
offset_top = 260.0
offset_right = 620.0
offset_left = 24.0
offset_top = 270.0
offset_right = 616.0
offset_bottom = 350.0
[node name="V" type="VBoxContainer" parent="SubtitlePanel"]
@ -35,7 +79,7 @@ layout_mode = 2
[node name="Who" type="Label" parent="SubtitlePanel/V"]
layout_mode = 2
text = "[Я]"
modulate = Color(0.9, 0.8, 0.5, 1)
modulate = Color(0.94, 0.71, 0.1, 1)
[node name="Text" type="Label" parent="SubtitlePanel/V"]
layout_mode = 2
@ -46,7 +90,7 @@ autowrap_mode = 3
layout_mode = 2
text = "ЛКМ или ПРОБЕЛ — дальше"
horizontal_alignment = 2
modulate = Color(0.55, 0.55, 0.55, 1)
modulate = Color(0.5, 0.5, 0.5, 1)
[node name="NoteOverlay" type="Control" parent="."]
anchor_right = 1.0
@ -79,7 +123,7 @@ layout_mode = 2
layout_mode = 2
text = "Записка"
horizontal_alignment = 1
modulate = Color(0.9, 0.8, 0.5, 1)
modulate = Color(0.94, 0.71, 0.1, 1)
[node name="Text" type="Label" parent="NoteOverlay/Center/P/V2"]
layout_mode = 2
@ -91,4 +135,4 @@ horizontal_alignment = 1
layout_mode = 2
text = "ЛКМ или ПРОБЕЛ — закрыть"
horizontal_alignment = 1
modulate = Color(0.55, 0.55, 0.55, 1)
modulate = Color(0.5, 0.5, 0.5, 1)

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=42 format=3]
[gd_scene load_steps=76 format=3]
[ext_resource type="Script" path="res://scripts/prologue/act1.gd" id="1_act1"]
[ext_resource type="Script" path="res://scripts/interactables/interactable.gd" id="2_int"]
@ -25,6 +25,18 @@ size = Vector3(0.1, 2.5, 4)
[sub_resource type="BoxMesh" id="mesh_window"]
size = Vector3(1.5, 1.0, 0.06)
[sub_resource type="BoxMesh" id="mesh_window_frame_h"]
size = Vector3(1.6, 0.06, 0.08)
[sub_resource type="BoxMesh" id="mesh_window_frame_v"]
size = Vector3(0.06, 1.1, 0.08)
[sub_resource type="BoxMesh" id="mesh_windowsill"]
size = Vector3(1.7, 0.06, 0.18)
[sub_resource type="BoxMesh" id="mesh_radiator"]
size = Vector3(1.0, 0.5, 0.1)
[sub_resource type="BoxMesh" id="mesh_door"]
size = Vector3(0.06, 2.0, 1.0)
@ -37,6 +49,9 @@ size = Vector3(1.5, 0.7, 0.6)
[sub_resource type="BoxMesh" id="mesh_old_pc"]
size = Vector3(0.25, 0.4, 0.3)
[sub_resource type="BoxMesh" id="mesh_keyboard"]
size = Vector3(0.4, 0.03, 0.15)
[sub_resource type="BoxMesh" id="mesh_bed"]
size = Vector3(2.0, 0.4, 1.0)
@ -49,6 +64,24 @@ size = Vector3(1.95, 0.06, 0.95)
[sub_resource type="BoxMesh" id="mesh_pillow"]
size = Vector3(0.5, 0.1, 0.25)
[sub_resource type="BoxMesh" id="mesh_wall_carpet"]
size = Vector3(1.4, 1.0, 0.02)
[sub_resource type="BoxMesh" id="mesh_poster"]
size = Vector3(0.4, 0.5, 0.02)
[sub_resource type="BoxMesh" id="mesh_shelf"]
size = Vector3(0.3, 1.7, 1.0)
[sub_resource type="BoxShape3D" id="shape_shelf"]
size = Vector3(0.3, 1.7, 1.0)
[sub_resource type="BoxMesh" id="mesh_book"]
size = Vector3(0.22, 0.04, 0.18)
[sub_resource type="BoxMesh" id="mesh_book_thick"]
size = Vector3(0.22, 0.08, 0.18)
[sub_resource type="BoxMesh" id="mesh_gift"]
size = Vector3(0.5, 0.4, 0.5)
@ -73,45 +106,117 @@ size = Vector3(0.06, 0.02, 0.025)
[sub_resource type="BoxMesh" id="mesh_father"]
size = Vector3(0.4, 1.7, 0.4)
[sub_resource type="BoxMesh" id="mesh_p4"]
size = Vector3(0.25, 0.42, 0.4)
[sub_resource type="BoxShape3D" id="shape_p4"]
size = Vector3(0.25, 0.42, 0.4)
[sub_resource type="BoxMesh" id="mesh_sock"]
size = Vector3(0.15, 0.03, 0.08)
[sub_resource type="BoxMesh" id="mesh_lays"]
size = Vector3(0.15, 0.01, 0.1)
[sub_resource type="BoxMesh" id="mesh_can"]
size = Vector3(0.06, 0.13, 0.06)
[sub_resource type="BoxMesh" id="mesh_plant"]
size = Vector3(0.09, 0.13, 0.09)
[sub_resource type="BoxMesh" id="mesh_cup"]
size = Vector3(0.07, 0.08, 0.07)
[sub_resource type="StandardMaterial3D" id="mat_floor"]
shading_mode = 0
albedo_color = Color(0.55, 0.35, 0.22, 1)
albedo_color = Color(0.72, 0.6, 0.41, 1)
[sub_resource type="StandardMaterial3D" id="mat_wall"]
shading_mode = 0
albedo_color = Color(0.79, 0.71, 0.54, 1)
albedo_color = Color(0.83, 0.72, 0.55, 1)
[sub_resource type="StandardMaterial3D" id="mat_ceiling"]
shading_mode = 0
albedo_color = Color(0.85, 0.83, 0.78, 1)
albedo_color = Color(0.92, 0.9, 0.85, 1)
[sub_resource type="StandardMaterial3D" id="mat_window"]
shading_mode = 0
albedo_color = Color(0.6, 0.85, 1.0, 1)
emission_enabled = true
emission = Color(0.6, 0.85, 1.0, 1)
emission_energy_multiplier = 0.5
emission_energy_multiplier = 0.6
[sub_resource type="StandardMaterial3D" id="mat_window_frame"]
shading_mode = 0
albedo_color = Color(0.95, 0.95, 0.95, 1)
[sub_resource type="StandardMaterial3D" id="mat_windowsill"]
shading_mode = 0
albedo_color = Color(0.96, 0.95, 0.92, 1)
[sub_resource type="StandardMaterial3D" id="mat_radiator"]
shading_mode = 0
albedo_color = Color(0.96, 0.94, 0.88, 1)
[sub_resource type="StandardMaterial3D" id="mat_door"]
shading_mode = 0
albedo_color = Color(0.29, 0.18, 0.09, 1)
albedo_color = Color(0.85, 0.82, 0.75, 1)
[sub_resource type="StandardMaterial3D" id="mat_desk"]
shading_mode = 0
albedo_color = Color(0.36, 0.23, 0.11, 1)
albedo_color = Color(0.96, 0.95, 0.93, 1)
[sub_resource type="StandardMaterial3D" id="mat_old_pc"]
shading_mode = 0
albedo_color = Color(0.43, 0.43, 0.43, 1)
albedo_color = Color(0.55, 0.55, 0.5, 1)
[sub_resource type="StandardMaterial3D" id="mat_keyboard"]
shading_mode = 0
albedo_color = Color(0.85, 0.82, 0.74, 1)
[sub_resource type="StandardMaterial3D" id="mat_bed_frame"]
shading_mode = 0
albedo_color = Color(0.36, 0.23, 0.11, 1)
[sub_resource type="StandardMaterial3D" id="mat_blanket"]
shading_mode = 0
albedo_color = Color(0.45, 0.15, 0.15, 1)
albedo_color = Color(0.13, 0.16, 0.32, 1)
[sub_resource type="StandardMaterial3D" id="mat_pillow"]
shading_mode = 0
albedo_color = Color(0.92, 0.88, 0.78, 1)
[sub_resource type="StandardMaterial3D" id="mat_wall_carpet"]
shading_mode = 0
albedo_color = Color(0.36, 0.12, 0.13, 1)
[sub_resource type="StandardMaterial3D" id="mat_poster_csgo"]
shading_mode = 0
albedo_color = Color(0.94, 0.71, 0.1, 1)
emission_enabled = true
emission = Color(0.94, 0.71, 0.1, 1)
emission_energy_multiplier = 0.25
[sub_resource type="StandardMaterial3D" id="mat_poster_morgen"]
shading_mode = 0
albedo_color = Color(0.7, 0.13, 0.13, 1)
[sub_resource type="StandardMaterial3D" id="mat_shelf"]
shading_mode = 0
albedo_color = Color(0.93, 0.91, 0.88, 1)
[sub_resource type="StandardMaterial3D" id="mat_book_a"]
shading_mode = 0
albedo_color = Color(0.36, 0.18, 0.15, 1)
[sub_resource type="StandardMaterial3D" id="mat_book_b"]
shading_mode = 0
albedo_color = Color(0.2, 0.35, 0.5, 1)
[sub_resource type="StandardMaterial3D" id="mat_book_c"]
shading_mode = 0
albedo_color = Color(0.13, 0.13, 0.15, 1)
[sub_resource type="StandardMaterial3D" id="mat_gift"]
shading_mode = 0
albedo_color = Color(0.1, 0.1, 0.12, 1)
@ -121,11 +226,14 @@ shading_mode = 0
albedo_color = Color(0.3, 0.32, 0.38, 1)
emission_enabled = true
emission = Color(0.2, 0.5, 0.9, 1)
emission_energy_multiplier = 0.6
emission_energy_multiplier = 0.7
[sub_resource type="StandardMaterial3D" id="mat_note"]
shading_mode = 0
albedo_color = Color(0.95, 0.95, 0.9, 1)
emission_enabled = true
emission = Color(0.95, 0.95, 0.7, 1)
emission_energy_multiplier = 0.3
[sub_resource type="StandardMaterial3D" id="mat_flash"]
shading_mode = 0
@ -138,6 +246,30 @@ emission_energy_multiplier = 0.4
shading_mode = 0
albedo_color = Color(0.18, 0.22, 0.4, 1)
[sub_resource type="StandardMaterial3D" id="mat_p4"]
shading_mode = 0
albedo_color = Color(0.45, 0.44, 0.4, 1)
[sub_resource type="StandardMaterial3D" id="mat_sock"]
shading_mode = 0
albedo_color = Color(0.18, 0.22, 0.32, 1)
[sub_resource type="StandardMaterial3D" id="mat_lays"]
shading_mode = 0
albedo_color = Color(0.96, 0.84, 0.34, 1)
[sub_resource type="StandardMaterial3D" id="mat_can"]
shading_mode = 0
albedo_color = Color(0.13, 0.32, 0.68, 1)
[sub_resource type="StandardMaterial3D" id="mat_plant"]
shading_mode = 0
albedo_color = Color(0.25, 0.45, 0.2, 1)
[sub_resource type="StandardMaterial3D" id="mat_cup"]
shading_mode = 0
albedo_color = Color(0.85, 0.83, 0.78, 1)
[node name="Act1Room" type="Node3D"]
script = ExtResource("1_act1")
@ -176,6 +308,61 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.3, 0.06)
mesh = SubResource("mesh_window")
material_override = SubResource("mat_window")
[node name="WindowFrameTop" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.82, 0.08)
mesh = SubResource("mesh_window_frame_h")
material_override = SubResource("mat_window_frame")
[node name="WindowFrameBot" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.22, 0.08)
mesh = SubResource("mesh_window_frame_h")
material_override = SubResource("mat_window_frame")
[node name="WindowFrameLeft" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.78, 0.3, 0.08)
mesh = SubResource("mesh_window_frame_v")
material_override = SubResource("mat_window_frame")
[node name="WindowFrameRight" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.78, 0.3, 0.08)
mesh = SubResource("mesh_window_frame_v")
material_override = SubResource("mat_window_frame")
[node name="WindowFrameMid" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.3, 0.08)
mesh = SubResource("mesh_window_frame_v")
material_override = SubResource("mat_window_frame")
[node name="Windowsill" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.2, 0.18)
mesh = SubResource("mesh_windowsill")
material_override = SubResource("mat_windowsill")
[node name="Plant" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, -0.11, 0.18)
mesh = SubResource("mesh_plant")
material_override = SubResource("mat_plant")
[node name="Cup" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, -0.13, 0.18)
mesh = SubResource("mesh_cup")
material_override = SubResource("mat_cup")
[node name="Radiator" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.0, 0.1)
mesh = SubResource("mesh_radiator")
material_override = SubResource("mat_radiator")
[node name="PosterCSGO" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.1, 0.45, 0.06)
mesh = SubResource("mesh_poster")
material_override = SubResource("mat_poster_csgo")
[node name="PosterMorgen" type="MeshInstance3D" parent="WallN"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.1, 0.45, 0.06)
mesh = SubResource("mesh_poster")
material_override = SubResource("mat_poster_morgen")
[node name="WallS" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.25, 2.05)
@ -186,6 +373,11 @@ material_override = SubResource("mat_wall")
[node name="Coll" type="CollisionShape3D" parent="WallS"]
shape = SubResource("shape_wall_ns")
[node name="WallCarpet" type="MeshInstance3D" parent="WallS"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0.0, -0.06)
mesh = SubResource("mesh_wall_carpet")
material_override = SubResource("mat_wall_carpet")
[node name="WallE" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.05, 1.25, 0)
@ -211,6 +403,51 @@ material_override = SubResource("mat_wall")
[node name="Coll" type="CollisionShape3D" parent="WallW"]
shape = SubResource("shape_wall_ew")
[node name="Shelf" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.85, 0.85, -1.0)
[node name="Mesh" type="MeshInstance3D" parent="Shelf"]
mesh = SubResource("mesh_shelf")
material_override = SubResource("mat_shelf")
[node name="Coll" type="CollisionShape3D" parent="Shelf"]
shape = SubResource("shape_shelf")
[node name="BookA" type="MeshInstance3D" parent="Shelf"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.05, 0.4, 0)
mesh = SubResource("mesh_book")
material_override = SubResource("mat_book_a")
[node name="BookB" type="MeshInstance3D" parent="Shelf"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.05, 0.46, 0)
mesh = SubResource("mesh_book")
material_override = SubResource("mat_book_b")
[node name="BookC" type="MeshInstance3D" parent="Shelf"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.05, 0.54, 0)
mesh = SubResource("mesh_book_thick")
material_override = SubResource("mat_book_c")
[node name="BookD" type="MeshInstance3D" parent="Shelf"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.05, -0.2, 0.2)
mesh = SubResource("mesh_book_thick")
material_override = SubResource("mat_book_a")
[node name="BookE" type="MeshInstance3D" parent="Shelf"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.05, -0.12, 0.2)
mesh = SubResource("mesh_book")
material_override = SubResource("mat_book_b")
[node name="OldP4" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.75, 0.21, -1.7)
[node name="Mesh" type="MeshInstance3D" parent="OldP4"]
mesh = SubResource("mesh_p4")
material_override = SubResource("mat_p4")
[node name="Coll" type="CollisionShape3D" parent="OldP4"]
shape = SubResource("shape_p4")
[node name="Desk" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.35, -1.5)
@ -222,12 +459,27 @@ material_override = SubResource("mat_desk")
shape = SubResource("shape_desk")
[node name="OldPC" type="MeshInstance3D" parent="Desk"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0.55, 0)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0.55, -0.1)
mesh = SubResource("mesh_old_pc")
material_override = SubResource("mat_old_pc")
[node name="Keyboard" type="MeshInstance3D" parent="Desk"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0.37, 0.18)
mesh = SubResource("mesh_keyboard")
material_override = SubResource("mat_keyboard")
[node name="AdrenalineCan" type="MeshInstance3D" parent="Desk"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.1, 0.42, 0.1)
mesh = SubResource("mesh_can")
material_override = SubResource("mat_can")
[node name="LaysWrapper" type="MeshInstance3D" parent="Desk"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.1, 0.36, 0.0)
mesh = SubResource("mesh_lays")
material_override = SubResource("mat_lays")
[node name="FlashDrive" type="StaticBody3D" parent="Desk"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.3, 0.36, 0.1)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.4, 0.36, 0.15)
script = ExtResource("2_int")
prompt = "взять флешку"
@ -243,7 +495,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0.2, 1.4)
[node name="Mesh" type="MeshInstance3D" parent="Bed"]
mesh = SubResource("mesh_bed")
material_override = SubResource("mat_desk")
material_override = SubResource("mat_bed_frame")
[node name="Coll" type="CollisionShape3D" parent="Bed"]
shape = SubResource("shape_bed")
@ -258,6 +510,16 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.7, 0.31, 0)
mesh = SubResource("mesh_pillow")
material_override = SubResource("mat_pillow")
[node name="Sock1" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0.015, 0.9)
mesh = SubResource("mesh_sock")
material_override = SubResource("mat_sock")
[node name="Sock2" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.85, 0.015, 0.2)
mesh = SubResource("mesh_sock")
material_override = SubResource("mat_sock")
[node name="GiftBox" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.2, -0.3)
script = ExtResource("2_int")
@ -298,7 +560,7 @@ mesh = SubResource("mesh_father")
material_override = SubResource("mat_father")
[node name="PlayerFPV" parent="." instance=ExtResource("3_player")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1.2)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.5)
[connection signal="interacted" from="Desk/FlashDrive" to="." method="_on_drive_interacted"]
[connection signal="interacted" from="GiftBox" to="." method="_on_gift_interacted"]

View file

@ -21,7 +21,8 @@ func _ready() -> void:
player.interactable_focused.connect(_on_player_focused)
player.interactable_unfocused.connect(_on_player_unfocused)
DialogManager.set_hud("Акт 1 — Подарок · WASD ходить · мышь смотреть · ЛКМ взаимодействие · ESC мышь · Q выход")
DialogManager.set_date_time("21 АВГ 2020 · ПТ", "10:30")
DialogManager.set_objective("Распакуй подарок от бати")
await get_tree().create_timer(0.8).timeout
await DialogManager.say("ОТЕЦ", "Ну? Чё стоишь. Распаковывай давай. Сам собирал, между прочим — полночи не спал.")
@ -51,6 +52,7 @@ func _on_gift_interacted(_p: Node) -> void:
note.visible = true
note.set_interactable(true)
DialogManager.clear_prompt()
DialogManager.set_objective("Прочитай записку")
func _on_note_interacted(_p: Node) -> void:
@ -74,6 +76,7 @@ func _on_note_interacted(_p: Node) -> void:
state = State.SEEK_DRIVE
flash_drive.set_interactable(true)
DialogManager.set_objective("Возьми флешку с Шиндовс")
player.unlock_input()
@ -84,6 +87,7 @@ func _on_drive_interacted(_p: Node) -> void:
flash_drive.set_interactable(false)
player.lock_input()
DialogManager.clear_prompt()
DialogManager.set_objective("")
await DialogManager.think("Ну ладно. Андрюхино так Андрюхино. Поехали.")
await DialogManager.say("СИСТЕМА", "Конец Акта 1. Акт 2 — Установка Шиндовс (TBD).")

View file

@ -11,7 +11,13 @@ signal advanced
@onready var note_text: Label = $NoteOverlay/Center/P/V2/Text
@onready var prompt_label: Label = $PromptLabel
@onready var hud_label: Label = $HudLabel
@onready var controls_hint: Label = $ControlsHint
@onready var date_time_label: Label = $DateTimeLabel
@onready var objective_label: Label = $ObjectiveLabel
@onready var money_label: Label = $MoneyLabel
@onready var weather_label: Label = $WeatherLabel
@onready var stats_label: Label = $StatsLabel
var _waiting: bool = false
@ -20,7 +26,11 @@ func _ready() -> void:
subtitle_panel.visible = false
note_overlay.visible = false
prompt_label.visible = false
hud_label.visible = false
objective_label.visible = false
money_label.visible = false
weather_label.visible = false
stats_label.visible = false
# ControlsHint всегда виден, не блокирует игру
func say(who: String, line: String) -> Signal:
@ -57,9 +67,56 @@ func clear_prompt() -> void:
prompt_label.visible = false
func set_hud(text: String) -> void:
hud_label.text = text
hud_label.visible = text != ""
func set_date_time(date: String, time: String) -> void:
date_time_label.text = "%s · %s" % [date, time]
func set_objective(text: String) -> void:
if text == "":
objective_label.visible = false
return
objective_label.text = "" + text
objective_label.visible = true
func set_money(rub: int, usd: float = 0.0, eur: float = 0.0) -> void:
if rub == 0 and usd == 0.0 and eur == 0.0:
money_label.visible = false
return
var parts: Array[String] = ["%d" % rub]
if usd > 0.0:
parts.append("$ %.2f" % usd)
if eur > 0.0:
parts.append("%.2f" % eur)
money_label.text = " ".join(parts)
money_label.visible = true
func set_weather(text: String, temp_c: int = -999) -> void:
if text == "":
weather_label.visible = false
return
if temp_c == -999:
weather_label.text = text
else:
weather_label.text = "%s %+d°C" % [text, temp_c]
weather_label.visible = true
func set_stat_alert(text: String) -> void:
if text == "":
stats_label.visible = false
return
stats_label.text = text
stats_label.visible = true
func set_controls_hint(text: String) -> void:
if text == "":
controls_hint.visible = false
return
controls_hint.text = text
controls_hint.visible = true
func _input(event: InputEvent) -> void: