# Ревизия проекта (03.09.2026)

## Копии исходников и что с ними стало

| Копия | Состояние на момент ревизии | Решение |
|---|---|---|
| `src_mobius/mobius/L2J_Mobius_CT_0_Interlude` | Источник истины после слияния 26.08 (мозг + чат) | Оставлен, теперь под git |
| `server/` | Развёрнутый сервер; в нём были **более новые** `FakePlayerProgression.xml` и `spp_clan_seed.sql` (новые ники из чата «Генерация ников»), jar собран из `src_mobius` | Ники забраны в `src_mobius`; `server/` вне git, наполняется деплоем |
| `patches/` | Мост между двумя копиями (26.08), содержимое старее `src_mobius` | Устарел, игнорируется |
| `src_mobius_interlude.zip` (26.08 13:59) | Снимок до слияния мозга; единственное отличие от дерева — отсутствие `FakePlayerBrain`/`CombatData` | Устарел |
| `ziAuQ8He`, `ziVsvreY` (26.08 00:16 и 01:47) | Ранние снимки чата (до Idiolect/HeardManager) | Устарели |
| `src/`, `l2j-lisvus/` | Заброшенная попытка на L2J Lisvus (C4) | Игнорируются |

Ванильная база найдена точно: java-дерево совпадает с Mobius `9be7adbe5a` (25.08.2026) везде, кроме наших файлов. Наш патч поверх ванили: `GameServer.java`, `AttackableAI.java`, `Attackable.java`, `Npc.java`, `Player.java`, `RequestJoinParty.java`, `FakePlayerInfo.java`, `FakePlayersConfig.java` + все `FakePlayer*.java` в `managers` + `FakePlayerNameGenerator.java`; в датапаке — `FakePlayers.ini`, `General.ini` (GridsAlwaysOn), `FakePlayers.xml` (спавн Evi выключен), `FakePlayerChatData.xml`, `ChatGeneral.java`, `ChatWhisper.java`, все `FakePlayer*.xml`/xsd, `dashboard.html`, `fpc_trader_00.xml`, `spp_*.sql`.

## Найденные проблемы

1. **Чат-движок был подключён не к тому населению.** Мир работает в режиме «только headless» (`FakePlayerProgression = False`, 500 headless). Весь чат из сессии «Изучение швов» — `understand()` с памятью позиций, молчанием на первое сообщение, реакцией на капс, зеркалированием стиля, фактами `asker` — жил только в `FakePlayerChatManager` и принимал `Npc`. Headless-боты (реальное население) отвечали через свой урезанный `understand()` без всего этого. Исправлено: общий `FakePlayerUnderstanding` + `FakePlayerBotRef` для обоих видов ботов.
2. **Боевой цикл душил социальный.** В `handle()` мозг возвращал `true`, как только видел моба или был в бою, и код ниже (ганг, ПКК, помощь, клан-вары, пати, бытовой чат, лут) не выполнялся почти никогда — в зоне фарма моб есть всегда. Исправлено: социальный слой (`FakePlayerSocial`) идёт до мозга и гейтится кулдаунами, лут перенесён в мозг.
3. **Боты не разговаривали друг с другом.** Единственный канал — «подхват» через `HeardManager` с 10% шансом и глобальным троттлом 8 с на весь сервер. Добавлены диалоги: приветствия при встрече, вопросы-открытия (`bot_talk`), ответы через тот же разбор интентов, что и для игрока, сплетни, поздравления; троттл сделан per-listener.
4. **Данные умели больше, чем код.** Факты `asker=clanmate|enemy_war`, слоты `{enemyclan} {mob} {town} {crowd} {drop}` были в XML, но код их не подавал — строки с ними никогда не выпадали. Теперь подаются (`FakePlayerBotContext.setSlot`).
5. **Зоны фарма не соответствовали уровням мобов.** Таблица зон была «сеткой» по регионам без сверки с мобами: Wasteland (мобы 30–35) значился как 15–24, Cruma Marshlands (28–35) как 15–24, Tanor Canyon (43–50) как 35–44 и т.д. Для NPC-ботов (статы из шаблонов) это не бросалось в глаза, для headless-игроков — гибель пачками. Таблица пересчитана по реальным спавнам датапака (`tools/fix_zones.py`): 96 зон с узкими полосами уровней, плюс 8 новых зон на 13–22 (Ruins of Agony/Despair, Abandoned Camp, Windmill Hill, Swampland, Dark Forest, Spider Nest, Abandoned Coal Mines).
6. **Боты не давали сдачи** мобам не своего уровня, не носили бижу, не имели бафов, потом зелья использовались через `useEquippableItem` (ошибка «Unknown body slot NONE» в логе). Исправлено.
7. **Класс 34 в `FakePlayerCombat.xml` был подписан как Spellhowler** (34 — Bladedancer, Spellhowler — 40): БД получал роль «маг». Профили были на 13 классов из 43 в сиде; теперь на все 43, id скиллов проверены по деревьям скиллов (`tools/check_data.py`).
8. **Лавка после закрытия оставляла бота в городе** — он «фармил» Гиран до конца жизни. Теперь после лавки — покупка расходников и возврат на спот.
9. **Ложные срабатывания интентов**: «молодая» ≈ «соло» → дуэль, «думаешь» ≈ «дурак» → оскорбление, «стоишь» ≈ «стоит» → цена, «слышь» удовлетворяло обе группы «что нового». Опечатко-устойчивость ограничена (основа ≥ 5 букв, длина слова близка), добавлена пометка `=основа` (только точный префикс), одно слово не закрывает две группы.
10. **NPC-режим ботов сломан**: шаблонов `fpc_spp_00..07.xml` (1600 NPC) в `server/` нет, `FakePlayerProgression = True` спавнить нечего. Не чинил — мир headless.
11. `FakePlayerLlmChat = True` при недоступной Ollama: каждый ответ ждёт таймаут/отказ и только потом шаблон. Добавлен `FakePlayerLlmPriority = seams` — шаблоны первыми, LLM только для фраз без интента.
12. Мелочи: XML без XSD печатали ошибки валидации при старте (добавлены разрешающие xsd); `reset-bots.ps1` чистит гербы 9000–9999 при диапазоне 9500–9668 — ок; `data.rar`/`html.rar` в `server/game/data` — 154 МБ мусора.

## Что не проверено вживую с клиентом

Все проверки — в песочнице (MariaDB + login + game, 120 ботов, ~2 мин на прогон) и оффлайн-харнессом. Не проверялось глазами из клиента: окно приглашения в пати от бота (`do=invite`), отрисовка бота, кастующего печать на артефакте, общий вид осады. Осада запускалась форсом (`do=siege&arg=Giran`): регистрация кланов, телепорт, крики, атака ворот — в логе есть, до печати за 45 секунд наблюдения дело не доходило.

## Смертность

После правок боты гибнут заметно реже (в песочнице без геодаты ~18/мин на 120 ботов в первую минуту после спавна, с геодатой ~10/мин; до правок — 20–24), но всё ещё много: маги гибнут от равных мобов, спавн попадает в центр стай. Дальнейшие ручки: `pickPrey` (сейчас цель не выше уровня+1 и подальше от стаи), пороги отдыха (охота только при HP ≥ 60%), сквады соклановцев (формируются сами и держатся лидера).
