Прилив: нож пересоздаётся только при свободной руке, сбой не ломает руку
Тест 10.10: NRE в Hand.Unequip оставлял Hand.isSwitching = true - рука переставала брать что-либо до перезапуска. Теперь: ножи в других слотах помечаются к пересборке, нож в руке пересоздаётся, когда нет смены предмета и удара; сбой перехватывается, isSwitching снимается, Reconcile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7d87903302
commit
523b9edcd9
+76
-12
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>Нож в руке ждёт пересоздания (сменились хват/модель).</summary>
|
||||
static bool _recreate;
|
||||
|
||||
/// <summary>«Собранный» предмет перестаёт совпадать со слотом (NeedsRebuild): копия того же ножа с другим Seed.
|
||||
/// Не ItemValue.None (тест 10.10): Hand.Unequip читает класс предмета у собранного - NRE.</summary>
|
||||
static void MarkStale(ItemInventoryData _d)
|
||||
{
|
||||
ItemValue pv = (_d.physicalItemValue ?? _d.itemValue).Clone();
|
||||
pv.Seed = (ushort)(pv.Seed + 1);
|
||||
_d.physicalItemValue = pv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пересоздать нож в руке: повторный выбор того же слота снимает его и собирает заново (Hand.SelectHoldingMode).
|
||||
/// Только когда рука свободна - не идёт смена предмета и удар; иначе ждём кадр. Тест 10.10: при сбое внутри
|
||||
/// SelectHoldingMode игра оставляла Hand.isSwitching = true навсегда, и рука переставала брать что-либо до
|
||||
/// перезапуска («после ошибки не получается переключиться на что-либо ещё»). Поэтому сбой перехватываем и
|
||||
/// возвращаем руку в рабочее состояние.
|
||||
/// </summary>
|
||||
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 ? ", в руке пересоздан" : ""));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- сердце
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user