FpArms собирает руки для первого лица по шагам игры (baseRigFPPrefab + голая кожа basePartsFP, аниматор FPPlayerController), пол по зомби (BaseMale/BaseFemale), кожа серая через _Tint, без одежды. ~/ё работает только у списка гуманоидов; подсказка - только им. Коллайдеры рук выключены. Ударов пока нет. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
143 lines
6.0 KiB
C#
143 lines
6.0 KiB
C#
using UnityEngine;
|
||
|
||
namespace NecromancerTome
|
||
{
|
||
/// <summary>
|
||
/// Руки одержимого в виде от первого лица (указание 13.10: «делаем так, как у игрока»). У персонажа игры две
|
||
/// модели: полное тело (его видят другие и он сам со стороны) и отдельные руки для первого лица (baseRigFP,
|
||
/// SDCSUtils.CreateVizFP) - рисуются только у себя. Здесь собираем такие же руки по тем же шагам игры:
|
||
/// скелет baseRigFPPrefab с аниматором FPPlayerController, голая кожа (basePartsFP), без одежды и волос
|
||
/// (указание: «одежду пока не показываем»). Пол - по зомби (IsMale): BaseMale или BaseFemale из
|
||
/// archetypes.xml. Кожа серая (указание: «руки вообще серые - типа зомби их так видит») - цвет _Tint у
|
||
/// материала кожи, как игра красит тон кожи.
|
||
///
|
||
/// Руки - под UFPSRoot камеры игрока, как у персонажа; камеру одержимости мы ставим в голову зомби, руки
|
||
/// едут вместе с ней. Слой HoldingItem - его камера игрока рисует только при ShowHoldingItemLayer(true).
|
||
///
|
||
/// Только гуманоиды обычной комплекции (Allows), указание 13.10.
|
||
///
|
||
/// ПАМЯТЬ. Одна модель рук на время вида от первого лица; Hide выгружает её (SDCSUtils.UnloadViz - материалы
|
||
/// и ссылки на ассеты освобождаются) - на переключении вида и на выходе из одержимости.
|
||
/// </summary>
|
||
public static class FpArms
|
||
{
|
||
/// <summary>Начала имён классов, у кого вид от первого лица (варианты Feral/Radiated/Charged/Infernal - тоже).</summary>
|
||
static readonly string[] Allowed =
|
||
{
|
||
"zombieArlene", "zombieBiker", "zombieBoe", "zombieBowler", "zombieBurnt", "zombieBusinessMan", "zombieDarlene",
|
||
"zombieInmate", "zombieJanitor", "zombieJoe", "zombieLab", "zombieLumberjack", "zombieMaleHazmat", "zombieMarlene",
|
||
"zombieMoe", "zombieNurse", "zombiePartyGirl", "zombieSkateboarder", "zombieSoldier", "zombieSteve", "zombieTomClark",
|
||
"zombieUtilityWorker", "zombieYo",
|
||
};
|
||
|
||
public static readonly Color Tint = new Color(0.55f, 0.56f, 0.55f, 1f);
|
||
|
||
static GameObject _rig;
|
||
static SDCSUtils.TransformCatalog _bones;
|
||
static bool _layerWasShown;
|
||
|
||
public static bool Active => _rig != null;
|
||
|
||
public static bool Allows(EntityAlive _z)
|
||
{
|
||
if (_z == null || !EntityClass.list.TryGetValue(_z.entityClass, out EntityClass cls) || cls?.entityClassName == null)
|
||
{
|
||
return false;
|
||
}
|
||
string name = cls.entityClassName;
|
||
if (name.Contains("Crawler"))
|
||
{
|
||
return false;
|
||
}
|
||
foreach (string a in Allowed)
|
||
{
|
||
if (name.StartsWith(a))
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public static void Show(EntityPlayerLocal _player, EntityAlive _z)
|
||
{
|
||
if (_rig != null || _player == null || _z == null)
|
||
{
|
||
return;
|
||
}
|
||
Archetype arch = Archetype.GetArchetype(_z.IsMale ? "BaseMale" : "BaseFemale");
|
||
Transform cam = _player.cameraTransform;
|
||
if (arch == null || cam == null)
|
||
{
|
||
Debug.LogWarning("[NecromancerTome] FpArms: нет архетипа или камеры - рук не будет");
|
||
return;
|
||
}
|
||
Transform parent = cam.FindInChildren("UFPSRoot") ?? cam;
|
||
Archetype wasArch = SDCSUtils.tmpArchetype;
|
||
SDCSUtils.AssetRefs wasOwner = SDCSUtils.tmpAssetsOwner;
|
||
try
|
||
{
|
||
SDCSUtils.tmpArchetype = arch;
|
||
SDCSUtils.setupRig(ref _rig, ref _bones, SDCSUtils.baseRigFPPrefab, parent, SDCSUtils.FPAnimController);
|
||
SDCSUtils.tmpAssetsOwner = SDCSUtils.GetAssetOwnerForRig(_rig);
|
||
SDCSUtils.setupBase(_rig, _bones, SDCSUtils.basePartsFP, true);
|
||
}
|
||
finally
|
||
{
|
||
SDCSUtils.tmpArchetype = wasArch;
|
||
SDCSUtils.tmpAssetsOwner = wasOwner;
|
||
}
|
||
_rig.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
|
||
_rig.name = "necroZombieArmsFP";
|
||
int layer = LayerMask.NameToLayer("HoldingItem");
|
||
int tinted = 0;
|
||
foreach (SkinnedMeshRenderer smr in _rig.GetComponentsInChildren<SkinnedMeshRenderer>(true))
|
||
{
|
||
smr.gameObject.layer = layer;
|
||
// Материалы с _Tint игра уже размножила для этой модели (SDCSUtils.Stitch) - красим свои копии.
|
||
foreach (Material m in smr.sharedMaterials)
|
||
{
|
||
if (m != null && m.HasColor("_Tint"))
|
||
{
|
||
m.SetColor("_Tint", Tint);
|
||
tinted++;
|
||
}
|
||
}
|
||
}
|
||
// Коллайдеры рук (у женского скелета игра вешает капсулу на таз) - выключены: руки в голове зомби ловили бы
|
||
// луч прицела и толкали бы предметы.
|
||
foreach (Collider c in _rig.GetComponentsInChildren<Collider>(true))
|
||
{
|
||
c.enabled = false;
|
||
}
|
||
foreach (HingeJoint j in _rig.GetComponentsInChildren<HingeJoint>(true))
|
||
{
|
||
if (j.connectedBody == null)
|
||
{
|
||
j.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
_layerWasShown = _player.playerCamera != null && (_player.playerCamera.cullingMask & (1 << layer)) != 0;
|
||
_player.ShowHoldingItemLayer(true);
|
||
Debug.Log("[NecromancerTome] FpArms: руки " + arch.Name + " для " + _z.EntityName + ", серых материалов " + tinted +
|
||
", родитель " + parent.name);
|
||
}
|
||
|
||
public static void Hide(EntityPlayerLocal _player)
|
||
{
|
||
if (_rig == null)
|
||
{
|
||
return;
|
||
}
|
||
if (!_layerWasShown)
|
||
{
|
||
_player?.ShowHoldingItemLayer(false);
|
||
}
|
||
SDCSUtils.UnloadViz(_rig);
|
||
_rig = null;
|
||
_bones = null;
|
||
Debug.Log("[NecromancerTome] FpArms: руки убраны");
|
||
}
|
||
}
|
||
}
|