diff --git a/canon/APARTMENT.md b/canon/APARTMENT.md new file mode 100644 index 0000000..28d4b78 --- /dev/null +++ b/canon/APARTMENT.md @@ -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 + +- Карта мира как постер (опц., если ремонт делался под подростка). +- Скейтборд/самокат у стенки (опц.). +- Кот? Канон не определил. diff --git a/canon/HUD.md b/canon/HUD.md new file mode 100644 index 0000000..0c33259 --- /dev/null +++ b/canon/HUD.md @@ -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). diff --git a/canon/STREET.md b/canon/STREET.md new file mode 100644 index 0000000..95d7e1a --- /dev/null +++ b/canon/STREET.md @@ -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). +- Имя бабушки на лавочке (опционально). +- Какой троллейбусный/автобусный маршрут останавливается у дома (для механики «доехать до магазина»). diff --git a/canon/_INDEX.md b/canon/_INDEX.md index 70d8bac..066f193 100644 --- a/canon/_INDEX.md +++ b/canon/_INDEX.md @@ -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, диалог в стиле Шиндовс-окна | средний | ### Сюжетный каркас | Файл | О чём | diff --git a/scenes/components/dialog_ui.tscn b/scenes/components/dialog_ui.tscn index bee84e3..c66a77a 100644 --- a/scenes/components/dialog_ui.tscn +++ b/scenes/components/dialog_ui.tscn @@ -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) diff --git a/scenes/prologue/act1_room.tscn b/scenes/prologue/act1_room.tscn index 0b6858a..60f4479 100644 --- a/scenes/prologue/act1_room.tscn +++ b/scenes/prologue/act1_room.tscn @@ -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"] diff --git a/scripts/prologue/act1.gd b/scripts/prologue/act1.gd index ef5e0a6..fee0dd1 100644 --- a/scripts/prologue/act1.gd +++ b/scripts/prologue/act1.gd @@ -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).") diff --git a/scripts/ui/dialog_manager.gd b/scripts/ui/dialog_manager.gd index c4149d5..bed49eb 100644 --- a/scripts/ui/dialog_manager.gd +++ b/scripts/ui/dialog_manager.gd @@ -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: