Хват для нитей: основа 68, поза рук мода, нож в левой руке

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-16 22:58:28 +03:00
co-authored by Claude Opus 5.5
parent bf334c5c44
commit ed4015ecee
3 changed files with 134 additions and 3 deletions
+3 -2
View File
@@ -2028,8 +2028,9 @@
<item name="necroWpnBladeNecroKnifeThread">
<property name="Extends" value="necroWpnBladeNecroKnife"/>
<property name="CreativeMode" value="None"/>
<!-- HoldType 52 (стриппер) - 16.10 «нож в режиме нитей держится странно»: огромный, поперёк кадра. Пока хват
самого ножа; свой хват «как кисточка» - подбирать в игре (necroheld). -->
<!-- Хват для нитей (16.10, подбор в игре): основа - 68 (деревянный лук), поверх - поза рук мода
(HandPose.PresetThread): нож в левой руке, правая раскрытой ладонью. 52 (стриппер) не подошёл. -->
<property name="HoldType" value="68"/>
<property name="DescriptionKey" value="necroWpnBladeNecroKnifeThreadDesc"/>
<property name="CustomIconTint" value="150, 205, 255"/>
</item>
+20 -1
View File
@@ -23,7 +23,10 @@ namespace NecromancerTome
public static class HandHolds
{
public const string HandItem = "meleeHandPlayer";
public const int None = 0, Deny = 1, PifPaf = 2;
public const int None = 0, Deny = 1, PifPaf = 2, Thread = 3;
/// <summary>Хват для нитей - не сразу: снимок замороженных костей должен быть в покое хвата 68, после доставания.</summary>
const float ThreadDelay = 0.6f;
static float _threadSince = -1f;
/// <summary>Дальность и конус выбора зомби для «отрицания».</summary>
public const float DenyRange = 25f;
@@ -59,6 +62,17 @@ namespace NecromancerTome
public static int Current(EntityPlayerLocal _player)
{
if (_player != null && _player.inventory?.holdingItem?.Name == CinerariumThreads.ThreadKnifeName &&
!SnakeMode.Active && !MindPalace.Active && !Possession.Active && !_player.IsDead())
{
if (_threadSince < 0f)
{
_threadSince = Time.time;
}
bool ready = Time.time - _threadSince >= ThreadDelay && !(_player.Hand != null && _player.Hand.isSwitching);
return ready ? Thread : None;
}
_threadSince = -1f;
if (_player == null || _player.Buffs == null || !IsHand(_player.inventory?.holdingItem) ||
SnakeMode.Active || MindPalace.Active || Possession.Active || _player.IsDead())
{
@@ -104,9 +118,14 @@ namespace NecromancerTome
{
HandPose.PresetPifPaf();
}
else if (want == Thread)
{
HandPose.PresetThread();
}
else
{
HandPose.Enabled = false;
HandPose.KnifeToLeft = false;
}
}
+111
View File
@@ -86,6 +86,7 @@ namespace NecromancerTome
public static void ResetAll()
{
Enabled = false;
KnifeToLeft = false;
Overrides.Clear();
CamOverrides.Clear();
_jabStart = -1f;
@@ -160,6 +161,10 @@ namespace NecromancerTome
b.localRotation = Quaternion.Euler(kv.Value);
}
}
if (KnifeToLeft)
{
ApplyKnifeToLeft();
}
Transform cam = CamOverrides.Count > 0 || _jabStart >= 0f ? Camera() : null;
ApplyJab(cam);
if (cam != null)
@@ -265,6 +270,7 @@ namespace NecromancerTome
/// (сгиб - как у поджатых пальцев «пиф-пафа»), указательный и мизинец прямые.</summary>
public static void PresetDeny()
{
KnifeToLeft = false;
Overrides.Clear();
CamOverrides.Clear();
Overrides["RightArm"] = new Vector3(345.8f, 34.9f, 24.3f);
@@ -291,6 +297,7 @@ namespace NecromancerTome
/// сомкнуты и смотрят к прицелу, безымянный и мизинец поджаты, большой вверх. Кисть - от камеры.</summary>
public static void PresetPifPaf()
{
KnifeToLeft = false;
Overrides.Clear();
CamOverrides.Clear();
Overrides["RightArm"] = new Vector3(330.8f, 34.9f, 24.3f);
@@ -313,6 +320,110 @@ namespace NecromancerTome
Enabled = true;
}
/// <summary>Нож в левой кисти (хват для нитей): корень модели в руке ставится каждый кадр от LeftHand. Смещение -
/// снимок хвата 68 (деревянный лук) 16.10, где нож лежал в левой руке («Нож в левой руке»).</summary>
public static bool KnifeToLeft;
static readonly Vector3 KnifeLeftPos = new Vector3(-0.0832f, -0.0354f, 0.0186f);
static readonly Quaternion KnifeLeftRot = new Quaternion(0.56471f, -0.62192f, -0.41297f, 0.35182f);
static void ApplyKnifeToLeft()
{
Transform lh = Bone("LeftHand");
Transform m = HeldTweak.Model();
if (lh != null && m != null)
{
m.SetPositionAndRotation(lh.TransformPoint(KnifeLeftPos), lh.rotation * KnifeLeftRot);
}
}
/// <summary>Хват для нитей (16.10, подбор с пользователем: «Нож в левую руку, а правую сделай как в том хвате, где
/// ты говорил что она перебирает нити»): основа - HoldType 68 (деревянный лук, items.xml); левая рука поднята и
/// отведена влево, нож в ней; правая - раскрытая ладонь хвата 64 (бинт), пересчитанная под плечо хвата 68 так,
/// чтобы кисть стояла там же относительно камеры (scratchpad ik.py).</summary>
public static void PresetThread()
{
Overrides.Clear();
CamOverrides.Clear();
Overrides["RightShoulder"] = new Vector3(0.0f, 180.0f, 180.0f);
Overrides["Right_sup_shoulder_01"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["Right_sup_shoulder_02"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["Right_sup_trap_01"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["RightArm"] = new Vector3(311.4f, 24.9f, 39.2f);
Overrides["Right_sup_arm_01"] = new Vector3(0.0f, 0.0f, 358.2f);
Overrides["RightArmRoll"] = new Vector3(357.9f, 0.0f, 0.0f);
Overrides["RightForeArm"] = new Vector3(0.0f, 79.9f, 0.0f);
Overrides["Right_sup_elbow_00"] = new Vector3(0.0f, 332.8f, 0.0f);
Overrides["RightForeArmRoll"] = new Vector3(8.7f, 0.0f, 0.0f);
Overrides["RightHand"] = new Vector3(7.2f, 346.5f, 5.4f);
Overrides["RightHandIndex0"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["Right_sup_index_00"] = new Vector3(0.0f, 0.0f, 17.3f);
Overrides["Right_sup_index_00_palm"] = new Vector3(0.0f, 0.0f, 15.6f);
Overrides["RightHandIndex1"] = new Vector3(2.6f, 2.9f, 31.3f);
Overrides["Right_sup_index_01_under"] = new Vector3(0.0f, 0.0f, 3.5f);
Overrides["RightHandIndex2"] = new Vector3(0.0f, 0.0f, 52.8f);
Overrides["Right_sup_index_02"] = new Vector3(0.0f, 0.0f, 333.6f);
Overrides["Right_sup_index_02_under"] = new Vector3(0.0f, 0.0f, 5.1f);
Overrides["RightHandIndex3"] = new Vector3(0.0f, 0.0f, 77.0f);
Overrides["Right_sup_index_03"] = new Vector3(0.0f, 0.0f, 321.5f);
Overrides["RightHandIndex4"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["RightHandMiddle0"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["Right_sup_middle_00"] = new Vector3(0.0f, 0.0f, 32.1f);
Overrides["Right_sup_middle_00_palm"] = new Vector3(0.0f, 0.0f, 28.8f);
Overrides["RightHandMiddle1"] = new Vector3(0.0f, 0.0f, 57.7f);
Overrides["Right_sup_middle_01_under"] = new Vector3(0.0f, 0.0f, 5.7f);
Overrides["RightHandMiddle2"] = new Vector3(0.0f, 0.0f, 85.0f);
Overrides["Right_sup_middle_02"] = new Vector3(0.0f, 0.0f, 317.5f);
Overrides["Right_sup_middle_02_under"] = new Vector3(0.0f, 0.0f, 5.1f);
Overrides["RightHandMiddle3"] = new Vector3(0.0f, 0.0f, 77.0f);
Overrides["Right_sup_middle_03"] = new Vector3(0.0f, 0.0f, 321.5f);
Overrides["RightHandMiddle4"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["RightHandPinky0"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["Right_sup_pinky_00"] = new Vector3(0.0f, 0.0f, 45.0f);
Overrides["Right_sup_pinky_00_palm"] = new Vector3(0.0f, 0.0f, 45.0f);
Overrides["RightHandPinky1"] = new Vector3(0.2f, 353.1f, 92.0f);
Overrides["Right_sup_pinky_01_under"] = new Vector3(0.0f, 0.0f, 5.6f);
Overrides["RightHandPinky2"] = new Vector3(0.0f, 0.0f, 84.0f);
Overrides["Right_sup_pinky_02"] = new Vector3(0.0f, 0.0f, 318.0f);
Overrides["Right_sup_pinky_02_under"] = new Vector3(0.0f, 0.0f, 5.2f);
Overrides["RightHandPinky3"] = new Vector3(0.0f, 0.0f, 78.0f);
Overrides["Right_sup_pinky_03"] = new Vector3(0.0f, 0.0f, 321.0f);
Overrides["RightHandPinky4"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["RightHandRing0"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["Right_sup_ring_00"] = new Vector3(0.0f, 0.0f, 33.0f);
Overrides["Right_sup_ring_00_palm"] = new Vector3(0.0f, 0.0f, 33.0f);
Overrides["RightHandRing1"] = new Vector3(358.6f, 355.2f, 66.1f);
Overrides["Right_sup_ring_01_under"] = new Vector3(0.0f, 0.0f, 5.5f);
Overrides["RightHandRing2"] = new Vector3(0.0f, 0.0f, 83.0f);
Overrides["Right_sup_ring_02"] = new Vector3(0.0f, 0.0f, 318.5f);
Overrides["Right_sup_ring_02_under"] = new Vector3(0.0f, 0.0f, 5.1f);
Overrides["RightHandRing3"] = new Vector3(0.0f, 0.0f, 77.0f);
Overrides["Right_sup_ring_03"] = new Vector3(0.0f, 0.0f, 321.5f);
Overrides["RightHandRing4"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["RightHandThumb1"] = new Vector3(27.9f, 75.4f, 33.2f);
Overrides["RightHandThumb2"] = new Vector3(0.0f, 0.0f, 15.8f);
Overrides["Right_sup_thumb_01"] = new Vector3(0.0f, 0.0f, 352.1f);
Overrides["Right_sup_thumb_01_under"] = new Vector3(0.0f, 0.0f, 1.2f);
Overrides["RightHandThumb3"] = new Vector3(0.0f, 0.0f, 17.9f);
Overrides["Right_sup_thumb_02"] = new Vector3(0.0f, 0.0f, 351.0f);
Overrides["RightHandThumb4"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["necroKnifePrefab(Clone)"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["boneShiv_LOD0"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["boneShiv_LOD1"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["boneShiv_LOD2"] = new Vector3(0.0f, 0.0f, 0.0f);
Overrides["RightForeArmRoll1"] = new Vector3(3.5f, 0.0f, 0.0f);
Overrides["RightForeArmRoll2"] = new Vector3(7.0f, 0.0f, 0.0f);
Overrides["RightForeArmRoll3"] = new Vector3(10.5f, 0.0f, 0.0f);
Overrides["RightForeArmRoll4"] = new Vector3(14.0f, 0.0f, 0.0f);
Overrides["Right_sup_wrist_00"] = new Vector3(0.0f, 0.0f, 357.5f);
Overrides["Right_sup_wrist_01"] = new Vector3(0.0f, 347.6f, 0.0f);
Overrides["Right_sup_wrist_02"] = new Vector3(0.0f, 0.0f, 356.8f);
Overrides["Right_sup_wrist_03"] = new Vector3(0.0f, 347.6f, 0.0f);
Overrides["LeftArm"] = new Vector3(329.6f, 42.5f, 8.5f);
KnifeToLeft = true;
Unfreeze();
Enabled = true;
}
public static string F(float _v) => _v.ToString("0.#", CultureInfo.InvariantCulture);
public static string F(Vector3 _v) => F(_v.x) + " " + F(_v.y) + " " + F(_v.z);
}