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; } } }