Files
2026-10-25 18:05:36 +03:00

18 KiB
Raw Permalink Blame History

PEAK HOUR — GDD (компактная сводка v1.2)

Статус: компактная сводка правил и чисел из постановки задачи + решений DECISIONS.md (ссылки Dxx). Версия v1.2 (25.10.2026) добавляет решения D18–D25 и не отменяет D01–D17, если ниже не сказано иное. Godot 4.7.2 → HTML5 (Web, no threads), RU-only, окно 1920×1080, логический viewport 1280×720 (canvas_items/keep/fractional), 4 человека, джем FEIS, дедлайн 26.10.2026 23:59 Minsk.

1–2. Обзор и платформа

Менеджер приёма/отправки файлов: дежурный узла обрабатывает пакеты, запросы клиентов, канал и атаки в течение одной смены. Ограничения: окно 1920×1080, логический viewport 1280×720 (canvas_items, keep, fractional), nearest, RU-only, Web no-threads (без Thread/блокирующего IO), шрифт Handjet (D15). UI v2 — «Kaleidos»: тёплая бумага, 1 px контуры, мягкие тени и бирюзовый акцент (D18).

3. Структура смены

Забег конечный, 9 игровых часов: Prep (подготовка) → Hour → итоги часа; после 9-го — победа и итоги забега. Досрочное поражение — SLA ≤ 0 (сразу итоги забега). «Конец забега по складу» — страховочный механизм (см. §16), тоже итоги забега. Магазин открывается с часа 2 (в подготовке после часа 1) и скрыт во время часа (D23).

4. Файлы и типы

4 типа файлов: текст (text), звук (sound), фото (photo), видео (video). Каждый с полями name_ru, ext, icon, recv_time, send_time, recv_fee, base_pay, weight, minigame_coeff, sla_loss — значения в data/balance.json. Перед отправкой запроса качество определяется заглушкой quality = 1.0; кнопка «Переделать» не даёт бонусов (D17). «Самый сложный тип» заменён средним коэффициентом (см. выбор мини-игры, п. 8.4/10). Потеря пакета бьёт по SLA по типу: text 2, sound 4, photo 8, video 16 (D19).

5. Папки и секции

Файлы лежат в папках (список папок по умолчанию — names_ru.json), папки сгруппированы в секции; секции докупаются в магазине (D13). Обычные файлы удаляются только в подготовке (долгое удержание/ПКМ); зловредные — в любой фазе (D02). «Уничтожить содержимое» папки реально удаляет файлы после подтверждения и снимает 5 SLA; пустая папка — без штрафа (D26).

6. Буфер приёма

Буфер = 4 + 2×уровня апгрейда буфера, максимум 8 (D05). Пакет тянут по таймеру в папку; таймеры пакетов в буфере идут только когда нет модалок (D03).

7. Запросы

Карточка запроса показывает имя требуемого файла (до 12 симв.) и папку, а не только иконку типа; required — конкретные id (D01). Файл может числиться в required нескольких запросов, но attached — только одном; второй запрос видит его серым; при failed файла все запросы, где он required, отменяются со штрафом (D06). В окне «Отправка» максимум 4 видимых карточки; 5-й и далее — скролл, карточки высотой 56 px (D05).

8. Meter/фазы и таймеры

Все фазы (приём, отправка, соединение, мини-игра, атаки) — на едином Clock/HourDirector.tick(delta); пауза флагами (см. IMPLEMENTATION.md). Полный буфер останавливает спавн приёма; открытые модалки/панели — останавливают спавн приёма и таймеры пакетов, но таймер активного запроса продолжается (D03). delta = min(delta, 0.1), авто-пауза при потере фокуса окна, макс FPS 60 (D11).

Таймеры пакетов/запросов с grace первых часов: h1 1.5, h2 1.35, h3 1.2, h4+ 1.0; формула (base − 0.5×(h−1))×grace + 4×timer_level (D20). Итоговые значения:

Час Пакет, с Запрос, с
1 30 45
2 26.325 39.825
3 22.8 34.8
4 18.5 28.5
5–9 18 → 16 28 → 26

8.4. Мини-игры запросов (правило выбора)

coeff = {text:1.0, sound:2.0, photo:3.0, video:4.0}
difficulty = sum(coeff(required)) / n     # средний коэффициент
пороги: <1.5 → text, <2.5 → sound, <3.5 → photo, иначе → video
MiniGame.start(type, difficulty)

9. Канал

Один общий ресурс для отправок. Фон и занятые слоты канал не грузят: idle load = 0, в нагрузку входят только активные передачи (loading/ sending). Формула (D21):

load = Σ weight(active_transfers)
factor = max(1.0, load / CHANNEL_CAPACITY)
CHANNEL_CAPACITY = 80 + 25×channel_level
actual_time = base_time × factor

Апгрейд «Канал +25» (магазин, ×4, D13/D21) увеличивает capacity. Полные параметры — data/balance.json → channel.

10. Мини-игры (детали)

Мини-игра — модалка; тип определяется правилом п. 8.4 (коэффициенты text 1.0 / sound 2.0 / photo 3.0 / video 4.0, средняя difficulty, пороги <1.5/<2.5/<3.5/иначе). MiniGame.start(type, difficulty). Типы: text — h1, sound — h2, photo/video — h3+; продвинутые мини-игры — мета complete_run, контента пока нет (D23). Esc в мини-игре — no-op (D10).

11. Полоска соединения

W = clamp(0.30 − 0.005×(hour−1) − 0.005×successes + 0.05×zone_upgrade_level, 0.18, 0.36); скорости палочек 440/340/280 px/с; окна попадания ~130–200 мс; апгрейд зоны учтён в формуле с кап 0.36 (D04). W — единственный источник правды по зоне; других формул зоны нет (D05). Esc в панели соединения — отмена: слот освобождается, запрос остаётся (D10). Промах закрывает полоску: автоповтора нет, нужно снова нажать «Соединиться». connected выставляется только после успешного прохождения полоски (D22).

12. SLA и штрафы

Старт забега: SLA 128 / 200 (D19). Прирост: приём +0.5, отправка +1, отражённая атака +1 (D12). Потеря пакета — по типу: text 2, sound 4, photo 8, video 16 (D19). Отдельная таблица штрафов атак (D07): мусор −5, DDoS −15, фишинг −10, шифровальщик −10. Таймаут и подобные штрафы масштабируются: −(10 + 2×hour) (D12).

13. Экономика

Ожидаемый доход/час ≈ 500 / 800 / 1200 / 1800 / 2200 для часов 1 / 2 / 3 / 5 / 9 (D12). Цены магазина подняты так, что полный выкуп реалистичен к часу 8–9. Таблица сложности останавливается на часе 8; дальше те же значения +5 % к скорости спавна каждые 2 часа (D12).

14. Магазин

10 позиций (D13 + D19): 3-й слот (250), 4-й слот (450), буфер +2 (200, ×2), таймер пакетов +4 с (350, ×3), зона +5 % (300, ×3), канал +25 (250, ×4), секция (300, ×5), поиск (250), щит (400), SLA +24 (300, ×3). Сканер и автосортировка — резерв (в прототип не входят). Открытия (D23): магазин — с часа 2; поиск — мета survive_hour_3; щит — мета survive_hour_5; в час магазин скрыт. Крестика у магазина нет: закрытие — «Закрыть» или Esc.

15. Save

Сохранение между часами (SaveManager, без секретов, локально). В Web — IndexedDB (user://save.json). Мета-открытия (meta_unlocks) сохраняются между забегами: survive_hour_3 → поиск, survive_hour_5 → щит, complete_run → продвинутые мини-игры (D23). Награды выдаются постепенно: после 3-го, 5-го и 9-го часа; Game.run_meta_awards копит открытия забега, итоги показывают «ОТКРЫТО: …».

16. Окончание забега

Победа — отработаны все 9 часов, затем итоги забега. Поражение — SLA ≤ 0 (смена не отработана), экран итогов. Переполнение склада за 9 часов недостижимо; механизм «конец забега по складу» остаётся как страховка (не основной конец): поражение, но пройденные 30+ часов засчитываются — отметка в итоговом отчёте (D02).

17. Состояния

Флаги, а не enum (D09):

  • FileItem.location ∈ registry/folder/attached/locked/malicious/failed, attached_request, malicious_kind, lock_until;
  • Request.slot_reserved, Request.connected, Request.minigame_active. Таблица переходов по таймерам (потеря таймера в приёме/соединении/мини-игре) — docs/IMPLEMENTATION.md.

18. Esc и паузирование (D10)

Час — пауза; мини-игра — no-op; панель соединения — отмена (слот свободен, запрос остаётся); закрытие модалок — кнопкой/таймаутом. Магазин закрывается «Закрыть» или Esc, без крестика (D24). Esc на итогах забега ведёт в главное меню (D26).

19. Тексты UI

Все строки игрока берутся из data/strings_ru.json, ключи btn.*, msg.*, ui.*, shop.*, attack.* (+ итаковые/панные/подсказки). Нет оскорблений, русский язык, никакого мата.

20. Tells и читаемость

Видимые теллы (D08): пакет показывает расширение; шифровальщик — красный квадрат 4×4; фишинг — client_id в формате id_XXXX с неверным символом (например id_7F3К, кириллическая К) и серым аватаром. locked/malicious файл остаётся кликабельным (уничтожение).

21. Арт и шрифты

  • Основной шрифт — Handjet (OFL 1.1, полная кириллица; вариативный wght 100–900, ELGR 1–2, ELSH 0–16; средняя ширина ≈0.36 em). (D15)
  • Press Start 2P — ТОЛЬКО крупные заголовки/логотип (слишком широкий: 17 символов не влезают в карточку 132 px).
  • Pixelify Sans — удалён из темы (неполная кириллица: нет О, П).
  • Допустимые кегли: 10 / 12 / 16 / 24 (Handjet узкий, 10 разрешён).
  • UI v2 «Kaleidos»: тёплая бумага #E9E6DD, 1 px контуры, мягкие тени #00000018, скругления 3–4 px, бирюзовый акцент #2F7F8F; меньше декоративных подписей. «Спокойный фон» — плоская PAPER без dither (D18, D24, D26).
  • Маскот БАЙТ ведёт короткий туториал первого часа (D24).
  • VHS-эффект только на главном меню: процедурный слой scripts/ui/vhs_overlay.gd (extends RefCounted), рисуется в MainMenu._draw до текста; скан-линии 2 физ. px, слабая хроматика, зерно, виньетка, полоса. Без shader/screen texture, ввод не блокирует, текст резкий. Чекбокс «VHS-эффект» в настройках, HEADLESS не рендерит. Игровой UI без CRT; это не полноэкранный CRT (D14, D27).
  • Фон: тёплый бумажный дизеринг и светлые панели, без полноэкранного fbm; CRT убрать (D14, D18).

22. Аудио

18 SFX (интерфейс, приём/отправка, соединение, мини-игры, атаки, экономика, итоги) + фоновый hum.wav (loop-friendly, 3 с); регулируемая громкость. Ambient машинного зала — 4 WAV (audio/amb, PSU/fan/room/seek), генератор audio/generate_ambient.py, autoload Ambient стартует после первого жеста (web autoplay), поддерживает mute/паузу/громкость музыки (D28).

23. Порядок разработки

P0 (D16, уточнено D23): данные/реестр → слоты → приём/отправка → UI. Типы: text h1, sound h2, photo/video h3+. Час 1 — без атак; junk/ddos — h2, phishing — h3, ransomware — h4 (difficulty.attacks = 0,1,1,2,2,3,3,4,4). Магазин — h2. Дальше: UI v2 «Kaleidos», прогрессивная мета, маскот-туториал, полировка, Web-сборка.

24. Приёмка (definition of done)

Полный забег из 9 часов, 4 типа файлов, 4 атаки, 10 позиций магазина, правило выбора мини-игры и формула зоны исчерпываются через data, RU-тексты, save/load и мета-открытия, HTML5-сборка работает на itch.io.

25. v1.2 — delta (D18–D28)

  • D18 — UI v2 «Kaleidos»: тёплая бумага, 1 px контуры, мягкие тени, скругления, бирюзовый акцент; окно 1920×1080, логический viewport 1280×720, fractional scale; меньше декоративного шума.
  • D19 — SLA/экономика: старт 128/200; потеря пакета text 2 / sound 4 / photo 8 / video 16; в магазине 10-я позиция SLA +24 (300, ×3).
  • D20 — таймеры: grace h1 1.5 / h2 1.35 / h3 1.2 / h4+ 1.0; (base − 0.5×(h−1))×grace + 4×timer_level; итоговая таблица — §8.
  • D21 — канал: load = Σ weight только активных передач; idle 0 %; capacity = 80 + 25×level; фон и слоты не грузят.
  • D22 — TCP: промах закрывает полоску, автоповтора нет; повторное «Соединиться»; connected только после успеха.
  • D23 — открытия/мета: магазин с часа 2; поиск/щит/complete_run — после 3/5/9 часов; run_meta_awards + «ОТКРЫТО» в итогах; типы text h1, sound h2, photo/video h3+; час 1 без атак, junk/ddos h2, phishing h3, ransomware h4; minigame_advanced — резерв без контента.
  • D24 — UX: уникальные имена папок, удаление пустых папок, автообновление, attached-галочки, магазин после часа без крестика, настройки на главном экране, маскот БАЙТ, спокойный фон = плоская бумага, реальное уничтожение содержимого (−5 SLA), Esc на итогах → меню.
  • D25 — проверки/ревью: scripts/run_all_tests.sh — 21 набор + parse-check, 22/22 PASS; MR-ревью OpenCode oracle (opencode-go/deepseek-v4.1-flash, 74–90 с на dry-run).
  • D26 — фиксы аудита: calm-фон без серого #C0C0C0, Esc на итогах → меню без soft-lock, реальное уничтожение папки, прогрессивная мета, час 1 без атак, честный резерв minigame_advanced.
  • D27 — VHS главного меню: процедурный vhs_overlay.gd (extends RefCounted) в MainMenu._draw; скан-линии, хроматика, зерно, виньетка, полоса. Без shader/screen texture, ввод не блокирует, текст резкий; только меню, чекбокс, HEADLESS без рендера. Не CRT на весь UI.
  • D28 — ambient machine room: 4 WAV в audio/amb, генератор generate_ambient.py, autoload после первого жеста, mute/пауза/громкость; тест test_ambient — 74/0.