using HarmonyLib;
using UnityEngine;
namespace NecromancerTome
{
///
/// Тело (вид от третьего лица и для других игроков) держит нож-для-нитей обычным хватом ножа, а не луком (16.10, скрин
/// от третьего лица: «у персонажа запястье вывихнуто» - анимация деревянного лука тянет правую кисть с ножом). Хват
/// предмета один на все модели (HoldType 68 нужен рукам первого лица - основа позы HandPose.PresetThread), поэтому
/// подменяется только параметр аниматора WeaponHoldType/WeaponCarry у тел, кроме рук первого лица, и место ножа в
/// руке тела. Подбор на лету: necroheld tphold N (0 - выключить подмену).
///
public static class ThreadKnifeBody
{
public static int TpHold = 36;
public static bool Applies(EntityAlive _e)
{
return TpHold > 0 && _e != null && _e.inventory?.holdingItem?.Name == CinerariumThreads.ThreadKnifeName;
}
}
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController._setInt), new[] { typeof(int), typeof(int), typeof(bool) })]
public static class Patch_AvatarMultiBodyController_setInt_ThreadKnife
{
public static bool Prefix(AvatarMultiBodyController __instance, int _propertyHash, int _value)
{
bool hold = _propertyHash == AvatarController.weaponHoldTypeHash;
if (!hold && _propertyHash != AvatarController.weaponCarryHash || !ThreadKnifeBody.Applies(__instance.Entity))
{
return true;
}
BodyAnimator fp = (__instance as AvatarLocalPlayerController)?.FPSArms;
int tp = hold ? ThreadKnifeBody.TpHold : AnimationDelayData.AnimationDelay[ThreadKnifeBody.TpHold].Carry;
foreach (BodyAnimator b in __instance.BodyAnimators)
{
Animator a = b.Animator;
int v = b == fp ? _value : tp;
if (a != null && a.GetInteger(_propertyHash) != v)
{
a.SetInteger(_propertyHash, v);
}
}
return false; // без рассылки по сети: у других игроков мод ставит то же сам
}
}
/// Место ножа в руке тела - по хвату ножа (игра берёт смещение по HoldType предмета).
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.SetInRightHand))]
public static class Patch_AvatarMultiBodyController_SetInRightHand_ThreadKnife
{
public static void Postfix(AvatarMultiBodyController __instance, Transform _transform)
{
EntityAlive e = __instance.Entity;
if (_transform == null || !ThreadKnifeBody.Applies(e) || e.emodel.IsFPV && !e.isEntityRemote)
{
return;
}
AnimationGunjointOffsetData.AnimationGunjointOffsets o = AnimationGunjointOffsetData.AnimationGunjointOffset[ThreadKnifeBody.TpHold];
_transform.localPosition = o.position;
_transform.localRotation = Quaternion.Euler(o.rotation);
}
}
[HarmonyPatch(typeof(AvatarMultiBodyController), nameof(AvatarMultiBodyController.SwitchModelAndView))]
public static class Patch_AvatarMultiBodyController_SwitchModelAndView_ThreadKnife
{
public static void Postfix(AvatarMultiBodyController __instance, bool _bFPV)
{
Transform t = __instance.heldItemTransform;
if (t == null || _bFPV || !ThreadKnifeBody.Applies(__instance.Entity))
{
return;
}
AnimationGunjointOffsetData.AnimationGunjointOffsets o = AnimationGunjointOffsetData.AnimationGunjointOffset[ThreadKnifeBody.TpHold];
t.localPosition = o.position;
t.localEulerAngles = o.rotation;
}
}
}