Стрела: защита от NullReference в GetDismemberChance (+ какое звено пустое - в лог); necrourn probe - что урна видит в зоне и что выбрала; necrofire

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-23 16:24:10 +03:00
co-authored by Claude Opus 5.5
parent 3ffb90cc57
commit f372660e39
4 changed files with 92 additions and 50 deletions
+51
View File
@@ -0,0 +1,51 @@
using System;
using HarmonyLib;
using UnityEngine;
namespace NecromancerTome
{
/// <summary>
/// Стрела: NullReferenceException в ItemAction.GetDismemberChance (23.10.2026). Вызывается из ProjectileMoveScript.checkCollision
/// аргументом к ItemActionAttack.Hit - поэтому в первых логах исключение выглядело как ошибка «внутри Hit» (метод был встроен).
/// Пустое звено цепочки actionData.invData.holdingEntity.inventory / invData.item у стрелы, запомнившей данные лука при выстреле.
/// Исключение вылетало раньше, чем стрела сменит состояние, и она «попадала» снова каждый шаг физики - пачки по 6-19 ошибок.
/// Здесь: при исключении шанс отстрела конечности 0 (стрела долетает как обычно), в лог - какое звено пустое (не больше
/// MaxLogs раз за запуск). Причина звена - выяснить по этим строкам.
/// </summary>
[HarmonyPatch(typeof(ItemAction), nameof(ItemAction.GetDismemberChance))]
public static class Patch_ItemAction_GetDismemberChance_Guard
{
const int MaxLogs = 5;
static int _logged;
public static Exception Finalizer(Exception __exception, ItemActionData _actionData, WorldRayHitInfo hitInfo, ref float __result)
{
if (__exception == null)
{
return null;
}
__result = 0f;
if (_logged < MaxLogs)
{
_logged++;
try
{
ItemInventoryData inv = _actionData?.invData;
EntityAlive holder = inv?.holdingEntity;
Debug.Log("[NecromancerTome] DismemberGuard: " + __exception.GetType().Name + " в GetDismemberChance - actionData " +
(_actionData == null ? "NULL" : _actionData.GetType().Name) +
", invData " + (inv == null ? "NULL" : "slot " + inv.slotIdx) +
", item " + (inv?.item == null ? "NULL" : inv.item.Name) +
", holdingEntity " + (holder == null ? "NULL" : holder.GetType().Name + " " + holder.entityId + (holder.IsDead() ? " dead" : "")) +
", inventory " + (holder == null ? "-" : holder.inventory == null ? "NULL" : "в руке " + holder.inventory.holdingItem?.Name) +
", tag " + (hitInfo?.tag ?? "NULL") + " - шанс отстрела 0");
}
catch (Exception e2)
{
Debug.Log("[NecromancerTome] DismemberGuard: не удалось описать - " + e2.Message);
}
}
return null; // проглотить: стрела долетает и попадает как обычно
}
}
}