1.3.0: шкала 20 убийств за уровень, два индикатора, мир между подчинёнными
Уровень навыка игра хранит ОДНИМ БАЙТОМ (ProgressionValue.Write/Read), поэтому старая шкала "одно убийство - один уровень" при max_level=5000 на каждом сохранении откатывала уровень на 256 назад. Снаружи это выглядело как самопроизвольно закрывающиеся рецепты (жалоба со стрима: Слёзы мертвеца открыты, Пир падальщика под замком при 250+ убитых), а тиры 500/2000/3000/5000 были недостижимы в принципе. Подтверждено на двух живых сейвах: sezon8 - 384 убийства при уровне 129, test8 - 303 при уровне 48. Шкала переведена на 20 убийств = 1 уровень, max_level=250 - влезает в байт с запасом. Уровень больше не накапливается, а вычисляется из necroZombieKillsCVar (float, сохраняется честно) и на каждом убийстве, и постфиксом на PlayerDataFile.ToPlayer - последнее чинит старые сейвы само, без команд и новой игры. Открытое при этом не теряется: в старой шкале уровень всегда был не больше счётчика, так что пересчёт может только вернуть украденное переполнением. Отдельно закрыт случай "счётчик пуст, а уровень есть" - счётчик восстанавливается из уровня по старой шкале. Все пороги пересчитаны в уровни, числа убийств не тронуты, кроме воды: 30 на сетку шагом 20 не ложится, по указанию пользователя мод переехал на 20 - туда же, где браслет и Кровавая сфера. Тег necroNecromancyLvl30 удалён. Сходимость всех 18 рецептов (тег -> RecipeTagUnlocked -> unlock_tier) проверена скриптом. Два индикатора: череп в статус-баре показывает уровень (раньше - общее число убийств), фиолетовая шкала над полосой опыта - продвижение внутри уровня, 0..20. Шкала сделана вёрсткой, а не баффом (бафф умеет число, но не полосу), заполнение привязано через XUi-выражение cvar(). Закрывающая скобка у выражения - одна "}", а не "%}": лишний "%" NCalc читает как остаток от деления и ждёт правый операнд, на чём первая проверка в игре и споткнулась. Третья правка: подчинённые зомби больше не дерутся между собой. Девиация выдаёт приказ "бей зомби", а подчинённый сам EntityZombie, и в targetClasses выражается только тип. Постфикс на EAITarget.check вычёркивает подчинённого из кандидатов (зомби выбирает следующего, настоящего врага), префикс на EntityAlive.SetAttackTarget гасит цель на путях мимо выбора - прежде всего месть, когда подчиняют уже дерущихся. Тексты на 13 языках, README (RU+EN), описания для сайта и Nexus приведены к новой шкале. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fbd58ad018
commit
ed5fea5192
@@ -116,4 +116,50 @@
|
||||
<sprite name="blackout" depth="0" sprite="menu_empty" type="sliced" color="[black]" anchor_left="#cam,0,-10" anchor_right="#cam,1,10" anchor_bottom="#cam,0,-10" anchor_top="#cam,1,10" globalopacitymod="0"/>
|
||||
</window>
|
||||
</append>
|
||||
<!-- ФИОЛЕТОВАЯ ШКАЛА НЕКРОМАНТИИ, 2026-09-17. Продиктовано: "Есть индикатор опыта. Это шкала
|
||||
до уровня. А мы сделаем ещё одну шкалу, которая заполняется каждые 20 зомби... Каждое
|
||||
заполнение индикатора пусть добавляет уровень некромантии, а индикатор обнуляет."
|
||||
|
||||
Заполнение считает не вёрстка: necroNecromancyProgressCVar (0..19) пишет
|
||||
HarmonySrc/NecromancyKillCreditPatch.cs на каждом убийстве и при загрузке игрока, деля
|
||||
общее число упокоенных зомби на 20 с остатком. Шкала обнуляется сама собой - вместе с
|
||||
переходом остатка через двадцатку растёт уровень Некромантии (череп в статус-баре).
|
||||
|
||||
ПОЧЕМУ ЭТО ВЁРСТКА, А НЕ ЕЩЁ ОДИН БАФФ. Бафф умеет показать ЧИСЛО (display_value), но не
|
||||
полосу. Полоса - это sprite type="filled" с атрибутом fill 0..1, и живёт она в окне.
|
||||
Взято ровно то окно и ровно тот приём, которым нарисована ванильная полоса опыта:
|
||||
windowToolbelt, три спрайта друг на друге (серая подложка, чёрная рамка fillcenter="false",
|
||||
заливка) - см. Data/Config/XUi_InGame/windows.xml, строки с fill="{xp}". Наша полоса
|
||||
стоит на 12 пикселей выше опыта (pos 0,20 против 0,8) и той же ширины 750.
|
||||
|
||||
ПРИВЯЗКА. fill читает CVar через функцию выражений cvar() - она есть в самой игре
|
||||
(BindingNcalcFunctions.cvar, регистрирует BindingInfoNcalc.VariableStateCVar, который
|
||||
сам перечитывает значение, а не застывает на первом).
|
||||
|
||||
ЗАКРЫВАЮЩАЯ СКОБКА - ОДНА "}", А НЕ "%}". Это не стилистика, а единственная рабочая форма,
|
||||
и первая же проверка в игре (17.09, лог 22-36-46) на этом и споткнулась:
|
||||
|
||||
ERR [XUi] Binding expression can not be evaluated. Binding fill="{% cvar(...) / 20 %}"
|
||||
EXC no viable alternative at input '<EOF>' at line 1:44
|
||||
|
||||
Открывается выражение как "{%", а закрывается просто "}" - так во всех ванильных
|
||||
примерах (Data/Config/XUi_InGame/windows.xml: visible="{% int(windowWidth) >= 300 }",
|
||||
text="{% dictvalue(sandboxvalues, '1') }"). Лишний "%" остаётся ВНУТРИ выражения, а в
|
||||
NCalc это оператор остатка от деления, поэтому парсер честно ждёт после него правый
|
||||
операнд и упирается в конец строки - позиция 44 в сообщении указывает ровно на него.
|
||||
Ошибка разовая, не в каждый кадр: привязка, не сумев вычислиться, гаснет насовсем, то
|
||||
есть полоса просто не работает молча.
|
||||
|
||||
Если полоса когда-нибудь опять не появится или застынет - запасной путь такой: писать из
|
||||
C# готовую долю 0..1 в отдельный CVar и подставлять её без арифметики в вёрстке. Своего XUi-контроллера тут сознательно
|
||||
нет: находит ли движок контроллер из сборки мода, в этом моде так и не проверено (см.
|
||||
комментарий к финальным слайдам выше), а окно с контроллером было бы риском без нужды.
|
||||
|
||||
Цвет 150,60,220 - фиолетовый, как просили; альфа 200, чтобы полоса читалась поверх
|
||||
тёмного HUD, но не спорила с опытом яркостью. -->
|
||||
<append xpath="/windows/window[@name='windowToolbelt']/rect">
|
||||
<sprite depth="1" pos="0,20" height="8" color="[mediumGrey]" sprite="menu_empty2px" globalopacitymod="0" type="sliced" />
|
||||
<sprite depth="9" pos="0,20" height="8" color="[black]" sprite="menu_empty2px" globalopacitymod="0" type="sliced" fillcenter="false" />
|
||||
<sprite depth="4" pos="0,20" height="8" width="750" color="150,60,220,200" globalopacitymod="0" type="filled" fill="{% cvar('necroNecromancyProgressCVar') / 20 }" />
|
||||
</append>
|
||||
</windows>
|
||||
|
||||
Reference in New Issue
Block a user