diff --git a/HarmonySrc/Possession.cs b/HarmonySrc/Possession.cs index ad8f26f..8a87b55 100644 --- a/HarmonySrc/Possession.cs +++ b/HarmonySrc/Possession.cs @@ -144,13 +144,14 @@ namespace NecromancerTome /// Камера - позади и выше головы зомби. public const float CamBack = 2.6f; /// Вид от первого лица (указание 13.10): клавиша ~/ё - как переключение вида у персонажа в игре - /// (QuickMenu, по умолчанию Backquote; и CameraChange геймпада), каждое вселение начинается от третьего лица. Камера - в голове, голова сжата - /// (HideHead), положение глаз сглажено (FpSmooth) - голова зомби на ходу мотается. + /// (QuickMenu, по умолчанию Backquote; и CameraChange геймпада), каждое вселение начинается от третьего лица. Камера - в голове, тело - только тень + /// (HideBody), положение глаз сглажено (FpSmooth) - голова зомби на ходу мотается. public static bool FirstPerson; public const float FpForward = 0.12f, FpSmooth = 12f; static Vector3 _fpEye; - static Transform _hiddenHead; - static Vector3 _hiddenHeadScale; + static readonly List _hiddenRenderers = new List(); + static readonly List _hiddenModes = new List(); + static EntityAlive _hiddenBody; public const float CamUp = 0.6f; /// Как далеко зомби замечают одержимого: зрение зомби - 30 м (entityclasses.xml SightRange). public const float TauntRange = 30f; @@ -354,7 +355,7 @@ namespace NecromancerTome } Active = false; FirstPerson = false; - HideHead(null); + HideBody(null); RatLoot.CloseIfViewing(); WolfBag.CloseWindow(); RatPhase.Stop(GameManager.Instance?.World, Zombie, "выход из одержимости"); @@ -579,7 +580,7 @@ namespace NecromancerTome _fpEye = Vector3.zero; if (!FirstPerson) { - HideHead(null); + HideBody(null); } Debug.Log("[NecromancerTome] Possession: вид от " + (FirstPerson ? "первого" : "третьего") + " лица"); } @@ -2024,26 +2025,39 @@ namespace NecromancerTome _flyZoomHeld = false; } - /// Голова одержимого сжата почти в точку, пока вид от первого лица, - иначе камера внутри черепа - /// (у зомби модель цельная, отдельных рук, как у персонажа, нет). Ставится каждый кадр после аниматора; - /// null - вернуть прежний масштаб. - static void HideHead(Transform _head) + /// Тело одержимого в виде от первого лица - только тень (тест 13.10: изнутри видно тело, у паука на + /// бегу лапы и череп в кадре; сжатие одной головы не спасало). Видимость - дело своего экрана: другие игроки + /// рисуют этого зомби сами и видят его как обычно; так же игра прячет тело персонажа от первого лица. + /// Рендеры собираются один раз на вход в вид; null - вернуть каждому прежний режим тени. + /// + /// ПАМЯТЬ. Ссылки на рендеры держим только пока вид от первого лица (null чистит список). + static void HideBody(EntityAlive _z) { - if (_hiddenHead != null && _hiddenHead != _head) - { - _hiddenHead.localScale = _hiddenHeadScale; - _hiddenHead = null; - } - if (_head == null) + if (_hiddenBody == _z) { return; } - if (_hiddenHead == null) + for (int i = 0; i < _hiddenRenderers.Count; i++) { - _hiddenHead = _head; - _hiddenHeadScale = _head.localScale; + if (_hiddenRenderers[i] != null) + { + _hiddenRenderers[i].shadowCastingMode = _hiddenModes[i]; + } } - _head.localScale = Vector3.one * 0.001f; + _hiddenRenderers.Clear(); + _hiddenModes.Clear(); + _hiddenBody = _z; + if (_z == null || _z.emodel == null) + { + return; + } + _z.emodel.GetComponentsInChildren(true, _hiddenRenderers); + for (int i = 0; i < _hiddenRenderers.Count; i++) + { + _hiddenModes.Add(_hiddenRenderers[i].shadowCastingMode); + _hiddenRenderers[i].shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly; + } + Debug.Log("[NecromancerTome] Possession: тело " + _z.EntityName + " - только тень, рендеров " + _hiddenRenderers.Count); } /// Из постфикса vp_FPCamera.LateUpdate: камера позади и выше головы зомби, не сквозь стены. @@ -2065,13 +2079,12 @@ namespace NecromancerTome Quaternion rot = Quaternion.Euler(-_pitch, _yaw, 0f); if (FirstPerson) { - // Положение головы - уже после аниматора (мы в LateUpdate камеры), до сжатия: сжатие масштаба - // самой кости её положения не меняет. + // Положение головы - уже после аниматора (мы в LateUpdate камеры). Vector3 want = anchor + rot * Vector3.forward * FpForward; _fpEye = _fpEye == Vector3.zero || (want - _fpEye).sqrMagnitude > 4f ? want : Vector3.Lerp(_fpEye, want, 1f - Mathf.Exp(-FpSmooth * Time.deltaTime)); - HideHead(head); + HideBody(z); _camera.SetPositionAndRotation(_fpEye, rot); return; }