From 85f80445d11f5616c888dd9ae803c917f5681785 Mon Sep 17 00:00:00 2001 From: sindoring Date: Sat, 18 Jul 2026 17:05:18 +0400 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=BB=D0=B0=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CUSTOMIZATION_PLAN.md | 788 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 788 insertions(+) create mode 100644 CUSTOMIZATION_PLAN.md diff --git a/CUSTOMIZATION_PLAN.md b/CUSTOMIZATION_PLAN.md new file mode 100644 index 0000000..3b6b9b0 --- /dev/null +++ b/CUSTOMIZATION_PLAN.md @@ -0,0 +1,788 @@ +# План расширенной кастомизации персонажей MoonWell + +## 1. Цель + +Создать для клиента WoW 3.3.5a (build 12340) расширенную систему внешности, визуально и по удобству близкую к retail, сохранив оригинальный `Wow.exe` и используя WarcraftXL для всех клиентских расширений. + +Система должна: + +- поддерживать стандартные параметры 3.3.5a и дополнительные параметры MoonWell; +- показывать одинаковую внешность при создании, выборе персонажа, входе в мир и другим игрокам; +- хранить дополнительные параметры на сервере и считать сервер источником истины; +- поддерживать текстурные слои, geoset базовой модели и отдельные прикрепляемые M2-модели; +- работать без Eluna/AIO в качестве постоянного транспорта состояния; +- позволять добавлять новые варианты преимущественно данными и ассетами; +- иметь версионирование формата и безопасный откат. + +## 2. Не входит в первую версию + +- полное копирование внутренних `ChrCustomization*` DB2 и протокола актуального retail-клиента; +- поддержка всех retail-рас, которых нет в MoonWell; +- динамическое изменение скелета или пропорций тела; +- автоматический импорт всех retail-ассетов без ручной проверки; +- публикация полного дампа современных файлов Blizzard; +- изменение бинарника `Wow.exe` на диске. + +## 3. Базовые ограничения + +### Клиент + +- WoW 3.3.5a, build 12340, Lua 5.1, `## Interface: 30300`. +- `Wow.exe` должен оставаться оригинальным с контролируемым SHA-256. +- Новое нативное поведение реализуется модулем MoonWell внутри WarcraftXL. +- GlueXML и FrameXML не используют retail API (`C_Timer`, `CreateFramePool`, `PixelUtil` и т. п.). +- Для анимаций интерфейса используется `OnUpdate`. +- UI-текстуры: `.blp`/`.tga`, размеры по степеням двойки, не более 512×512 на отдельный UI-тайл. +- В Lua/XML использовать `SetWidth`/`SetHeight`, а не `SetSize`. + +### Ассеты и рендер + +- Исходные современные M2/MD21 обрабатываются `wxl-modern-assets`. +- Каждая модель проверяется на поддерживаемую версию формата, лимит костей, материалы, анимации и attachment points. +- Не использовать OBJ/FBX/glTF как вход для игрового клиента: нужны исходные `.m2`, `.skin`, `.skel`, `.anim` и `.blp`. +- UI-превью и модель в мире должны использовать один каталог вариантов и одинаковые идентификаторы. + +### Сервер + +- Сервер валидирует расу, пол, доступность и совместимость каждого выбора. +- Клиент не может назначить себе недоступный вариант внешности. +- Дополнительные параметры хранятся отдельно от стандартных байтов внешности 3.3.5a. +- Изменения схемы БД поставляются миграциями и имеют обратимый путь. + +## 4. Целевая архитектура + +```text +Retail CDN (выбранные FileDataID) + │ + ▼ +Asset manifest + downloader + validation + │ + ▼ +Patch*.MPQ / loose Patch-WXL assets + │ + ├── wxl-modern-assets + ├── адаптированный wxl-equip-extension + └── MoonWell customization runtime + │ + Lua API / GlueXML UI + │ + ▼ + MoonWell customization protocol + │ + ▼ + AzerothCore storage + validation + broadcast +``` + +### Компоненты + +1. **Asset pipeline** — получает только перечисленные зависимости по `FileDataID`, сохраняет манифест и проверяет комплектность. +2. **`wxl-modern-assets`** — загружает и приводит современные M2/MD21 и текстуры к контракту клиента 3.3.5a. +3. **Адаптированный `wxl-equip-extension`** — прикрепляет M2, поддерживает collection M2, два модельных канала, attachment points и фильтрацию geoset. +4. **MoonWell customization runtime** — управляет независимыми косметическими каналами, текстурными слоями, geoset базовой модели и Lua API. +5. **GlueXML UI** — категории, список вариантов, камера, случайный выбор, сброс и предварительный просмотр. +6. **Серверный модуль** — хранение, валидация, загрузка, изменение и распространение внешности. + +## 5. Типы параметров внешности + +### Стандартные параметры 3.3.5a + +- пол; +- цвет кожи; +- лицо; +- причёска; +- цвет волос; +- стандартная особенность лица/борода. + +Они продолжают использовать штатные поля персонажа и стандартный пакет создания. + +### Дополнительные текстурные параметры + +- шрамы; +- татуировки тела; +- татуировки лица; +- макияж; +- рисунок/отметины; +- дополнительные оттенки кожи; +- дополнительные слои лица. + +Реализация: расширение `CharSections`, каталог слоёв и модификация/перехват клиентского композитора текстуры персонажа. + +### Geoset базовой модели + +- дополнительные причёски; +- части бороды и усов; +- форма ушей/бровей; +- варианты клыков; +- встроенные рога; +- скрытие частей базовой модели. + +Реализация: таблица выбора geoset по расе, полу, категории и варианту. + +### Прикрепляемые M2-элементы + +- серьги и пирсинг; +- украшения для волос; +- объёмные бороды; +- рога и дополнительные клыки; +- протезы; +- венцы, диадемы и прочие аксессуары; +- независимые объёмные элементы тела. + +Реализация: косметические каналы поверх механизма `wxl-equip-extension`. + +## 6. Косметические каналы + +Кастомизация не должна занимать реальные слоты экипировки. Нужен отдельный реестр каналов: + +```text +hair_extra +beard_extra +horns +ears +tusks +piercing_1 +piercing_2 +accessory_head +accessory_face +accessory_body_1 +accessory_body_2 +``` + +Для каждого канала задаются: + +- стабильный числовой `option_id`; +- допустимые расы и пол; +- `display_id` или прямое описание M2; +- Model1/Model2; +- Texture1/Texture2; +- attachment point для каждого модельного канала; +- список разрешённых geoset collection M2; +- флаги суффиксов расы/пола и структуры каталогов; +- правила конфликта со шлемом и настоящей экипировкой; +- приоритет и взаимоисключающие каналы; +- значение сброса (`choice_id = 0`). + +## 7. Адаптация `wxl-equip-extension` + +### Обязательные работы + +- закрепить точную ревизию репозитория как submodule; +- адаптировать сборочную структуру к текущему WarcraftXL MoonWell; +- проверить пересечение хуков с `wxl-modern-assets` и существующими `OnItemSlotChange`, `OnItemSlotClear`, `OnM2PerFrameUpdate`; +- вынести разбор Model1/Model2, `Icon2`, attachment points и collection geoset в переиспользуемый слой; +- добавить API независимых косметических каналов, не привязанных к надетому предмету; +- устранить утечку/остаток collection M2 после снятия или смены варианта; +- обеспечить корректное уничтожение дочерних моделей при смене персонажа, карты, формы и пола; +- исключить двойное прикрепление модели при повторной синхронизации; +- очистить мусорные Model1/Model2 в старых строках `ItemDisplayInfo.dbc`; +- добавить диагностический лог разрешения пути, модели, текстуры, attachment point и geoset; +- реализовать безопасный fallback при отсутствии ассета. + +### Проверки совместимости + +- персонаж игрока; +- другие игроки; +- NPC с тем же `display_id`; +- экран создания; +- экран выбора; +- парикмахерская; +- смена экипировки; +- превращения и shapeshift; +- транспорт; +- телепорт и смена карты; +- повторный вход и `/reload`. + +## 8. Каталог данных кастомизации + +Нужен единый, версионируемый источник данных, из которого генерируются клиентское и серверное представления. + +Предлагаемая запись: + +```text +option_id +choice_id +race_mask +gender_mask +category +label_key +render_type +char_section_id +geoset_ids +model_1 +model_2 +texture_1 +texture_2 +attachment_1 +attachment_2 +flags +conflict_group +unlock_condition +asset_manifest_id +enabled +``` + +Требования: + +- `(option_id, choice_id)` никогда не переиспользуется с другим смыслом; +- удалённый вариант остаётся распознаваемым для миграции старых персонажей; +- порядок отображения UI хранится отдельно от стабильного идентификатора; +- клиент и сервер собираются из одной версии каталога; +- версия каталога входит в сетевое рукопожатие. + +## 9. Серверное хранение + +### Предлагаемая таблица + +```sql +character_customization ( + guid INT UNSIGNED NOT NULL, + option_id SMALLINT UNSIGNED NOT NULL, + choice_id INT UNSIGNED NOT NULL, + updated_at TIMESTAMP NOT NULL, + PRIMARY KEY (guid, option_id) +) +``` + +Дополнительно: + +- индекс по `guid`; +- внешний ключ или очистка записей при удалении персонажа; +- миграция с начальными значениями для существующих персонажей; +- сервис сброса неизвестных/отключённых вариантов; +- аудит изменения внешности при необходимости. + +### Серверная логика + +- загрузить набор при `Character::LoadFromDB` или эквивалентном этапе; +- валидировать выбор по расе, полу, режиму игры и доступности; +- сохранять транзакционно; +- включать состояние в данные экрана выбора персонажа; +- отправлять полный snapshot при входе в мир; +- отправлять delta при изменении; +- рассылать актуальное состояние игрокам в зоне видимости; +- отправлять snapshot при появлении объекта в зоне видимости нового клиента; +- ограничить частоту изменений; +- запретить недоступные комбинации независимо от клиентского UI. + +## 10. Сетевой протокол MoonWell + +### Общие требования + +- собственный namespace/opcode или надёжный WarcraftXL transport; +- версия протокола и версия каталога; +- явная длина сообщения и лимит числа записей; +- little-endian поля с фиксированной шириной; +- сервер является источником истины; +- неизвестные поля пропускаются или отклоняются согласно версии; +- отсутствие расширения не ломает стандартный вход в игру. + +### Сообщения + +```text +CMSG_MOONWELL_CUSTOMIZATION_CREATE + protocol_version + catalog_version + option_count + repeated(option_id, choice_id) + +SMSG_MOONWELL_CUSTOMIZATION_RESULT + result_code + normalized choices + +SMSG_MOONWELL_CUSTOMIZATION_SNAPSHOT + player_guid + catalog_version + option_count + repeated(option_id, choice_id) + +CMSG_MOONWELL_CUSTOMIZATION_UPDATE + option_count + repeated(option_id, choice_id) + +SMSG_MOONWELL_CUSTOMIZATION_DELTA + player_guid + option_count + repeated(option_id, choice_id) +``` + +### Экран выбора персонажа + +Предпочтительный вариант — отдельный snapshot после получения списка персонажей. Не расширять штатный пакет без строгой проверки длины и совместимости. + +Клиент должен: + +- сопоставить snapshot с GUID персонажа; +- применить его к модели выбранного персонажа; +- хранить данные только до обновления от сервера; +- показывать стандартную внешность, если snapshot отсутствует или версия несовместима. + +## 11. Клиентский runtime API + +Планируемый API WarcraftXL: + +```text +MoonWellCustomizationGetCatalogVersion() +MoonWellCustomizationGetOptions(race, gender) +MoonWellCustomizationGetChoices(optionId) +MoonWellCustomizationGetCurrent(optionId) +MoonWellCustomizationPreview(optionId, choiceId) +MoonWellCustomizationResetPreview() +MoonWellCustomizationCommitPreview() +MoonWellCustomizationRandomize() +MoonWellCustomizationApplySnapshot(guid, data) +MoonWellCustomizationClear(guid) +``` + +Требования: + +- Lua получает только безопасные операции высокого уровня; +- нативный слой владеет указателями моделей и их жизненным циклом; +- повторное применение snapshot идемпотентно; +- preview не меняет серверное состояние; +- при ошибке модель возвращается к последнему подтверждённому snapshot; +- смена расы или пола пересчитывает допустимость всех параметров; +- отсутствие M2/текстуры отключает только конкретный вариант, а не весь экран. + +## 12. Применение внешности + +Порядок применения должен быть фиксированным: + +1. базовая раса и пол; +2. стандартные параметры 3.3.5a; +3. `CharSections` и текстурные слои; +4. geoset базовой модели; +5. скрытие/конфликты с экипировкой; +6. независимые косметические M2-каналы; +7. обновление материалов и композитной текстуры; +8. окончательное обновление позы и камеры превью. + +При смене одного параметра обновляется только затронутый слой, если это безопасно. Полная пересборка модели используется как fallback. + +## 13. Интерфейс создания персонажа + +### Структура + +- категории слева или справа от модели; +- прокручиваемая сетка вариантов; +- текстовое название активной категории; +- состояние выбранного варианта; +- кнопки случайного выбора и сброса; +- возврат к выбору расы/класса без потери валидных параметров; +- подтверждение создания только после серверной валидации; +- плавное приближение камеры к зоне редактирования. + +### Категории первой версии + +- кожа; +- лицо; +- причёска; +- цвет волос; +- борода/особенность лица; +- шрамы; +- татуировки; +- серьги/пирсинг; +- расовый аксессуар. + +Категории скрываются, если для текущей расы/пола нет вариантов. + +### Камера + +- профиль камеры задаётся по расе, полу и категории; +- отдельно настраиваются distance, вертикальная цель, горизонтальный сдвиг и FOV; +- переход использует easing через `OnUpdate`; +- короткие и средние расы имеют отдельные профили; +- при выходе из кастомизации камера плавно возвращается к полному росту; +- вращение персонажа доступно во всех режимах; +- UI не перекрывает лицо и активный аксессуар на 4:3, 16:9 и 16:10. + +### Ограничения UI 3.3.5a + +- XML загружается раньше Lua; +- именованные Button и ScrollFrame; +- `relativeTo`, а не `relativeKey`; +- `$parentX`, а не `$parent.X`; +- `SetWidth`/`SetHeight` вместо `SetSize`; +- таймеры и анимации через `OnUpdate`; +- UI-атласы режутся на тайлы не более 512×512. + +## 14. Парикмахерская и изменение существующего персонажа + +- использовать тот же каталог и preview API; +- получать текущий серверный snapshot при открытии; +- считать стоимость на сервере; +- подтверждать изменение одним атомарным запросом; +- откатывать preview при закрытии или отказе сервера; +- блокировать недоступные варианты; +- поддерживать бесплатные/платные категории отдельными правилами; +- обновлять внешность окружающим только после подтверждения. + +## 15. Получение retail-ассетов без установки клиента + +### Инструменты + +- `wow.export` в online-режиме — поиск и предварительный просмотр; +- Wago Tools/wow-listfile — поиск пути и `FileDataID`; +- TACTSharp/TACTTool — точечная загрузка исходных файлов с CDN Blizzard. + +### Манифест ассета + +```text +asset_id +source_product +source_build +file_data_id +original_path +target_path +sha256 +kind +parent_asset_id +license_note +``` + +### Пайплайн + +1. Выбрать модель и исходный retail build. +2. Зафиксировать корневой `FileDataID`. +3. Выгрузить M2 и определить зависимости. +4. Загрузить `.skin`, `.skel`, `.anim` и текстуры. +5. Проверить хэши и комплектность. +6. Проверить модель в изолированном preview. +7. Проверить downport через `wxl-modern-assets`. +8. Добавить запись в каталог кастомизации. +9. Упаковать только выбранные файлы. +10. Не помещать массовый дамп retail-клиента в Git. + +### Автоматические проверки ассета + +- поддерживаемая версия M2/MD21; +- наличие всех skin-профилей; +- разрешимые FileDataID и пути текстур; +- наличие внешнего скелета/анимаций; +- attachment points для целевой расы; +- лимит костей на draw после разбиения; +- валидные материалы и blend modes; +- отсутствие коллизий целевых путей; +- размер итогового MPQ и память после загрузки; +- корректное освобождение ресурсов. + +## 16. Этапы реализации + +### Этап 0. Исследование и фиксация контрактов + +- [ ] Зафиксировать ревизии WarcraftXL и всех модулей. +- [ ] Зафиксировать исходный retail build для ассетов. +- [ ] Составить карту существующих хуков персонажа и DBC. +- [ ] Проверить структуру штатных пакетов создания/выбора персонажа. +- [ ] Зафиксировать каталог option/choice ID. +- [ ] Утвердить правила доступности и монетизации. +- [ ] Выбрать первую расу для вертикального среза: человек. + +**Результат:** техническая спецификация без конфликтующих точек расширения. + +### Этап 1. Интеграция equip-extension + +- [ ] Добавить репозиторий как закреплённый submodule. +- [ ] Адаптировать CMake/module layout. +- [ ] Собрать Win32 runtime и x64 host. +- [ ] Устранить конфликт хуков с текущим WarcraftXL. +- [ ] Исправить снятие collection M2. +- [ ] Очистить мусорные поля `ItemDisplayInfo.dbc`. +- [ ] Добавить smoke-тест Model1/Model2 на каждом поддержанном слоте. +- [ ] Добавить диагностическое логирование. + +**Результат:** современная объёмная экипировка работает и корректно снимается. + +### Этап 2. Независимые косметические каналы + +- [ ] Отделить attachment runtime от реальных слотов экипировки. +- [ ] Реализовать реестр косметических каналов. +- [ ] Реализовать add/replace/remove/clear. +- [ ] Реализовать conflict groups и приоритеты. +- [ ] Реализовать скрытие под шлемом. +- [ ] Добавить API preview. +- [ ] Проверить смену карты, формы и пола. + +**Результат:** аксессуар можно показать без создания фиктивного предмета. + +### Этап 3. Asset pipeline + +- [ ] Добавить входной manifest с FileDataID. +- [ ] Реализовать пакетную загрузку через CDN. +- [ ] Добавить локальный кэш по хэшу. +- [ ] Автоматически проверять зависимости. +- [ ] Формировать отчёт о пропущенных файлах. +- [ ] Интегрировать выбранные ассеты в MPQ build. +- [ ] Добавить контроль размера и дубликатов. + +**Результат:** воспроизводимая сборка выбранных retail-ассетов без полного клиента. + +### Этап 4. Серверное хранение и протокол + +- [ ] Добавить миграцию `character_customization`. +- [ ] Реализовать серверный каталог допустимых вариантов. +- [ ] Реализовать create/update validation. +- [ ] Реализовать snapshot и delta. +- [ ] Подключить данные к character enum/select flow. +- [ ] Рассылать состояние в visibility range. +- [ ] Добавить rate limit и журнал ошибок. +- [ ] Добавить fallback для клиента без совместимой версии. + +**Результат:** параметры сохраняются и одинаково видны всем клиентам. + +### Этап 5. Текстурные слои и geoset + +- [ ] Расширить/переопределить `CharSections` данными MoonWell. +- [ ] Реализовать слои шрамов, татуировок и макияжа. +- [ ] Реализовать таблицу geoset базовой модели. +- [ ] Синхронизировать цветовые зависимости. +- [ ] Обеспечить совместимость с надетой бронёй. +- [ ] Добавить полную пересборку как fallback. + +**Результат:** работают не только прикрепляемые M2, но и полноценные параметры тела/лица. + +### Этап 6. Новый UI создания персонажа + +- [ ] Создать адаптивную панель категорий. +- [ ] Создать прокручиваемую сетку choices. +- [ ] Подключить preview API. +- [ ] Добавить race/gender/category camera profiles. +- [ ] Добавить randomize и reset. +- [ ] Добавить обработку недоступного ассета. +- [ ] Добавить серверное подтверждение создания. +- [ ] Проверить 4:3, 16:9, 16:10 и UI scale. + +**Результат:** законченный retail-подобный пользовательский сценарий. + +### Этап 7. Вертикальный срез — человек + +- [ ] Мужская и женская модели. +- [ ] Стандартные категории. +- [ ] Минимум одна новая текстурная категория. +- [ ] Минимум два M2-косметических канала. +- [ ] Сохранение, выбор персонажа и отображение в мире. +- [ ] Видимость другим игрокам. +- [ ] Парикмахерская/изменение существующего персонажа. +- [ ] Полный regression-тест экипировки. + +**Результат:** одна раса полностью проходит production-сценарий. + +### Этап 8. Масштабирование на все расы WotLK + +- [ ] Дворфы. +- [ ] Ночные эльфы. +- [ ] Гномы. +- [ ] Дренеи. +- [ ] Орки. +- [ ] Нежить. +- [ ] Таурены. +- [ ] Тролли. +- [ ] Эльфы крови. +- [ ] Отдельная настройка камер для каждого пола. +- [ ] Матрица конфликтов расовых элементов с экипировкой. + +**Результат:** единый уровень качества для всех доступных рас. + +### Этап 9. Стабилизация и выпуск + +- [ ] Нагрузочный тест большого скопления игроков. +- [ ] Проверка утечек модели/текстур при многократной смене вариантов. +- [ ] Проверка холодного кэша WarcraftXLHost. +- [ ] Проверка отсутствующих/повреждённых ассетов. +- [ ] Версионирование manifest, каталога и протокола. +- [ ] Миграция существующих персонажей. +- [ ] Rollback-пакет. +- [ ] Документация для добавления новой категории/расы. +- [ ] Обновление deploy-скрипта и launcher manifest. + +**Результат:** воспроизводимый production-релиз. + +## 17. Матрица тестирования + +### Персонажи + +- каждая раса × каждый пол; +- стандартный режим × предатель; +- новый персонаж × существующий персонаж; +- минимальное × максимальное число выбранных параметров; +- случайная комбинация × преднамеренно конфликтная комбинация. + +### Состояния клиента + +- создание; +- выбор; +- загрузочный экран; +- вход в мир; +- появление другого игрока; +- телепорт; +- смерть/дух; +- транспорт; +- shapeshift/превращение; +- парикмахерская; +- смена экипировки; +- скрытие шлема/плаща; +- `/reload`; +- переподключение; +- выход и повторный вход. + +### Графика + +- native renderer и основной D3D9On12 путь; +- разные уровни component texture quality; +- включённые/выключенные SSAA, SSAO и AA; +- дальние LOD; +- тени; +- прозрачные и emissive материалы; +- несколько одинаковых моделей одновременно; +- 4:3, 16:9, 16:10 и разные UI scale. + +### Сеть и сервер + +- потеря/повтор snapshot; +- snapshot до появления модели и после неё; +- неизвестная версия каталога; +- неизвестный option/choice; +- запрещённый выбор; +- слишком большое сообщение; +- быстрое повторное изменение; +- одновременное изменение и телепорт; +- сохранение при logout/crash; +- удаление и восстановление персонажа. + +## 18. Производительность + +Целевые ограничения: + +- не выполнять разбор каталога каждый кадр; +- не пересобирать всю модель при изменении независимого аксессуара; +- кэшировать разрешённые пути и обработанные modern assets; +- не создавать дубликаты одной и той же дочерней M2-модели; +- освобождать attachment при удалении/скрытии объекта; +- ограничить число одновременных косметических M2 на персонажа; +- иметь настройку отключения дальних косметических attachment; +- измерять время первой загрузки, потребление RAM/VRAM и frame time; +- логирование hot path отключено в release-сборке. + +Предварительный бюджет первой версии: + +- до 6 независимых M2-каналов на персонажа; +- не более двух моделей на канал; +- отсутствие постоянной работы Lua `OnUpdate`, кроме активной UI-анимации; +- пересборка полной внешности только при snapshot, смене расы/пола или восстановлении после ошибки. + +## 19. Безопасность и целостность + +- сервер проверяет все ID и комбинации; +- клиент не передаёт пути файлов серверу; +- протокол содержит только числовые option/choice ID; +- сообщения имеют максимальный размер и максимальное число записей; +- сервер нормализует дубликаты option ID; +- неизвестные значения не записываются в БД; +- стоимость изменения рассчитывается сервером; +- unlock condition проверяется сервером; +- клиентский каталог не считается доказательством доступности; +- журналировать несовпадение версии и попытки недопустимых изменений. + +## 20. Сборка, доставка и откат + +### Сборка + +- закреплённые submodule revisions; +- asset manifest с SHA-256; +- генерация клиентского и серверного каталога из одного источника; +- сборка WarcraftXL Win32 и Host x64; +- сборка MPQ; +- автоматическая проверка оригинального `Wow.exe`; +- формирование launcher manifest. + +### Версионирование + +- `customization_protocol_version`; +- `customization_catalog_version`; +- `customization_asset_version`; +- совместимая версия WarcraftXL runtime. + +### Откат + +- сервер умеет не отправлять расширенные сообщения; +- клиент при отсутствии данных показывает стандартную внешность; +- отключение модуля не блокирует вход персонажа; +- миграция БД не удаляет стандартные параметры; +- предыдущие MPQ/runtime хранятся как отдельный release artifact; +- неизвестные сохранённые choices не удаляются автоматически без миграции. + +## 21. Оценка трудоёмкости + +Для одного разработчика при наличии подготовленных ассетов: + +| Работа | Оценка | +|---|---:| +| Адаптация и исправление equip-extension | 4–7 дней | +| Независимые косметические каналы | 4–7 дней | +| Asset pipeline | 3–5 дней | +| Серверное хранение и протокол | 4–7 дней | +| Текстурные слои и geoset | 5–10 дней | +| Новый UI создания/изменения | 5–8 дней | +| Полный вертикальный срез одной расы | 5–10 дней | +| Каждая следующая раса | 2–5 дней | +| Стабилизация и regression | 7–12 дней | + +Ориентиры: + +- технический прототип одной расы: 1–2 недели; +- production-вертикаль людей: 3–5 недель; +- все десять рас WotLK: 2–3 месяца; +- насыщенность категориями, близкая к retail: 3–6 месяцев. + +Главный переменный фактор — подготовка и проверка ассетов, а не серверная схема. + +## 22. Рекомендуемый первый milestone + +Вертикальный срез для людей обоих полов: + +- штатные пять категорий; +- одна текстурная категория: шрамы; +- два независимых M2-канала: серьги и аксессуар для волос; +- серверное сохранение; +- snapshot на экране выбора; +- видимость другим игрокам; +- изменение через парикмахерскую; +- камера по категориям; +- корректная работа со шлемом; +- один полный набор automated/manual acceptance checks. + +Этот milestone должен подтвердить всю архитектуру до масштабирования на остальные расы. + +## 23. Критерии готовности production-версии + +- [ ] `Wow.exe` идентичен оригиналу по SHA-256. +- [ ] Все расширения поставляются через WarcraftXL и MPQ. +- [ ] Клиент и сервер используют одинаковую версию каталога. +- [ ] Внешность сохраняется после выхода и перезапуска клиента. +- [ ] Экран создания, экран выбора и модель в мире совпадают. +- [ ] Другие игроки видят подтверждённую сервером внешность. +- [ ] Недоступные варианты невозможно применить изменённым клиентом. +- [ ] Смена/снятие варианта не оставляет collection M2. +- [ ] Нет placeholder-моделей из мусорных строк `ItemDisplayInfo.dbc`. +- [ ] Нет заметных утечек памяти при многократном preview. +- [ ] Отсутствующий ассет не приводит к падению клиента. +- [ ] Все расы и оба пола проходят тестовую матрицу. +- [ ] Камера корректно кадрирует низких, средних и высоких персонажей. +- [ ] UI работает на 4:3, 16:9, 16:10 и разных UI scale. +- [ ] Реализован и проверен rollback. +- [ ] Описан процесс добавления новой категории, choice и ассета. + +## 24. Открытые решения перед началом реализации + +- точная ревизия `wxl-equip-extension` для закрепления; +- список категорий первого релиза; +- исходный retail build для моделей; +- набор моделей для вертикального среза людей; +- формат единого каталога: JSON, CSV или генератор из SQL/YAML; +- транспорт custom packets между WarcraftXL и AzerothCore; +- способ передачи snapshots на экране выбора; +- политика скрытия аксессуаров под шлемом; +- правила доступности и разблокировки вариантов; +- использование парикмахерской или отдельного UI изменения внешности; +- лимит косметических M2 на одного персонажа; +- политика хранения выбранных Blizzard-ассетов и доступа к ним; +- минимальная поддерживаемая версия launcher/runtime.