Версия 2.0: свои модели ножа и крови, своя краска блоков через патч атласа
Нож некроманта и Кровь некроманта получили собственные модели, а Пирамида духов - собственную поверхность. Три разных способа, каждый выбран по тому, как устроен сам предмет. НОЖ И КРОВЬ - свои префабы в бандлах мода. Форма записи "#@modfolder(...)?prefab" подтверждена живым примером; геометрия у обоих ванильная, меняются материал и текстура. Текстуры генерируются скриптами (см. _private/tools), а не рисуются: правка вида сводится к правке констант и одному запуску. Нож: состаренная кость, почти чёрная обмотка, пурпур во впадинах, плюс слой под ручную роспись рун - он подмешивается в альбедо и в эмиссию, поэтому руны светятся. Слой пользовательский, генератор его никогда не перезаписывает. Положение росписи посчитано по геометрии: развёртка выгружена из меша, и подобрано смещение, при котором вся роспись ложится на одну плоскую грань. Раньше она перегибалась через кромку, обращённую к игроку. Кровь: банка вместо мешка. Заодно чинится расхождение, жившее с самого начала - описание предмета говорило "Банка, наполненная кровью", а наследуемый medicalBloodBag показывал sackPrefab, обычный мешок. Жидкость перерисована по маскам мешей, а не перекрашена тинтом: тинт предмета на этот меш не действует вовсе, у шейдера Game_EntityTintMaskSSS выигрывает _Color материала. ПИРАМИДА - своя краска в атласе блоков через собственный Harmony-патч. Ваниль своих текстур блоков не умеет: Texture у блока это индекс в готовом атласе, а запись краски несёт только TextureId/PaintCost/Group/SortIndex и никогда путь к картинке. Поэтому CustomBlockPaintPatch дописывает наш слой в массивы атласа на лету. Путь через свою модель (Shape="ModelEntity") пробовался и отложен: там остались нерешёнными столкновения и маджента на дальних экземплярах. Краска лучше тем, что блок остаётся обычным Shape="New" - со всеми работающими столкновениями, наведением по E и правильной посадкой, - а поверхность у него своя. Побочно краска доступна кисточкой под именем "Некротический прах". Параметры атласа не угаданы, а замерены в игре (BlockAtlasProbePatch): 512x512, DXT1 для альбедо и DXT5 для нормалей со specular, 10 мип-уровней, массивы нечитаемые - отсюда GPU-копирование и явные настройки импорта текстур. Зонд оставлен намеренно: номер краски в blocks.xml (608) это длина ванильного uvMapping, и после обновления игры он может сдвинуться - зонд печатает фактические числа при каждом запуске. Патчи обёрнуты целиком: они работают внутри загрузки игры, где вылетевшее исключение срывает шаг загрузки. Resources/necropyramid в коммит не идёт - на него никто не ссылается. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W5F3AVwsusZHMqPBcSQcVJ
This commit is contained in:
co-authored by
Claude Opus 5
parent
026e006c9c
commit
ab1b3eadaf
+95
-2
@@ -66,10 +66,103 @@
|
||||
<property class="TEFeaturePyramidWard" />
|
||||
</property>
|
||||
<property name="Material" value="Msteel_shapes" />
|
||||
<!-- ВЕРНУТО НА Shape="New" 2026-09-10 по решению пользователя: «пока верни пирамиду,
|
||||
которая была у нас изначально».
|
||||
|
||||
Своя модель со своей текстурой требует Shape="ModelEntity", и на этом пути осталось
|
||||
два невылеченных дефекта - разбор и все замеры в BACKLOG.md, раздел про пирамиду:
|
||||
- нет столкновений: при "New" их считает воксельная система блока, а "ModelEntity"
|
||||
берёт от модели, и одного BoxCollider на корне в слое 16 не хватило;
|
||||
- дальние экземпляры рисуются фиолетовым (маджента = не найден шейдер), ближние
|
||||
при этом верны; добавленный LODGroup положения не исправил.
|
||||
|
||||
Всё, что сделано для того пути, сохранено и работает: генератор текстуры
|
||||
_private/tools/make_pyramid_textures.py, сборка _private/Extracted/ShapesUnityProject,
|
||||
бандл Resources/necropyramid. Чтобы вернуться к нему, достаточно заменить Shape на
|
||||
ModelEntity и раскомментировать строку Model ниже. -->
|
||||
<property name="Shape" value="New" />
|
||||
<!-- Своя модель отключена вместе с возвратом на Shape="New" (см. комментарий выше).
|
||||
Строка сохранена: она рабочая, ею подключается наш бандл. -->
|
||||
<property name="Model" value="@:Shapes/pyramid.fbx" />
|
||||
<property name="Texture" value="356" />
|
||||
<property name="TintColor" value="8A4142" />
|
||||
<!-- <property name="Model" value="#@modfolder(NecromancerTome):Resources/necropyramid?necroPyramidPrefab.prefab" /> -->
|
||||
<!-- ModelOffset - ПОЛОЖЕНИЕ МОДЕЛИ, и задавать его надо именно здесь.
|
||||
|
||||
Меш формы из shapes-бандла сделан под воксельную систему: его границы лежат не вокруг
|
||||
начала координат, а в углу (центр -0.50, 0.13, -0.50 при размере 0.51 x 0.26 x 0.50).
|
||||
Как ModelEntity такая модель вылезает из своего куба - что и наблюдалось: «поднялась,
|
||||
вершиной упирается в верхний угол».
|
||||
|
||||
Сначала это лечили сдвигом детей ВНУТРИ префаба. Модель встала верно, но по блоку
|
||||
по-прежнему нельзя было попасть и не работало наведение по E: о сдвиге знал только
|
||||
префаб, а игра держала свой объём для попаданий там, где модель была бы без сдвига.
|
||||
Игрок целился в одно, а попадал мимо.
|
||||
|
||||
Ваниль двигает модель именно этим свойством (у верстака стоит "0,.5,0"), и его игра
|
||||
учитывает целиком - и в отрисовке, и в попаданиях. Значение посчитано скриптом сборки
|
||||
по фактическим границам меша: по X и Z в центр куба, по Y основанием на нижнюю грань.
|
||||
Если меш заменят, скрипт напечатает новое значение в лог. -->
|
||||
<!-- ModelOffset нужен только при ModelEntity; при "New" положение задаёт сама форма.
|
||||
Значение верное, посчитано скриптом сборки - сохранено для возврата.
|
||||
<property name="ModelOffset" value="0.5,-0.495,0.5" /> -->
|
||||
<!-- ПОКРАСКА ВМЕСТО СВОЕЙ ТЕКСТУРЫ, 2026-09-10. Мысль пользователя: «в игре есть
|
||||
кисточка, позволяющая перекрашивать блоки, можем ли мы наложить текстуру через
|
||||
покраску, только заранее?» Можем - именно это свойство Texture и делает.
|
||||
|
||||
Data/Config/painting.xml сопоставляет краски из кисточки с номерами текстур атласа
|
||||
(поле TextureId), а Texture у блока задаёт краску заранее. Доступно 156 красок;
|
||||
выписаны с названиями в _private/Extracted/paints.txt.
|
||||
|
||||
Было 356 (txName_Steel_wall, «оцинкованная стальная стена») - выбор достался от
|
||||
steelShapes вместе с парой Material/Texture и к праху отношения не имел.
|
||||
Пробовали 11 (txName_Gravel, «гравий») - в игре прочиталось как земля.
|
||||
Сейчас 552 (txName_GraniteBlack, «гранит чёрный»): тёмный камень ближе к
|
||||
спрессованному праху, чем крупная осыпь гравия.
|
||||
|
||||
СВОЮ текстуру сюда подставить НЕЛЬЗЯ, проверено по коду игры: у записи краски есть
|
||||
только TextureId, PaintCost, Group, SortIndex - поля с путём к своей картинке нет.
|
||||
TextureId это индекс в уже собранном атласе, а сам атлас лежит в
|
||||
blocktextureatlases_assets_all.bundle среди Addressables игры (рядом с
|
||||
TerrainTextures), и крючка для подмены его модом не нашлось. Своя текстура
|
||||
возможна только через путь ModelEntity со своим бандлом - см. BACKLOG.md.
|
||||
|
||||
Подбирать краску удобнее всего кисточкой прямо в игре: доступны все 156, перезапуск
|
||||
не нужен. Найденный номер прописывается сюда.
|
||||
|
||||
СЕЙЧАС ЭТИ ДВА СВОЙСТВА НЕ РАБОТАЮТ. Блок снова на Shape="ModelEntity" со своей
|
||||
моделью (2026-09-10, после того как префаб довели до вида ванильного): при
|
||||
ModelEntity поверхность даёт материал префаба, а не атлас, и Texture с TintColor
|
||||
не участвуют. Оставлены нетронутыми, чтобы возврат к покраске был ровно двумя
|
||||
правками - Shape на "New" и переключить строку Model ниже.
|
||||
|
||||
TintColor - множитель поверх краски. Взят пепельно-серый с уходом в фиолет, в тон
|
||||
остальному мод-набору. Прежний 8A4142 давал ржаво-красный.
|
||||
|
||||
Texture принимает и ШЕСТЬ значений через запятую - по одному на грань (в ванили есть
|
||||
например value="195,570,570,570,570,570"). Если захочется основание отличать от
|
||||
скатов - делается здесь же, без всякого бандла.
|
||||
|
||||
Хорошие запасные варианты из того же списка: 606 concrete_broken (потрескавшийся
|
||||
бетон), 552 GraniteBlack (чёрный гранит), 443 Rust_black (чёрная ржавчина),
|
||||
385 Green_rusty_metal (зелёная ржавчина, в тон вкраплениям). -->
|
||||
<!-- СВОЯ КРАСКА, 2026-09-10. Это уже НЕ ванильная краска из атласа: текстуру пирамиды
|
||||
добавляет в атлас наш собственный Harmony-патч, HarmonySrc/CustomBlockPaintPatch.cs.
|
||||
Блок при этом остаётся обычным Shape="New" - со всеми работающими столкновениями,
|
||||
наведением по E и правильной посадкой, - а поверхность у него своя.
|
||||
|
||||
608 - это НОМЕР ЗАПИСИ В uvMapping, а не номер краски. Патч печатает его в лог при
|
||||
каждом запуске: «uvMapping entry 608 points at slice 407». Краска дополнительно
|
||||
регистрируется под именем txName_NecroAsh («Некротический прах») и занимает слот 13,
|
||||
но блоку нужен именно номер записи.
|
||||
|
||||
ХРУПКОЕ МЕСТО: 608 - это длина uvMapping ванильной игры, то есть наша запись просто
|
||||
дописывается в конец. Число верно, пока атлас игры не изменился; после обновления игры
|
||||
оно может сдвинуться. Патч печатает фактический номер в лог, поэтому расхождение видно
|
||||
сразу - сверяться при обновлениях.
|
||||
|
||||
TintColor убран намеренно: цвет несёт сама текстура, а тинт - множитель, он бы её
|
||||
исказил. Тот же вывод, что уже сделан по ножу и по банке крови.
|
||||
<property name="TintColor" value="C8BCD2" /> -->
|
||||
<property name="Texture" value="608" />
|
||||
<!-- Real generated art (exch/pyramidOfSpirit.png, copied to
|
||||
UIAtlases/ItemIconAtlas/) added 2026-09-02, per direct instruction - no
|
||||
CustomIconTint alongside it (same lesson as every other real icon in this mod,
|
||||
|
||||
Reference in New Issue
Block a user