Files
andrey 7f545347b4 Этап 45: локация «Волшебное болото» (id 4, 90 000 🪙) — светящиеся рыбы, лягушки, кувшинки/лилии. (1) Данные: LOCATIONS[4] (тёмно-моховая вода 6 hex, слабая рябь; в массиве ПОСЛЕДНИЙ, по цене — между Озёрами 65536 и Морем 131072); 5 новых видов строго в КОНЕЦ SPECIES (32→37, по одному на редкость r0–r4, у каждого glow:'#hex' — 5 разных цветов): glowfin Светлячок #5ff2ff 8🪙, moonfish Лунная рыбка #b9c8ff 13, emberfin Изумрудный светляк #57ffa8 20, violetlure Фиалковый огонёк #d17bff 38, spiritfin Дух болота #ffe07a 70; SWAMP_IDS/SWAMP_DAY_WEIGHTS/SWAMP_NIGHT_WEIGHTS/SWAMP_SPECIES(_NIGHT) — паттерн LAKE/SEA/OCEAN без пересечений; NIGHT_WEIGHTS — ключи всем 37 id. (2) pickSpecies(): вложенный тернарник → табличный доступ SPECIES_BY_LOCATION(_NIGHT) по save.location + guard (вне 0..4 → Река); роллы 0..3 бит-в-идентичны (lc3/lc4/lc4b/lc4c + речные §9j/M4/M6 не тронуты). (3) Свечение (только ночь): nightMix()>0.35 — тот же порог, что у фонаря; drawGlowAura() (радиальный градиент + 'lighter', save/restore, кэш GLOW_RGBA) — фоновые рыбы болота (AMBIENT_FISH[4] — 7 рыб + palette из 4 цветов, цвет стабильно по индексу), зацепившаяся/вываживаемая (fishGlow — вид с glow), боссовая золотая аура сохранена; карточка — класс glow-card + --glow (только normal-вариант, drop-shadow, не конфликтует с фильтрами вариантов), дневник — drop-shadow на SVG. (4) Декорации: initScenery() ветка i===4 (bank+reed+snag+pine в болотной гамме), ГЛОБАЛЬНЫЕ pads[] (8–14 кувшинок с вырезом, 45% с лилиями — жёлтые/белые/розовые) и frogs[] (3–5, sit→jump по параболе на соседнюю кувшинку, 3–7 с) — очищаются/пересобираются в initScenery() (resize + обе ветки shopClick); updateDecor(dt) — покачивание/прыжки; drawSwampDecor() — ОТДЕЛЬНЫЙ слой после drawWater/drawAmbientFish и до drawBoat (дusk берега не гасит; локальное притухание ночью). (5) Босс: BOSS_BY_LOCATION[4]='spiritfin' (Дух болота, 20–50 кг, ×5 — паттерн Этапа 37). (6) Магазин/i18n/ачивки: тост welcome_swamp (ru/en, тернарник → if/else), ачивки 34→36: swamp_first (bonus:{coinPct:0.02}, locations-based) + swamp_boss (bonus:{}, bosses.spiritfin) → пин achBonus().coinPct 0.16→0.18; species_8 = все 37. (7) Баланс: SWAMP_DAY_WEIGHTS {glowfin:3,moonfish:4,emberfin:28,violetlure:13,spiritfin:4.5}, SWAMP_NIGHT_WEIGHTS {glowfin:2.5,moonfish:2.5,emberfin:20,violetlure:30,spiritfin:4} — Болото 240.3/328.9 🪙 (ночь/день ×1.37), порядок по цене Озёра 194.1/249.0 < Болото < Море 297.3/476.7 в ОБЕ фазы; пины остальных вод не изменились (Река 65.1/125.9 · Озёра 194.1/249.0 · Море 297.3/476.7 · Океан 329.1/552.7). (8) tools/balance.mjs: 8→10 таблиц, +SWAMP_SPECIES(_NIGHT) в return, сводка/пары отношений — сортировка ПО ЦЕНЕ (болото встает между Озёрами и Морем), пины в шапке. (9) Портреты: 5 flat-SVG (каждый — отдельным художником) assets/fish/fish-{glowfin,moonfish,emberfin,violetlure,spiritfin}.svg (viewBox 0 0 160 100, var(--f1..f4,hsl-fallback)); embed-fish.mjs IDS 32→37 (в конец), 37 <symbol> в index.html; fish-preview.html 32→37 карточек. (10) Тесты (тот же коммит): lc1 (37/5 локаций/90000/names/sprites 37/oceanOrder slice(23,32)/swampOrder/swampGlow/swampRar), lc2 (+SWAMP-таблицы, пересечения, nightW 37), lc4d (новый: 3000+3000 роллов болота — все 5 ≥1, чужих нет), lc5 (+location:4 не сбрасывается, location:5→0), lc8w (новый: покупка 90000 + welcome_swamp), lc9 (37), lc10 (mid29), lc11 (новый: glow #rrggbb, 5 цветов различны, веса покрывают id, NIGHT_WEIGHTS — все 37), a22d (36), a36loc (+swamp_first), пин 0.18, §9k2 (+{loc:4, spiritfin, swamp_boss}). 198→204 PASS, exit 0. (11) Скриншоты: gen-screenshots.js +кадры swamp/swamp-night (12→14 × 3 вьюпорта, dayTime 0.3/0.85) — 42 RU + 42 EN PNG (screenshots-wiki/, screenshots-wiki-en/). (12) Доки: AGENTS.md (локации/босс/баланс/баланс-скрипт/награды/портреты/скриншоты), README (5 локаций, 37 видов, 36 ачивок, 204 теста, 14 кадров, mobp-swamp*), KODA.md (SWAMP_*, SPECIES_BY_LOCATION, drawGlowAura/fishGlow/GLOW_RGBA, drawSwampDecor, pads/frogs), DEVLOG (Этап 45), PLAN-SWAMP.md (статус «реализован»). Проверено: 204/204 PASS exit 0, check.mjs OK, balance.mjs — пины без изменений + Болото в цели, emoji-font --check OK (52 глифа, новых emoji нет), ревью @oracle — критичных замечаний нет (.gitignore + .opencode/, fish-preview, осколок комментария species_8 — закрыты в этом же коммите). Миграция сейва не тронута (граница из LOCATIONS.length; location=4 покрыт lc5(f)).
2026-09-21 22:59:15 +03:00

56 lines
5.1 KiB
XML

<!-- Дух болота (spiritfin): полупрозрачное призрачное тело «каплей» вправо, вместо хвоста — растекающиеся вниз духовные отростки-струи, большие светящиеся золотые глаза, ореол из светящихся дуг вокруг головы, парящие золотые точки-души -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 100" width="160" height="100">
<!-- ореол: светящиеся дуги вокруг головы (сзади тела) -->
<path fill="none" stroke="#ffe07a" stroke-width="7" stroke-linecap="round" opacity="0.08" d="M76 18 Q118 -6 158 26"/>
<path fill="none" stroke="#ffe07a" stroke-width="3" stroke-linecap="round" opacity="0.55" d="M78 18 Q118 -5 158 26"/>
<path fill="none" stroke="#ffe07a" stroke-width="2.6" stroke-linecap="round" opacity="0.7" d="M88 18 Q122 1 158 32"/>
<path fill="none" stroke="#ffe07a" stroke-width="2.4" stroke-linecap="round" opacity="0.6" d="M102 18 Q132 5 158 38"/>
<path fill="none" stroke="#ffe07a" stroke-width="5" stroke-linecap="round" opacity="0.1" d="M138 82 Q162 66 158 42"/>
<path fill="none" stroke="#ffe07a" stroke-width="2.4" stroke-linecap="round" opacity="0.6" d="M138 82 Q162 66 158 42"/>
<!-- души-точки (задний план) -->
<circle fill="#ffe07a" cx="88" cy="10" r="5" opacity="0.18"/>
<circle fill="#ffe07a" cx="88" cy="10" r="2.2"/>
<circle fill="#ffe07a" cx="34" cy="18" r="6" opacity="0.18"/>
<circle fill="#ffe07a" cx="34" cy="18" r="2.6"/>
<circle fill="#ffe07a" cx="16" cy="70" r="5" opacity="0.18"/>
<circle fill="#ffe07a" cx="16" cy="70" r="2.2"/>
<!-- духовные отростки вместо хвоста: растекающиеся вниз струи -->
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.45" d="M40 30 C33 22 26 18 17 18 C26 23 32 28 36 35 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.8" d="M28 60 C24 72 22 84 25 97 C31 89 33 78 36 66 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.7" d="M44 73 C41 83 42 92 47 99 C52 91 51 82 53 73 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.6" d="M60 80 C59 88 62 95 68 100 C71 92 68 86 67 80 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.5" d="M76 84 C76 90 79 95 84 98 C86 92 84 87 82 83 Z"/>
<!-- спинной и грудной плавники: призрачные, полупрозрачные -->
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.85" d="M56 27 C64 12 82 7 96 15 C82 15 68 20 60 29 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.8" d="M116 60 C108 68 100 78 102 88 C112 80 120 70 124 62 Z"/>
<!-- тело: крупная призрачная «капля», полупрозрачная, тянется влево -->
<path fill="var(--f1,hsl(182,30%,40%))" opacity="0.85" d="M150 52 C150 38 138 27 118 23 C96 18.5 68 20 48 29 C38 33.5 30 40 25 47 C22 51 22 55 25 59 C30 66 38 72 48 76 C68 85 96 86.5 118 82 C138 78 150 66 150 52 Z"/>
<!-- брюхо: светлая пологая полоса снизу -->
<path fill="var(--f2,hsl(178,22%,64%))" opacity="0.85" d="M150 52 C150 66 138 78 118 82 C96 86.5 68 85 48 76 C38 72 30 66 25 59 C35 64.5 48 69 62 72 C90 78 122 74 150 52 Z"/>
<!-- духовные вихри на теле -->
<path fill="none" stroke="var(--f2,hsl(178,22%,64%))" stroke-width="2" stroke-linecap="round" opacity="0.5" d="M70 40 Q90 30 112 33"/>
<path fill="none" stroke="var(--f4,hsl(186,38%,20%))" stroke-width="2" stroke-linecap="round" opacity="0.3" d="M64 58 Q88 64 116 60"/>
<path fill="none" stroke="var(--f2,hsl(178,22%,64%))" stroke-width="1.8" stroke-linecap="round" opacity="0.4" d="M78 72 Q98 78 120 72"/>
<!-- жаберная линия у головы -->
<path fill="none" stroke="var(--f4,hsl(186,38%,20%))" stroke-width="2.5" stroke-linecap="round" opacity="0.32" d="M110 30 Q103 52 112 76"/>
<!-- пасть: тёмная щель на нижней части головы -->
<path fill="var(--f4,hsl(186,38%,20%))" d="M150 54 C140 61 128 65 118 65 C130 70 146 65 150 54 Z"/>
<!-- глаз: большой светящийся золотой -->
<circle fill="#ffe07a" cx="122" cy="44" r="13" opacity="0.18"/>
<circle fill="#ffe07a" cx="122" cy="44" r="9" opacity="0.35"/>
<circle fill="#fff3c4" cx="122" cy="44" r="6.5"/>
<circle fill="#142638" cx="122" cy="44" r="3.2"/>
<circle fill="#fff" cx="123.6" cy="42.2" r="1.4"/>
<!-- души-точки (передний план) -->
<circle fill="#ffe07a" cx="150" cy="24" r="6.5" opacity="0.2"/>
<circle fill="#ffe07a" cx="150" cy="24" r="3"/>
<circle fill="#ffe07a" cx="138" cy="88" r="5" opacity="0.2"/>
<circle fill="#ffe07a" cx="138" cy="88" r="2.2"/>
<circle fill="#ffe07a" cx="104" cy="92" r="7" opacity="0.2"/>
<circle fill="#ffe07a" cx="104" cy="92" r="3.2"/>
<circle fill="#ffe07a" cx="58" cy="94" r="5.5" opacity="0.2"/>
<circle fill="#ffe07a" cx="58" cy="94" r="2.4"/>
<circle fill="#ffe07a" cx="72" cy="70" r="4" opacity="0.35"/>
<circle fill="#ffe07a" cx="72" cy="70" r="1.8"/>
</svg>