diff --git a/HarmonySrc/NecroView.cs b/HarmonySrc/NecroView.cs
index dfc2ec9..423e802 100644
--- a/HarmonySrc/NecroView.cs
+++ b/HarmonySrc/NecroView.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Globalization;
+using HarmonyLib;
using UnityEngine;
using UnityEngine.Scripting;
@@ -29,6 +30,61 @@ namespace NecromancerTome
static Quaternion _lockCam;
static bool _mouseBroken;
+ /// «Выйти из тела» (16.10: «временно мог выйти из тела, когда попрошу? Чтобы мог ходить вокруг тела и
+ /// осматривать»): камера летает свободно - WASD, мышь, пробел/Ctrl - выше/ниже, Shift - быстрее; тело стоит
+ /// (PlayerMoveController.Update пропускается, как при одержимости), поза рук замерла. Выход - End или necroview off.
+ public static bool Free;
+ static Vector3 _freePos;
+ static float _freeYaw, _freePitch;
+ const float FlySpeed = 1.5f;
+
+ public static string StartFree()
+ {
+ string r = Start(0f, 0f, 0.6f);
+ Transform pc = HandPose.Camera();
+ if (!On || pc == null)
+ {
+ return r;
+ }
+ Free = true;
+ _freePos = pc.position;
+ Vector3 e = pc.eulerAngles;
+ _freeYaw = e.y;
+ _freePitch = e.x > 180f ? e.x - 360f : e.x;
+ return "вне тела: WASD, мышь, пробел/Ctrl - выше/ниже, Shift - быстрее, End - вернуться";
+ }
+
+ static void UpdateFree(float _dt)
+ {
+ PlayerMoveController pmc = PlayerMoveController.Instance;
+ Vector2 sens = pmc != null ? pmc.mouseLookSensitivity : Vector2.one * 5f;
+ if (!_mouseBroken)
+ {
+ try
+ {
+ _freeYaw += Input.GetAxis("Mouse X") * sens.x;
+ _freePitch = Mathf.Clamp(_freePitch - Input.GetAxis("Mouse Y") * sens.y, -89f, 89f);
+ }
+ catch (System.Exception e)
+ {
+ _mouseBroken = true;
+ Debug.LogWarning("[NecromancerTome] necroview: мышь не читается (" + e.Message + ")");
+ }
+ }
+ Quaternion rot = Quaternion.Euler(_freePitch, _freeYaw, 0f);
+ Vector3 move = Vector3.zero;
+ if (Input.GetKey(KeyCode.W)) move += Vector3.forward;
+ if (Input.GetKey(KeyCode.S)) move += Vector3.back;
+ if (Input.GetKey(KeyCode.A)) move += Vector3.left;
+ if (Input.GetKey(KeyCode.D)) move += Vector3.right;
+ Vector3 world = rot * move;
+ if (Input.GetKey(KeyCode.Space)) world += Vector3.up;
+ if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.C)) world += Vector3.down;
+ float speed = FlySpeed * (Input.GetKey(KeyCode.LeftShift) ? 4f : 1f);
+ _freePos += world * speed * _dt;
+ _cam.transform.SetPositionAndRotation(_freePos, rot);
+ }
+
public static string Start(float _yaw, float _pitch, float _dist)
{
Transform pc = HandPose.Camera();
@@ -50,7 +106,16 @@ namespace NecromancerTome
_cam = go.AddComponent();
}
_cam.CopyFrom(pl.playerCamera);
- _cam.depth = pl.playerCamera.depth + 50f;
+ // Сразу над камерой игрока, но ПОД камерами интерфейса (16.10: с +50 рисовала поверх меню - «мне из игры не выйти даже»).
+ float above = float.MaxValue;
+ foreach (Camera c in Camera.allCameras)
+ {
+ if (c != _cam && c.depth > pl.playerCamera.depth && c.depth < above)
+ {
+ above = c.depth;
+ }
+ }
+ _cam.depth = above < float.MaxValue ? (pl.playerCamera.depth + above) * 0.5f : pl.playerCamera.depth + 1f;
_cam.nearClipPlane = 0.01f;
_cam.gameObject.SetActive(true);
HandPose.HoldStill = true;
@@ -63,6 +128,7 @@ namespace NecromancerTome
public static void Stop()
{
On = false;
+ Free = false;
HandPose.HoldStill = false;
if (_cam != null)
{
@@ -85,6 +151,16 @@ namespace NecromancerTome
return;
}
float dt = Time.unscaledDeltaTime;
+ if (Free)
+ {
+ if (Input.GetKeyDown(KeyCode.End))
+ {
+ Stop();
+ return;
+ }
+ UpdateFree(dt);
+ return;
+ }
EntityPlayerLocal pl = GameManager.Instance?.World?.GetPrimaryPlayer();
if (Mouse && pl != null && !_mouseBroken)
{
@@ -128,7 +204,7 @@ namespace NecromancerTome
public class ConsoleCmdNecroView : ConsoleCmdAbstract
{
public override string[] getCommands() => new[] { "necroview" };
- public override string getDescription() => "NecromancerTome: осмотр рук со стороны - on [вокруг высота расстояние]|off|set вокруг высота расстояние|mouse [off]|show; мышь или цифровой блок 4/6 8/2 +/- 5";
+ public override string getDescription() => "NecromancerTome: осмотр рук со стороны - on [вокруг высота расстояние]|off|set вокруг высота расстояние|free (выйти из тела, End - назад)|mouse [off]|show; мышь или цифровой блок 4/6 8/2 +/- 5";
static bool Num(List _p, int _i, out float _v)
{
@@ -159,6 +235,9 @@ namespace NecromancerTome
NecroView.Pitch = p2;
NecroView.Dist = d2;
break;
+ case "free":
+ Out(NecroView.StartFree());
+ return;
case "mouse":
NecroView.Mouse = !(_params.Count > 1 && _params[1] == "off");
Out("мышь " + (NecroView.Mouse ? "облетает руки" : "крутит персонажа, облёт - цифровой блок"));
@@ -172,4 +251,19 @@ namespace NecromancerTome
Out(NecroView.On ? "вокруг " + NecroView.F(NecroView.Yaw) + ", высота " + NecroView.F(NecroView.Pitch) + ", расстояние " + NecroView.F(NecroView.Dist) : "осмотр выключен");
}
}
+
+ /// Вне тела (NecroView.Free) тело не ходит и не крутится - как при одержимости.
+ [HarmonyPatch(typeof(PlayerMoveController), nameof(PlayerMoveController.Update))]
+ public static class Patch_PlayerMoveController_Update_NecroView
+ {
+ public static bool Prefix(PlayerMoveController __instance)
+ {
+ if (!NecroView.Free)
+ {
+ return true;
+ }
+ __instance.stopMoving();
+ return false;
+ }
+ }
}