diff --git a/HarmonySrc/HeldTweak.cs b/HarmonySrc/HeldTweak.cs index ee0e7dd..11b058b 100644 --- a/HarmonySrc/HeldTweak.cs +++ b/HarmonySrc/HeldTweak.cs @@ -142,6 +142,10 @@ namespace NecromancerTome case "scale" when Num(_params, 1, out float s) && s > 0f: HeldTweak.Scale = s; break; + case "tphold" when Num(_params, 1, out float th): + ThreadKnifeBody.TpHold = (int)th; + Out("хват тела для ножа-для-нитей: " + ThreadKnifeBody.TpHold + (ThreadKnifeBody.TpHold > 0 ? "" : " (выкл - как у рук)") + "; место в руке - при следующем доставании"); + return; case "hold" when Num(_params, 1, out float h): Out(HeldTweak.SetHold((int)h)); return; diff --git a/HarmonySrc/ThreadKnifeBody.cs b/HarmonySrc/ThreadKnifeBody.cs new file mode 100644 index 0000000..4e33743 --- /dev/null +++ b/HarmonySrc/ThreadKnifeBody.cs @@ -0,0 +1,80 @@ +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; + } + } +}