diff --git a/HarmonySrc/BloodTide.cs b/HarmonySrc/BloodTide.cs
index 8ca0e20..ff55447 100644
--- a/HarmonySrc/BloodTide.cs
+++ b/HarmonySrc/BloodTide.cs
@@ -57,6 +57,7 @@ namespace NecromancerTome
{
Active = Armed = false;
_swapped = false; // классы предметов игра грузит заново с миром
+ _recreate = false;
_origHoldType = -1;
Heart(false);
Patch_XUiC_HUDStatBar_Update_BloodTide.Forget();
@@ -70,6 +71,7 @@ namespace NecromancerTome
Debug.Log("[NecromancerTome] BloodTide: " + (tide ? "прилив начался" : "прилив схлынул"));
}
SwapKnife(player, Active);
+ TryRecreate(player);
if (Time.time >= _nextBuffCheck && !player.IsDead())
{
_nextBuffCheck = Time.time + 0.5f;
@@ -108,20 +110,82 @@ namespace NecromancerTome
knife.HoldType.Value = _tide ? TideHoldType : _origHoldType;
knife.MeshFile = _tide && !string.IsNullOrEmpty(TideMeshFile) ? TideMeshFile : _origMesh;
_swapped = _tide;
- Inventory inv = _player.inventory;
- ItemInventoryData held = inv?.holdingItemData;
- if (held != null && held.item == knife)
+ Hand hand = _player.Hand;
+ // Ножи в других слотах пояса: «собранная» копия помечается устаревшей - соберутся заново (с новыми хватом и
+ // моделью), когда их возьмут. Нож в руке - в TryRecreate, когда рука свободна.
+ if (hand?.slotDatas != null)
{
- // NeedsRebuild - «собранный» предмет не совпадает с тем, что в слоте: сбрасываем собранный, и
- // повторный выбор того же слота снимает нож и собирает его заново (Hand.SelectHoldingMode).
- // Не ItemValue.None (тест 10.10: NRE в Hand.Unequip - он читает класс предмета у собранного): копия того же
- // ножа с другим Seed - класс прежний, а EqualsExceptUseTimesAndMeta (по нему NeedsRebuild) уже не совпадёт.
- ItemValue pv = (held.physicalItemValue ?? held.itemValue).Clone();
- pv.Seed = (ushort)(pv.Seed + 1);
- held.physicalItemValue = pv;
- inv.SetHoldingItemIdx(inv.holdingItemIdx);
+ foreach (ItemInventoryData d in hand.slotDatas)
+ {
+ if (d != null && d.item == knife && d != hand.equipped && d.physicalItemValue != null)
+ {
+ MarkStale(d);
+ }
+ }
+ }
+ _recreate = true;
+ Debug.Log("[NecromancerTome] BloodTide: нож - хват " + knife.HoldType.Value);
+ }
+
+ /// Нож в руке ждёт пересоздания (сменились хват/модель).
+ static bool _recreate;
+
+ /// «Собранный» предмет перестаёт совпадать со слотом (NeedsRebuild): копия того же ножа с другим Seed.
+ /// Не ItemValue.None (тест 10.10): Hand.Unequip читает класс предмета у собранного - NRE.
+ static void MarkStale(ItemInventoryData _d)
+ {
+ ItemValue pv = (_d.physicalItemValue ?? _d.itemValue).Clone();
+ pv.Seed = (ushort)(pv.Seed + 1);
+ _d.physicalItemValue = pv;
+ }
+
+ ///
+ /// Пересоздать нож в руке: повторный выбор того же слота снимает его и собирает заново (Hand.SelectHoldingMode).
+ /// Только когда рука свободна - не идёт смена предмета и удар; иначе ждём кадр. Тест 10.10: при сбое внутри
+ /// SelectHoldingMode игра оставляла Hand.isSwitching = true навсегда, и рука переставала брать что-либо до
+ /// перезапуска («после ошибки не получается переключиться на что-либо ещё»). Поэтому сбой перехватываем и
+ /// возвращаем руку в рабочее состояние.
+ ///
+ static void TryRecreate(EntityPlayerLocal _player)
+ {
+ if (!_recreate)
+ {
+ return;
+ }
+ Inventory inv = _player.inventory;
+ Hand hand = _player.Hand;
+ ItemInventoryData held = inv?.holdingItemData;
+ if (hand == null || held == null || !SnakeMode.IsKnife(held.item))
+ {
+ _recreate = false; // ножа в руке нет - возьмут, тогда и соберётся (слоты помечены)
+ return;
+ }
+ if (hand.isSwitching || inv.IsHoldingItemActionRunning() || _player.IsDead())
+ {
+ return;
+ }
+ _recreate = false;
+ ItemValue before = held.physicalItemValue;
+ try
+ {
+ MarkStale(held);
+ inv.SetHoldingItemIdx(inv.holdingItemIdx);
+ Debug.Log("[NecromancerTome] BloodTide: нож в руке пересоздан, хват " + held.item.HoldType.Value);
+ }
+ catch (System.Exception ex)
+ {
+ Debug.LogWarning("[NecromancerTome] BloodTide: нож не пересоздан - " + ex.Message + "; рука восстановлена");
+ held.physicalItemValue = before;
+ hand.isSwitching = false;
+ try
+ {
+ hand.Reconcile();
+ }
+ catch (System.Exception ex2)
+ {
+ Debug.LogWarning("[NecromancerTome] BloodTide: Reconcile - " + ex2.Message);
+ }
}
- Debug.Log("[NecromancerTome] BloodTide: нож - хват " + knife.HoldType.Value + (held != null && held.item == knife ? ", в руке пересоздан" : ""));
}
// ---------------------------------------------------------------- сердце
diff --git a/NecromancerHarmony.dll b/NecromancerHarmony.dll
index ff023db..6de571a 100644
Binary files a/NecromancerHarmony.dll and b/NecromancerHarmony.dll differ
diff --git a/NecromancerHarmony.pdb b/NecromancerHarmony.pdb
index 7863f6f..18568ce 100644
Binary files a/NecromancerHarmony.pdb and b/NecromancerHarmony.pdb differ