diff --git a/HarmonySrc/CVarBindingLeakPatch.cs b/HarmonySrc/CVarBindingLeakPatch.cs
new file mode 100644
index 0000000..133b754
--- /dev/null
+++ b/HarmonySrc/CVarBindingLeakPatch.cs
@@ -0,0 +1,42 @@
+using HarmonyLib;
+
+namespace NecromancerTome
+{
+ ///
+ /// Утечка в самой игре, на которую наступала шкала некромантии в поясе (1.3.0+,
+ /// fill="{% cvar('necroNecromancyProgressCVar') / 20 }" в Config/XUi_InGame/windows.xml).
+ ///
+ /// Найдено 28.09 замером (NecroProfiler): FPS 60 -> 30 за 10-15 минут в любом мире, в теле;
+ /// группа окон toolbelt росла 2 -> 23 мс/кадр при неизменных 573 элементах; в режиме змеи пояс
+ /// скрыт - и тормозов нет; перезаход в мир сбрасывает.
+ ///
+ /// Механика (декомпиляция 3.3): BindingNcalcFunctions.cvar при каждом вычислении выражения
+ /// регистрирует НОВЫЙ VariableStateCVar, а BindingInfoNcalc.RegisterVariable добавляет его в
+ /// список без проверки. Новая переменная начинает с 0; если шкала не пуста, её RefreshValue в
+ /// следующем кадре видит «изменилось» -> выражение пересчитывается -> cvar() добавляет ещё одну.
+ /// Плюс одна переменная за кадр, пока CVar не 0, и каждый кадр обходится весь список.
+ ///
+ /// Лечение: одну и ту же CVar в одной привязке регистрируем один раз. Значение cvar() берёт
+ /// прямо у игрока, так что отслеживающая переменная нужна только одна - для «изменилось».
+ ///
+ [HarmonyPatch(typeof(BindingInfoNcalc), nameof(BindingInfoNcalc.RegisterVariable))]
+ public static class Patch_BindingInfoNcalc_RegisterVariable_CVarLeak
+ {
+ public static bool Prefix(BindingInfoNcalc __instance, BindingInfoNcalc.VariableStateAbs _var, ref bool __result)
+ {
+ if (!(_var is BindingInfoNcalc.VariableStateCVar added))
+ {
+ return true;
+ }
+ foreach (BindingInfoNcalc.VariableStateAbs existing in __instance.variables)
+ {
+ if (existing is BindingInfoNcalc.VariableStateCVar known && known.cVarName == added.cVarName)
+ {
+ __result = true;
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
diff --git a/HarmonySrc/CustomBlockPaintPatch.cs b/HarmonySrc/CustomBlockPaintPatch.cs
index bd5d84b..5ec8cf6 100644
--- a/HarmonySrc/CustomBlockPaintPatch.cs
+++ b/HarmonySrc/CustomBlockPaintPatch.cs
@@ -269,7 +269,15 @@ namespace NecromancerTome
return -1;
}
- if (ours.width != src.width || ours.height != src.height)
+ // Качество текстур ниже Full уменьшает атлас игры вдвое/вчетверо (Half: 256 вместо 512).
+ // Раньше тут был пропуск - и пирамида оставалась без текстуры (28.09, игра на Half).
+ // Наши уменьшенные копии уже лежат в мипах: при Half берём с мипа 1, при Quarter - с 2.
+ int mipOffset = 0;
+ while (mipOffset < ours.mipmapCount && (ours.width >> mipOffset) > src.width)
+ {
+ mipOffset++;
+ }
+ if ((ours.width >> mipOffset) != src.width || (ours.height >> mipOffset) != src.height)
{
Debug.LogWarning("[NecromancerTome] CustomBlockPaint: " + label + " size mismatch, " +
"atlas is " + src.width + "x" + src.height + " but ours is " +
@@ -283,11 +291,11 @@ namespace NecromancerTome
" - skipped");
return -1;
}
- if (ours.mipmapCount != src.mipmapCount)
+ if (ours.mipmapCount - mipOffset < src.mipmapCount)
{
Debug.LogWarning("[NecromancerTome] CustomBlockPaint: " + label + " mip mismatch, " +
"atlas has " + src.mipmapCount + " but ours has " + ours.mipmapCount +
- " - skipped");
+ " (from mip " + mipOffset + ") - skipped");
return -1;
}
@@ -303,11 +311,14 @@ namespace NecromancerTome
// GPU-side copy: the game's arrays are non-readable, so nothing can be pulled back
// to the CPU. CopyTexture moves whole slices with their mip chains.
for (int i = 0; i < slice; i++) Graphics.CopyTexture(src, i, grown, i);
- Graphics.CopyTexture(ours, 0, grown, slice);
+ for (int mip = 0; mip < src.mipmapCount; mip++)
+ {
+ Graphics.CopyTexture(ours, 0, mip + mipOffset, grown, slice, mip);
+ }
target = grown;
Debug.Log("[NecromancerTome] CustomBlockPaint: " + label + " grown from " + slice +
- " to " + (slice + 1) + " slices");
+ " to " + (slice + 1) + " slices" + (mipOffset > 0 ? ", ours taken from mip " + mipOffset : ""));
return slice;
}
diff --git a/ModInfo.xml b/ModInfo.xml
index 9f6a970..e355626 100644
--- a/ModInfo.xml
+++ b/ModInfo.xml
@@ -4,6 +4,6 @@
-
+
diff --git a/NEXUS_CHANGELOG_1.4.3.txt b/NEXUS_CHANGELOG_1.4.3.txt
new file mode 100644
index 0000000..ad69f32
--- /dev/null
+++ b/NEXUS_CHANGELOG_1.4.3.txt
@@ -0,0 +1,4 @@
+FIX: the frame rate no longer sinks during a session. Before, FPS went from 60 down to 15-30 within 10-15 minutes of playing, even standing still, and only reloading the world brought it back. Thanks to Megaladon43, sanovskiy and zomb1 for the reports and tests.
+The cause is a bug in the game's own UI bindings: an expression that reads a CVar registers one more watcher each time it is recalculated, and a fresh watcher triggers a recalculation again the next frame. The purple Necromancy progress bar above the XP bar (added in 1.3.0) hit exactly that, so it gained one watcher per frame and the game walked the whole growing list every frame. The mod now registers a CVar watcher once per binding.
+FIX: the Pyramid of Heresy is textured again when Texture Quality is set below Full. On lower settings the game's block atlas is smaller than the pyramid texture and the mod used to skip it.
+This is the same fix as in 1.5.1, brought to game 3.2. Drop-in over 1.4.2, saves carry over. For game version 3.2 only; for game 3.3 use 1.5.1. Single-player. The mod ships Harmony libraries, so EasyAntiCheat must be off.
diff --git a/NEXUS_FILE_SUMMARY_1.4.3.txt b/NEXUS_FILE_SUMMARY_1.4.3.txt
new file mode 100644
index 0000000..43400ac
--- /dev/null
+++ b/NEXUS_FILE_SUMMARY_1.4.3.txt
@@ -0,0 +1 @@
+FPS fix for game 3.2: the frame rate no longer sinks over a session (a bug in the game's UI bindings, hit by the Necromancy bar since 1.3.0). Pyramid of Heresy textured again below Full texture quality. Drop-in over 1.4.2.
diff --git a/NecromancerHarmony.dll b/NecromancerHarmony.dll
index c2e2a06..c52439f 100644
Binary files a/NecromancerHarmony.dll and b/NecromancerHarmony.dll differ
diff --git a/NecromancerHarmony.pdb b/NecromancerHarmony.pdb
index aa1279e..67293bd 100644
Binary files a/NecromancerHarmony.pdb and b/NecromancerHarmony.pdb differ
diff --git a/README.md b/README.md
index f31cd2e..2bcdd6e 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
*English version below — scroll past the Russian half.*
-**Версия 1.4.2** — для 7 Days to Die 3.2 (с 3.3 experimental не совместима и сама об этом скажет). Автор: Alex Cube.
+**Версия 1.4.3** — для 7 Days to Die 3.2 (с 3.3 experimental не совместима и сама об этом скажет). Автор: Alex Cube.
- Страница мода: https://www.alexcube.ru/7-days-to-die-moi-mody/kniga-nekromanta-necromancer-s-tome/
- Nexus Mods: https://www.nexusmods.com/7daystodie/mods/12547
@@ -162,6 +162,8 @@ HUD за этим следят два индикатора: череп в ста
## Статус
+Версия 1.4.3 — **FPS больше не сползает за сессию**. Раньше за 10–15 минут игры FPS падал с 60 до 15–30 даже стоя на месте, и помогал только перезаход в мир. Причина — ошибка в интерфейсных привязках самой игры, на которую наступала фиолетовая шкала некромантии над полосой опыта (с 1.3.0): она набирала по одной отслеживаемой переменной за кадр. Теперь переменная регистрируется один раз. Заодно Пирамида Ереси снова с текстурой при качестве текстур ниже Full.
+
Версия 1.4.2 — **защита от несовместимой версии игры**. Если мод запущен не на той версии игры, под которую собран (эта сборка — для 3.2.x), в главном меню появляется окно «мод несовместим, обновите» с единственной кнопкой «Выйти из игры». Если игрок всё же откроет мир, сохранённое Пространственное хранилище не разбирается и записывается обратно байт в байт — вещи дождутся правильной сборки мода.
Версия 1.4.1 — **исправлено падение FPS**. Красный труп «Жертвы» оставлял в памяти свои текстуры и материалы и не отдавал их до перезапуска игры: за пару часов набегали гигабайты видеопамяти, и FPS падал в разы. Теперь всё убирается вместе с трупом, а сам труп лежит 5 минут, а не час. Урон ножа пересчитывается раз в секунду, а не 10 раз.
@@ -250,7 +252,7 @@ HUD за этим следят два индикатора: череп в ста
# Necromancer's Tome (English)
-**Version 1.4.2** - for 7 Days to Die 3.2 (not compatible with 3.3 experimental, and says so itself). By Alex Cube.
+**Version 1.4.3** - for 7 Days to Die 3.2 (not compatible with 3.3 experimental, and says so itself). By Alex Cube.
- Mod page: https://www.alexcube.ru/7-days-to-die-moi-mody/kniga-nekromanta-necromancer-s-tome/
- Nexus Mods: https://www.nexusmods.com/7daystodie/mods/12547
@@ -412,6 +414,8 @@ story scenes play without stopping time.
## Status
+Version 1.4.3 - **the frame rate no longer sinks during a session**. Before, FPS went from 60 down to 15-30 within 10-15 minutes of playing, even standing still, and only reloading the world brought it back. The cause is a bug in the game's own UI bindings, hit by the purple Necromancy bar above the XP bar (since 1.3.0): it gained one watcher per frame. The watcher is now registered once. Also, the Pyramid of Heresy is textured again when Texture Quality is below Full.
+
Version 1.4.2 - **protection against an incompatible game version**. If the mod runs on a game version it was not built for (this build is for 3.2.x), the main menu shows a "mod is incompatible, please update" window with a single "Quit game" button. And if a world does get opened, the saved Spatial Vault is not parsed but written back byte for byte - its items wait for the right build of the mod.
Version 1.4.1 - **the FPS drop is fixed**. A red Victim corpse left its textures and materials in memory and never gave them back until the game was restarted: within a couple of hours that was gigabytes of video memory, and the frame rate fell several times over. Everything is now cleaned up with the corpse, and the corpse itself stays for 5 minutes instead of an hour. The knife's damage is refreshed once a second instead of 10 times.
diff --git a/Resources/necroatlas b/Resources/necroatlas
index 57cfcfc..bbe308e 100644
Binary files a/Resources/necroatlas and b/Resources/necroatlas differ