using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ZombePlayerMod
{
[BepInPlugin("BigPickle.ZombePlayerMod", "BenWarning", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInProcess("Content Warning.exe")]
public class ZombePlayerMod : BaseUnityPlugin
{
public const string MOD_GUID = "BigPickle.ZombePlayerMod";
public const string MOD_NAME = "BenWarning";
public const string MOD_VERSION = "1.0.0";
private Harmony _harmony;
internal static ZombePlayerMod Instance { get; private set; }
internal ManualLogSource Log { get; private set; }
internal static ConfigEntry<bool> EnableModelReplacement { get; private set; }
internal static ConfigEntry<float> ModelScale { get; private set; }
internal static ConfigEntry<float> ModelFacingYaw { get; private set; }
internal static ConfigEntry<float> ModelPitch { get; private set; }
internal static ConfigEntry<float> ModelForwardOffset { get; private set; }
internal static ConfigEntry<float> HandRaise { get; private set; }
internal static ConfigEntry<bool> ShowOwnModel { get; private set; }
private void Awake()
{
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
EnableModelReplacement = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableModelReplacement", true, "Replace the player model with the Zombe monster.");
ModelScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ModelScale", 1f, "Extra scale multiplier applied to the Zombe model (1.0 = same size as a player).");
ModelFacingYaw = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ModelFacingYaw", 0f, "Rotates the Zombe around its Y axis (degrees) so it faces the same way the player does. Try 0 or 180.");
ModelPitch = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ModelPitch", 0f, "Pitches the Zombe's head up/down (degrees) around its sideways axis. Try -90 or 90 if it is lying down.");
ModelForwardOffset = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ModelForwardOffset", 0f, "Moves the model forward along its facing (meters). Optional cosmetic nudge; the camera rides the Zombe's head so alignment is exact by default.");
HandRaise = ((BaseUnityPlugin)this).Config.Bind<float>("General", "HandRaise", 0.1f, "Raises the Zombe's hands (world meters) above the player's real hands so held items are gripped properly.");
ShowOwnModel = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowOwnModel", true, "Whether the local player (you) wears the Zombe model. Turn off to keep the default first-person body and visor.");
_harmony = new Harmony("BigPickle.ZombePlayerMod");
_harmony.PatchAll();
ZombeNetworkHandler.Init();
Log.LogInfo((object)"BenWarning v1.0.0 loaded! Big Pickle reporting for duty.");
}
private void OnDestroy()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "BigPickle.ZombePlayerMod";
public const string PLUGIN_NAME = "BenWarning";
public const string PLUGIN_VERSION = "1.0.0";
}
public static class ZombeModelCache
{
private static Player _zombePlayer;
private static SkinnedMeshRenderer[] _zombeRenderers;
private static Transform _rootBone;
private static Dictionary<string, Transform> _sourceBones;
private static bool _searchStarted;
private static bool _loadAllTried;
private static float _lastLoadAllTime = -999f;
private static bool _usedFallbackMonster;
private static int _fallbackRejects;
private static bool _found;
private static readonly string[] _keywords = new string[6] { "zombe", "snail", "zombie", "zomby", "sluggie", "slug" };
public static Player ZombePlayer => _zombePlayer;
public static SkinnedMeshRenderer[] ZombeRenderers => _zombeRenderers;
public static Transform RootBone => _rootBone;
public static Dictionary<string, Transform> SourceBones => _sourceBones;
public static bool Found => _found;
public static void Init()
{
if (!_searchStarted)
{
_searchStarted = true;
TryFindNow();
}
}
public static void TryFindNow()
{
if (!_found)
{
SearchResources();
}
}
public static void ResetForRetry()
{
if (_usedFallbackMonster)
{
_fallbackRejects++;
}
_usedFallbackMonster = false;
_found = false;
_zombePlayer = null;
_zombeRenderers = null;
_rootBone = null;
_sourceBones = null;
}
private static void SearchResources()
{
try
{
Player[] array = Resources.FindObjectsOfTypeAll<Player>();
if (array != null)
{
Player[] array2 = array;
foreach (Player val in array2)
{
if (!((Object)(object)val == (Object)null) && val.ai && LooksLikeZombe(val))
{
_fallbackRejects = 0;
if (ExtractFromPlayer(val))
{
return;
}
}
}
Player val2 = null;
if (_fallbackRejects < 3)
{
Player[] array3 = array;
foreach (Player val3 in array3)
{
if (!((Object)(object)val3 == (Object)null) && val3.ai && !LooksLikeZombe(val3) && HasUsableMesh(val3))
{
val2 = val3;
break;
}
}
}
if ((Object)(object)val2 != (Object)null)
{
_usedFallbackMonster = true;
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogWarning((object)("No keyword-matched Zombe; falling back to monster '" + ((Object)val2).name + "'. Model quality may vary until a real Zombe is found."));
}
}
if (ExtractFromPlayer(val2))
{
return;
}
}
}
GameObject[] array4 = Resources.FindObjectsOfTypeAll<GameObject>();
if (array4 != null)
{
GameObject[] array5 = array4;
foreach (GameObject val4 in array5)
{
if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4.GetComponentInParent<Player>() != (Object)null) && NameMatches(((Object)val4).name) && ExtractFromGameObject(val4))
{
return;
}
}
}
if (!_found)
{
MaybeLoadAll();
}
}
catch (Exception arg)
{
ZombePlayerMod instance2 = ZombePlayerMod.Instance;
if (instance2 != null)
{
ManualLogSource log2 = instance2.Log;
if (log2 != null)
{
log2.LogError((object)$"Zombe model search failed: {arg}");
}
}
}
}
private static void MaybeLoadAll()
{
if (_loadAllTried || Time.realtimeSinceStartup - _lastLoadAllTime < 30f)
{
return;
}
_lastLoadAllTime = Time.realtimeSinceStartup;
_loadAllTried = true;
try
{
GameObject[] array = Resources.LoadAll<GameObject>("");
if (array == null)
{
return;
}
GameObject[] array2 = array;
foreach (GameObject val in array2)
{
if ((Object)(object)val == (Object)null || !NameMatches(((Object)val).name))
{
continue;
}
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogInfo((object)("ResourceLoad matched '" + ((Object)val).name + "' via Resources.LoadAll."));
}
}
if (ExtractFromGameObject(val))
{
break;
}
}
}
catch (Exception ex)
{
ZombePlayerMod instance2 = ZombePlayerMod.Instance;
if (instance2 != null)
{
ManualLogSource log2 = instance2.Log;
if (log2 != null)
{
log2.LogWarning((object)("Resources.LoadAll scan failed: " + ex.Message));
}
}
}
}
private static bool HasUsableMesh(Player player)
{
if ((Object)(object)player == (Object)null)
{
return false;
}
SkinnedMeshRenderer[] array = (from r in ((Component)player).GetComponentsInChildren<SkinnedMeshRenderer>(true)
where (Object)(object)r != (Object)null && (Object)(object)r.sharedMesh != (Object)null && r.bones != null && r.bones.Length != 0
select r).ToArray();
return array.Length != 0;
}
private static bool LooksLikeZombe(Player player)
{
try
{
PlayerRefs refs = player.refs;
if (refs != null)
{
if ((Object)(object)refs.bodyMeshRenderer != (Object)null && NameMatches(((Object)refs.bodyMeshRenderer).name))
{
return true;
}
SkinnedMeshRenderer bodyMeshRenderer = refs.bodyMeshRenderer;
if ((Object)(object)((bodyMeshRenderer != null) ? bodyMeshRenderer.sharedMesh : null) != (Object)null && NameMatches(((Object)refs.bodyMeshRenderer.sharedMesh).name))
{
return true;
}
if ((Object)(object)refs.rigRoot != (Object)null && NameMatches(((Object)refs.rigRoot).name))
{
return true;
}
}
if (NameMatches(((Object)player).name))
{
return true;
}
SkinnedMeshRenderer[] componentsInChildren = ((Component)player).GetComponentsInChildren<SkinnedMeshRenderer>(true);
if (componentsInChildren != null)
{
SkinnedMeshRenderer[] array = componentsInChildren;
foreach (SkinnedMeshRenderer val in array)
{
if (!((Object)(object)val == (Object)null))
{
if (NameMatches(((Object)val).name))
{
return true;
}
if ((Object)(object)val.sharedMesh != (Object)null && NameMatches(((Object)val.sharedMesh).name))
{
return true;
}
}
}
}
}
catch
{
return false;
}
return false;
}
private static bool ExtractFromPlayer(Player player)
{
SkinnedMeshRenderer[] array = (from r in ((Component)player).GetComponentsInChildren<SkinnedMeshRenderer>(true)
where (Object)(object)r != (Object)null && (Object)(object)r.sharedMesh != (Object)null && r.bones != null && r.bones.Length != 0
select r).ToArray();
if (array.Length == 0)
{
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogWarning((object)("Player '" + ((Object)player).name + "' has no usable skinned mesh renderers; skipping."));
}
}
return false;
}
_zombePlayer = player;
_zombeRenderers = array;
_rootBone = FindRootBone(player);
_sourceBones = CollectSourceBones(player, _rootBone);
_found = true;
ZombePlayerMod instance2 = ZombePlayerMod.Instance;
if (instance2 != null)
{
ManualLogSource log2 = instance2.Log;
if (log2 != null)
{
log2.LogInfo((object)string.Format("Zombe model cached: {0} renderer(s) / {1} / {2} bones from '{3}'.", array.Length, ((Object)(object)_rootBone != (Object)null) ? ("root=" + ((Object)_rootBone).name) : "no root", _sourceBones?.Count ?? 0, ((Object)player).name));
}
}
return true;
}
private static bool ExtractFromGameObject(GameObject go)
{
SkinnedMeshRenderer[] array = (from r in go.GetComponentsInChildren<SkinnedMeshRenderer>(true)
where (Object)(object)r != (Object)null && (Object)(object)r.sharedMesh != (Object)null && r.bones != null && r.bones.Length != 0
select r).ToArray();
if (array.Length == 0)
{
return false;
}
_zombePlayer = null;
_zombeRenderers = array;
_rootBone = FindRootBoneFromRenderers(array);
_sourceBones = CollectSourceBonesFromRenderers(array, _rootBone);
_found = true;
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogInfo((object)$"Zombe model cached from GameObject '{((Object)go).name}': {array.Length} renderer(s), {_sourceBones?.Count ?? 0} bones.");
}
}
return true;
}
private static Transform FindRootBone(Player player)
{
try
{
if ((Object)(object)player.refs?.rigRoot != (Object)null)
{
return player.refs.rigRoot.transform;
}
}
catch
{
}
return FindRootBoneFromRenderers(_zombeRenderers);
}
private static Transform FindRootBoneFromRenderers(SkinnedMeshRenderer[] renderers)
{
if (renderers == null)
{
return null;
}
foreach (SkinnedMeshRenderer val in renderers)
{
if ((Object)(object)val != (Object)null && (Object)(object)val.rootBone != (Object)null)
{
return val.rootBone;
}
}
if (renderers.Length != 0 && (Object)(object)renderers[0] != (Object)null && renderers[0].bones != null && renderers[0].bones.Length != 0)
{
return renderers[0].bones[0];
}
return null;
}
private static Dictionary<string, Transform> CollectSourceBones(Player player, Transform root)
{
Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase);
if ((Object)(object)root != (Object)null)
{
AddBoneTree(root, dictionary);
}
if ((Object)(object)player != (Object)null)
{
Transform[] componentsInChildren = ((Component)player).GetComponentsInChildren<Transform>(true);
foreach (Transform val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null) && !dictionary.ContainsKey(((Object)val).name))
{
dictionary[((Object)val).name] = val;
}
}
}
return dictionary;
}
private static Dictionary<string, Transform> CollectSourceBonesFromRenderers(SkinnedMeshRenderer[] renderers, Transform root)
{
Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase);
if ((Object)(object)root != (Object)null)
{
AddBoneTree(root, dictionary);
}
if (renderers != null)
{
foreach (SkinnedMeshRenderer val in renderers)
{
if ((Object)(object)val == (Object)null || val.bones == null)
{
continue;
}
Transform[] bones = val.bones;
foreach (Transform val2 in bones)
{
if ((Object)(object)val2 == (Object)null)
{
continue;
}
Transform val3 = val2;
while ((Object)(object)val3 != (Object)null && dictionary.Count < 100000)
{
if (!dictionary.ContainsKey(((Object)val3).name))
{
dictionary[((Object)val3).name] = val3;
}
val3 = val3.parent;
}
}
}
}
return dictionary;
}
private static void AddBoneTree(Transform t, Dictionary<string, Transform> map)
{
if ((Object)(object)t == (Object)null)
{
return;
}
if (!map.ContainsKey(((Object)t).name))
{
map[((Object)t).name] = t;
}
for (int i = 0; i < t.childCount; i++)
{
Transform child = t.GetChild(i);
if ((Object)(object)child != (Object)null)
{
AddBoneTree(child, map);
}
}
}
private static bool NameMatches(string name)
{
if (string.IsNullOrEmpty(name))
{
return false;
}
string text = name.ToLowerInvariant();
string[] keywords = _keywords;
foreach (string value in keywords)
{
if (text.Contains(value))
{
return true;
}
}
return false;
}
}
public class ZombeModelController : MonoBehaviour
{
private class BoneSync
{
public Transform ZombeBone;
public Transform PlayerBone;
public Quaternion BasePlayerLocalRot;
public Quaternion BaseZombeLocalRot;
public Quaternion BoneAlign = Quaternion.identity;
}
private Player _player;
private PlayerRagdoll _playerRagdoll;
private GameObject _visualModel;
private Dictionary<string, Transform> _zombeBones;
private Dictionary<string, Transform> _playerBones;
private Dictionary<string, Transform> _sourceBones;
private SkinnedMeshRenderer[] _playerRenderers;
private List<BoneSync> _boneSyncs;
private List<Transform> _sourceFollowBones;
private bool _built;
private bool _ragdolling;
private Coroutine _ragdollRoutine;
private SkinnedMeshRenderer[] _clonedRenderers;
private int _boneFallbackCount;
private int _diagFrames;
private bool _diagDone;
private bool _diagPostDone;
private float _facingYaw;
private float _pitch;
private float _forwardOffset;
private Dictionary<string, Quaternion> _bindCorrectRot;
private bool _handPinLogged;
private bool _footDiagLogged;
private Transform _playerHip;
private Transform _playerHead;
private Vector3 _zombeUp = Vector3.up;
private Vector3 _zombeForward = Vector3.forward;
private float _hipToFeetY;
private float _footLocalY;
private Vector3 _lastTrackPos;
private int _trackCount;
private static readonly string[] _footNames = new string[4] { "leftfoot", "rightfoot", "lefttoebase", "righttoebase" };
private static readonly string[] _handNames = new string[2] { "Hand_L", "Hand_R" };
private void Start()
{
_player = ((Component)this).GetComponent<Player>();
if ((Object)(object)_player == (Object)null || _player.ai)
{
Object.Destroy((Object)(object)this);
}
else
{
((MonoBehaviour)this).StartCoroutine(WaitForRefs());
}
}
private IEnumerator WaitForRefs()
{
for (int i = 0; i < 120; i++)
{
if (_player.refs != null && (Object)(object)_player.refs.rigRoot != (Object)null && (Object)(object)_player.refs.ragdoll != (Object)null)
{
_playerRagdoll = _player.refs.ragdoll;
((MonoBehaviour)this).StartCoroutine(WaitForZombeThenBuild());
yield break;
}
yield return null;
}
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogWarning((object)("Player refs never became ready on '" + ((Object)((Component)this).gameObject).name + "'; cancelling model."));
}
}
Object.Destroy((Object)(object)this);
}
private IEnumerator WaitForZombeThenBuild()
{
int tries = 0;
while (!_built)
{
if ((Object)(object)_player == (Object)null)
{
Object.Destroy((Object)(object)this);
break;
}
ZombeModelCache.TryFindNow();
if (ZombeModelCache.Found)
{
int attempts = 0;
while (attempts < 3 && !_built)
{
try
{
if (BuildModel())
{
_built = true;
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogInfo((object)("Zombe model applied to '" + ((Object)((Component)this).gameObject).name + "'."));
}
}
yield break;
}
}
catch (Exception ex)
{
ZombePlayerMod instance2 = ZombePlayerMod.Instance;
if (instance2 != null)
{
ManualLogSource log2 = instance2.Log;
if (log2 != null)
{
log2.LogError((object)$"Zombe model build error for {((Object)((Component)this).gameObject).name} (attempt {attempts + 1}): {ex.Message}");
}
}
}
attempts++;
yield return null;
}
ZombeModelCache.ResetForRetry();
}
else
{
int num = tries + 1;
tries = num;
if (num % 20 == 0)
{
ZombePlayerMod instance3 = ZombePlayerMod.Instance;
if (instance3 != null)
{
ManualLogSource log3 = instance3.Log;
if (log3 != null)
{
log3.LogDebug((object)$"Still waiting for the Zombe to load in for '{((Object)((Component)this).gameObject).name}' (tries={tries}).");
}
}
}
}
yield return (object)new WaitForSeconds(1f);
}
}
private bool BuildModel()
{
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Expected O, but got Unknown
_playerBones = CollectBoneMap(_player.refs?.rigRoot);
_sourceBones = ZombeModelCache.SourceBones ?? new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase);
_playerRenderers = (from r in ((Component)_player).GetComponentsInChildren<SkinnedMeshRenderer>(true)
where (Object)(object)r != (Object)null
select r).ToArray();
_visualModel = new GameObject("ZombeModel_" + ((Object)((Component)this).gameObject).name);
_visualModel.layer = ((Component)this).gameObject.layer;
_visualModel.transform.SetParent(((Component)this).transform, false);
_zombeBones = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase);
if ((Object)(object)ZombeModelCache.RootBone != (Object)null)
{
CloneHierarchy(ZombeModelCache.RootBone, _visualModel.transform, _zombeBones);
}
int num = CloneMeshes();
CacheBindCorrections();
if (num <= 0 || _zombeBones.Count == 0)
{
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogWarning((object)$"Zombe clone for '{((Object)((Component)this).gameObject).name}' produced no usable renderers ({num}) or bones ({_zombeBones.Count}); skipping.");
}
}
Object.Destroy((Object)(object)_visualModel);
_visualModel = null;
return false;
}
FitAndAlign();
HideOriginalBody();
BuildBoneSync();
return true;
}
private static Dictionary<string, Transform> CollectBoneMap(GameObject root)
{
Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase);
if ((Object)(object)root == (Object)null)
{
return dictionary;
}
Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
foreach (Transform val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null) && !dictionary.ContainsKey(((Object)val).name))
{
dictionary[((Object)val).name] = val;
}
}
return dictionary;
}
private void CloneHierarchy(Transform source, Transform parent, Dictionary<string, Transform> boneMap)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Expected O, but got Unknown
if ((Object)(object)source == (Object)null)
{
return;
}
GameObject val = new GameObject(((Object)source).name);
val.layer = ((Component)source).gameObject.layer;
val.transform.SetParent(parent, false);
val.transform.localPosition = source.localPosition;
val.transform.localRotation = Quaternion.identity;
val.transform.localScale = source.localScale;
if (!boneMap.ContainsKey(((Object)source).name))
{
boneMap[((Object)source).name] = val.transform;
}
foreach (Transform item in source)
{
Transform val2 = item;
if ((Object)(object)val2 != (Object)null)
{
CloneHierarchy(val2, val.transform, boneMap);
}
}
}
private int CloneMeshes()
{
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0210: Unknown result type (might be due to invalid IL or missing references)
//IL_0215: Unknown result type (might be due to invalid IL or missing references)
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
List<SkinnedMeshRenderer> list = new List<SkinnedMeshRenderer>();
SkinnedMeshRenderer[] zombeRenderers = ZombeModelCache.ZombeRenderers;
foreach (SkinnedMeshRenderer val in zombeRenderers)
{
if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || val.bones == null)
{
continue;
}
GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, _visualModel.transform, false);
((Object)val2).name = ((Object)val).name + "_ZombeMesh";
val2.layer = ((Component)val).gameObject.layer;
SkinnedMeshRenderer component = val2.GetComponent<SkinnedMeshRenderer>();
if ((Object)(object)component == (Object)null)
{
Object.Destroy((Object)(object)val2);
continue;
}
_boneFallbackCount = 0;
component.rootBone = ResolveBone(val.rootBone, _visualModel.transform);
if (val.bones.Length != 0)
{
Transform[] array = (Transform[])(object)new Transform[val.bones.Length];
for (int j = 0; j < val.bones.Length; j++)
{
array[j] = ResolveBone(val.bones[j], _visualModel.transform);
}
component.bones = array;
}
component.sharedMesh = val.sharedMesh;
((Renderer)component).sharedMaterials = ((Renderer)val).sharedMaterials;
((Renderer)component).shadowCastingMode = ((Renderer)val).shadowCastingMode;
((Renderer)component).receiveShadows = ((Renderer)val).receiveShadows;
component.updateWhenOffscreen = true;
((Renderer)component).enabled = true;
list.Add(component);
num++;
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
object[] obj = new object[10]
{
((Object)val).name,
((Object)val.sharedMesh).name,
null,
null,
null,
null,
null,
null,
null,
null
};
Bounds bounds = val.sharedMesh.bounds;
obj[2] = ((Bounds)(ref bounds)).center;
bounds = val.sharedMesh.bounds;
obj[3] = ((Bounds)(ref bounds)).size;
Matrix4x4[] bindposes = val.sharedMesh.bindposes;
obj[4] = ((bindposes != null) ? bindposes.Length : 0);
obj[5] = component.bones.Length;
obj[6] = val.sharedMesh.vertexCount;
obj[7] = val2.layer;
obj[8] = _boneFallbackCount;
obj[9] = (((Object)(object)component.rootBone != (Object)null) ? ((Object)component.rootBone).name : "null");
log.LogInfo((object)string.Format("Clone diagnostic: '{0}' mesh='{1}' localCenter={2:F2} localSize={3:F2} bindposes={4} bones={5} vertexCount={6} layer={7} boneFallbacks={8} rootBone='{9}'.", obj));
}
}
_boneFallbackCount = 0;
}
_clonedRenderers = list.ToArray();
LogRenderContext();
return num;
}
private void LogRenderContext()
{
try
{
Camera[] allCameras = Camera.allCameras;
if (allCameras == null || allCameras.Length == 0)
{
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogInfo((object)"Render context: no cameras yet.");
}
}
return;
}
Camera[] array = allCameras;
foreach (Camera val in array)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
ZombePlayerMod instance2 = ZombePlayerMod.Instance;
if (instance2 != null)
{
ManualLogSource log2 = instance2.Log;
if (log2 != null)
{
log2.LogInfo((object)$"Render context: camera '{((Object)val).name}' enabled={((Behaviour)val).enabled} cullingMask=0x{val.cullingMask:x8} near={val.nearClipPlane:0.00} far={val.farClipPlane:0.00}");
}
}
}
}
catch (Exception ex)
{
ZombePlayerMod instance3 = ZombePlayerMod.Instance;
if (instance3 != null)
{
ManualLogSource log3 = instance3.Log;
if (log3 != null)
{
log3.LogWarning((object)("Render context diagnostic failed: " + ex.Message));
}
}
}
}
private Transform ResolveBone(Transform original, Transform fallbackRoot)
{
if ((Object)(object)original == (Object)null)
{
return fallbackRoot;
}
if (_zombeBones.TryGetValue(((Object)original).name, out var value) && (Object)(object)value != (Object)null)
{
return value;
}
Transform parent = original.parent;
while ((Object)(object)parent != (Object)null)
{
if (_zombeBones.TryGetValue(((Object)parent).name, out value) && (Object)(object)value != (Object)null)
{
return value;
}
parent = parent.parent;
}
_boneFallbackCount++;
return fallbackRoot;
}
private void FitAndAlign()
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0311: Unknown result type (might be due to invalid IL or missing references)
//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
//IL_019f: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: Unknown result type (might be due to invalid IL or missing references)
//IL_0209: Unknown result type (might be due to invalid IL or missing references)
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_022f: Unknown result type (might be due to invalid IL or missing references)
//IL_023a: Unknown result type (might be due to invalid IL or missing references)
float value = ZombePlayerMod.ModelScale.Value;
_facingYaw = ZombePlayerMod.ModelFacingYaw.Value;
_pitch = ZombePlayerMod.ModelPitch.Value;
_forwardOffset = ZombePlayerMod.ModelForwardOffset.Value;
SkinnedMeshRenderer[] renderers = (from r in _visualModel.GetComponentsInChildren<SkinnedMeshRenderer>(true)
where (Object)(object)r != (Object)null && (Object)(object)r.sharedMesh != (Object)null
select r).ToArray();
Bounds val = CombineBounds(renderers);
Bounds val2 = CombineBounds(_playerRenderers);
if (((Bounds)(ref val2)).size.y > 0.01f && ((Bounds)(ref val)).size.y > 0.01f)
{
float num = value * (((Bounds)(ref val2)).size.y / ((Bounds)(ref val)).size.y);
_visualModel.transform.localScale = new Vector3(num, num, num);
}
else
{
_visualModel.transform.localScale = new Vector3(value, value, value);
}
Bounds val3 = CombineBounds(renderers);
_footLocalY = ((Bounds)(ref val3)).min.y - _visualModel.transform.position.y;
_playerHip = null;
_playerHead = null;
if (_playerBones != null)
{
_playerBones.TryGetValue("hip", out _playerHip);
_playerBones.TryGetValue("head", out _playerHead);
}
if ((Object)(object)_playerHip != (Object)null)
{
_hipToFeetY = ((Bounds)(ref val2)).min.y - _playerHip.position.y;
}
_zombeUp = Vector3.up;
try
{
SkinnedMeshRenderer val4 = ((ZombeModelCache.ZombeRenderers != null && ZombeModelCache.ZombeRenderers.Length != 0) ? ZombeModelCache.ZombeRenderers[0] : null);
if ((Object)(object)val4 != (Object)null && (Object)(object)val4.sharedMesh != (Object)null)
{
_zombeForward = Vector3.forward;
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogInfo((object)$"Zombe bind frame: up={_zombeUp:F2} forward={_zombeForward:F2}");
}
}
}
}
catch (Exception ex)
{
ZombePlayerMod instance2 = ZombePlayerMod.Instance;
if (instance2 != null)
{
ManualLogSource log2 = instance2.Log;
if (log2 != null)
{
log2.LogWarning((object)("Zombe bind-frame read failed: " + ex.Message));
}
}
}
ZombePlayerMod instance3 = ZombePlayerMod.Instance;
if (instance3 != null)
{
ManualLogSource log3 = instance3.Log;
if (log3 != null)
{
log3.LogInfo((object)$"Fit: scale={_visualModel.transform.localScale.x:F3} footLocalY={_footLocalY:F2} hipToFeetY={_hipToFeetY:F2} playerHeight={((Bounds)(ref val2)).size.y:F2} zombeHeight={((Bounds)(ref val)).size.y:F2} zombeUp={_zombeUp:F2} facingYaw={_facingYaw:F0} pitch={_pitch:F0}");
}
}
}
private void AnchorToPlayer()
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_visualModel == (Object)null)
{
return;
}
if ((Object)(object)_playerHip == (Object)null || (Object)(object)_playerHead == (Object)null)
{
_visualModel.transform.rotation = Quaternion.Euler(0f, _facingYaw, 0f) * Quaternion.Euler(_pitch, 0f, 0f);
_visualModel.transform.position = ((Component)this).transform.position;
return;
}
Transform val = ((_player.refs != null && (Object)(object)_player.refs.rigRoot != (Object)null) ? _player.refs.rigRoot.transform : ((Component)this).transform);
Quaternion rotation = val.rotation;
Quaternion val2 = rotation * Quaternion.Euler(_pitch, 0f, 0f);
_visualModel.transform.rotation = val2;
_visualModel.transform.position = _playerHip.position;
Transform cloneHead = GetCloneHead();
if ((Object)(object)_playerHead != (Object)null && (Object)(object)cloneHead != (Object)null)
{
Transform transform = _visualModel.transform;
transform.position += _playerHead.position - cloneHead.position;
}
Transform transform2 = _visualModel.transform;
transform2.position += new Vector3(0f, FootGroundSnapY(), 0f);
Transform transform3 = _visualModel.transform;
transform3.position += val2 * Vector3.forward * _forwardOffset;
}
private static Bounds CombineBounds(SkinnedMeshRenderer[] renderers)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
bool flag = false;
Bounds result = default(Bounds);
if (renderers == null)
{
return result;
}
foreach (SkinnedMeshRenderer val in renderers)
{
if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null))
{
if (!flag)
{
result = ((Renderer)val).bounds;
flag = true;
}
else
{
((Bounds)(ref result)).Encapsulate(((Renderer)val).bounds);
}
}
}
return result;
}
private void HideOriginalBody()
{
Renderer[] componentsInChildren = ((Component)_player).GetComponentsInChildren<Renderer>(true);
foreach (Renderer val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null) && (!((Object)(object)_visualModel != (Object)null) || !((Component)val).transform.IsChildOf(_visualModel.transform)))
{
val.enabled = false;
}
}
}
private void ForceCloneRenderers()
{
if (_clonedRenderers == null)
{
return;
}
for (int i = 0; i < _clonedRenderers.Length; i++)
{
SkinnedMeshRenderer val = _clonedRenderers[i];
if (!((Object)(object)val == (Object)null))
{
if (!((Component)val).gameObject.activeSelf)
{
((Component)val).gameObject.SetActive(true);
}
if (!((Renderer)val).enabled)
{
((Renderer)val).enabled = true;
}
}
}
}
private void DisableCloneRenderers()
{
if (_clonedRenderers == null)
{
return;
}
for (int i = 0; i < _clonedRenderers.Length; i++)
{
SkinnedMeshRenderer val = _clonedRenderers[i];
if (!((Object)(object)val == (Object)null))
{
((Renderer)val).enabled = false;
}
}
}
private Transform GetCloneHead()
{
if (_zombeBones != null && _zombeBones.TryGetValue("head", out var value) && (Object)(object)value != (Object)null)
{
return value;
}
return null;
}
private void OnEnable()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnCameraPreCull));
}
private void OnDisable()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnCameraPreCull));
}
private void OnCameraPreCull(Camera cam)
{
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
if (!_built)
{
return;
}
if ((Object)(object)_player == (Object)(object)Player.localPlayer && (Object)(object)cam == (Object)(object)Camera.main)
{
DisableCloneRenderers();
AnchorToPlayer();
Transform cloneHead = GetCloneHead();
if ((Object)(object)cam != (Object)null && (Object)(object)cloneHead != (Object)null)
{
((Component)cam).transform.position = cloneHead.position;
}
}
else
{
ForceCloneRenderers();
AnchorToPlayer();
}
}
private void BuildBoneSync()
{
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
_boneSyncs = new List<BoneSync>();
_sourceFollowBones = new List<Transform>();
foreach (KeyValuePair<string, Transform> zombeBone in _zombeBones)
{
if (!((Object)(object)zombeBone.Value == (Object)(object)_visualModel.transform))
{
Transform value2;
if (_playerBones.TryGetValue(zombeBone.Key, out var value) && (Object)(object)value != (Object)null)
{
BoneSync item = new BoneSync
{
ZombeBone = zombeBone.Value,
PlayerBone = value,
BasePlayerLocalRot = value.localRotation,
BaseZombeLocalRot = value.localRotation
};
_boneSyncs.Add(item);
}
else if (_sourceBones != null && _sourceBones.TryGetValue(zombeBone.Key, out value2) && (Object)(object)value2 != (Object)null)
{
_sourceFollowBones.Add(zombeBone.Value);
}
}
}
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogInfo((object)$"Bone sync on '{((Object)((Component)this).gameObject).name}': {_boneSyncs.Count} animated bones, {_sourceFollowBones.Count} zombe-only bones.");
}
}
LogHandArmCandidates();
}
private void LogHandArmCandidates()
{
try
{
StringBuilder stringBuilder = new StringBuilder();
foreach (KeyValuePair<string, Transform> playerBone in _playerBones)
{
if (playerBone.Key.IndexOf("hand", StringComparison.OrdinalIgnoreCase) >= 0 || playerBone.Key.IndexOf("arm", StringComparison.OrdinalIgnoreCase) >= 0)
{
stringBuilder.Append(" P:" + playerBone.Key);
}
}
foreach (KeyValuePair<string, Transform> zombeBone in _zombeBones)
{
if (zombeBone.Key.IndexOf("hand", StringComparison.OrdinalIgnoreCase) >= 0 || zombeBone.Key.IndexOf("arm", StringComparison.OrdinalIgnoreCase) >= 0)
{
stringBuilder.Append(" Z:" + zombeBone.Key);
}
}
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogInfo((object)$"Hand/arm candidates:{stringBuilder}");
}
}
}
catch
{
}
}
private void DriveFromPlayerRig()
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_035d: Unknown result type (might be due to invalid IL or missing references)
//IL_0362: Unknown result type (might be due to invalid IL or missing references)
//IL_0371: Unknown result type (might be due to invalid IL or missing references)
//IL_0376: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0321: Unknown result type (might be due to invalid IL or missing references)
//IL_0330: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_018b: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: Unknown result type (might be due to invalid IL or missing references)
//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0202: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Unknown result type (might be due to invalid IL or missing references)
//IL_0409: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0245: Unknown result type (might be due to invalid IL or missing references)
//IL_0251: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < _boneSyncs.Count; i++)
{
BoneSync boneSync = _boneSyncs[i];
if (!((Object)(object)boneSync.PlayerBone == (Object)null) && !((Object)(object)boneSync.ZombeBone == (Object)null))
{
Quaternion val = Quaternion.Inverse(boneSync.BasePlayerLocalRot) * boneSync.PlayerBone.localRotation;
boneSync.ZombeBone.localRotation = boneSync.BoneAlign * (boneSync.BaseZombeLocalRot * val);
}
}
for (int j = 0; j < _boneSyncs.Count; j++)
{
BoneSync boneSync2 = _boneSyncs[j];
if ((Object)(object)boneSync2.PlayerBone == (Object)null || (Object)(object)boneSync2.ZombeBone == (Object)null || !IsFootBone(((Object)boneSync2.ZombeBone).name) || _bindCorrectRot == null || !_bindCorrectRot.TryGetValue(((Object)boneSync2.ZombeBone).name, out var value))
{
continue;
}
Quaternion val2 = boneSync2.PlayerBone.rotation * Quaternion.Euler(180f, 0f, 0f) * value;
Transform val3 = (((Object)(object)boneSync2.ZombeBone.parent != (Object)null) ? boneSync2.ZombeBone.parent : _visualModel.transform);
boneSync2.ZombeBone.localRotation = Quaternion.Inverse(val3.rotation) * val2;
if (_footDiagLogged)
{
continue;
}
_footDiagLogged = true;
Quaternion rotation = boneSync2.PlayerBone.rotation;
Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles;
rotation = boneSync2.ZombeBone.rotation;
Vector3 eulerAngles2 = ((Quaternion)(ref rotation)).eulerAngles;
Quaternion val4 = Quaternion.Inverse(boneSync2.PlayerBone.rotation) * boneSync2.ZombeBone.rotation;
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogInfo((object)$"FootDiag '{((Object)boneSync2.ZombeBone).name}': playerWorld={eulerAngles:F0} zombeWorld={eulerAngles2:F0} delta={((Quaternion)(ref val4)).eulerAngles:F0}");
}
}
}
for (int k = 0; k < _handNames.Length; k++)
{
if (_playerBones == null || !_playerBones.TryGetValue(_handNames[k], out var value2) || _zombeBones == null || !_zombeBones.TryGetValue(_handNames[k], out var value3))
{
continue;
}
if (!_handPinLogged)
{
_handPinLogged = true;
ZombePlayerMod instance2 = ZombePlayerMod.Instance;
if (instance2 != null)
{
ManualLogSource log2 = instance2.Log;
if (log2 != null)
{
log2.LogInfo((object)$"Hand pin matched '{_handNames[k]}' pHand={value2.position:F2} zHand={value3.position:F2} raise={ZombePlayerMod.HandRaise.Value:F2}");
}
}
}
value3.position = value2.position + Vector3.up * ZombePlayerMod.HandRaise.Value;
}
if (_sourceBones == null || _sourceFollowBones == null)
{
return;
}
for (int l = 0; l < _sourceFollowBones.Count; l++)
{
Transform val5 = _sourceFollowBones[l];
if (!((Object)(object)val5 == (Object)null) && _sourceBones.TryGetValue(((Object)val5).name, out var value4) && (Object)(object)value4 != (Object)null)
{
val5.localRotation = value4.localRotation;
}
}
}
private static bool IsFootBone(string name)
{
if (string.IsNullOrEmpty(name))
{
return false;
}
return name.IndexOf("foot", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("toe", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("shoe", StringComparison.OrdinalIgnoreCase) >= 0;
}
private void CacheBindCorrections()
{
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
_bindCorrectRot = null;
try
{
SkinnedMeshRenderer val = ((ZombeModelCache.ZombeRenderers != null && ZombeModelCache.ZombeRenderers.Length != 0) ? ZombeModelCache.ZombeRenderers[0] : null);
if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || val.bones == null || val.sharedMesh.bindposes == null || val.sharedMesh.bindposes.Length == 0)
{
return;
}
for (int i = 0; i < val.bones.Length; i++)
{
Transform val2 = val.bones[i];
if ((Object)(object)val2 == (Object)null || i >= val.sharedMesh.bindposes.Length || !IsFootBone(((Object)val2).name))
{
continue;
}
if (_bindCorrectRot == null)
{
_bindCorrectRot = new Dictionary<string, Quaternion>();
}
Dictionary<string, Quaternion> bindCorrectRot = _bindCorrectRot;
string name = ((Object)val2).name;
Matrix4x4 inverse = ((Matrix4x4)(ref val.sharedMesh.bindposes[i])).inverse;
bindCorrectRot[name] = ((Matrix4x4)(ref inverse)).rotation;
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
string name2 = ((Object)val2).name;
inverse = ((Matrix4x4)(ref val.sharedMesh.bindposes[i])).inverse;
Quaternion rotation = ((Matrix4x4)(ref inverse)).rotation;
log.LogInfo((object)$"Bind correction '{name2}' = {((Quaternion)(ref rotation)).eulerAngles:F0}");
}
}
}
}
catch (Exception ex)
{
ZombePlayerMod instance2 = ZombePlayerMod.Instance;
if (instance2 != null)
{
ManualLogSource log2 = instance2.Log;
if (log2 != null)
{
log2.LogWarning((object)("Bind correction cache failed: " + ex.Message));
}
}
}
}
private float FootGroundSnapY()
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
try
{
float num = float.MaxValue;
float num2 = float.MaxValue;
for (int i = 0; i < _footNames.Length; i++)
{
if (_zombeBones != null && _zombeBones.TryGetValue(_footNames[i], out var value) && (Object)(object)value != (Object)null)
{
num = Mathf.Min(num, value.position.y);
}
if (_playerBones != null && _playerBones.TryGetValue(_footNames[i], out var value2) && (Object)(object)value2 != (Object)null)
{
num2 = Mathf.Min(num2, value2.position.y);
}
}
if (num == float.MaxValue || num2 == float.MaxValue)
{
return 0f;
}
return num2 - num;
}
catch (Exception ex)
{
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogDebug((object)("Foot ground-snap skipped: " + ex.Message));
}
}
return 0f;
}
}
private void DriveRagdollOnce()
{
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_playerRagdoll == (Object)null || _zombeBones == null)
{
return;
}
Bodypart[] componentsInChildren = ((Component)_playerRagdoll).GetComponentsInChildren<Bodypart>(true);
Bodypart[] array = componentsInChildren;
foreach (Bodypart val in array)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
Transform transform = ((Component)val).transform;
if (!((Object)(object)transform == (Object)null))
{
Transform value;
Transform val2 = (_zombeBones.TryGetValue(((Object)transform).name, out value) ? value : null);
if (!((Object)(object)val2 == (Object)null))
{
val2.position = transform.position;
val2.rotation = transform.rotation;
}
}
}
}
private IEnumerator RagdollLoop()
{
while ((Object)(object)_player != (Object)null && _player.data != null && _player.data.dead)
{
DriveRagdollOnce();
yield return (object)new WaitForFixedUpdate();
}
_ragdolling = false;
if (!((Object)(object)_player != (Object)null) || _player.data == null || _player.data.dead)
{
yield break;
}
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogDebug((object)("Ragdoll ended, revived " + ((Object)((Component)this).gameObject).name + "."));
}
}
}
public void OnPlayerRagdollActivated()
{
if (_built && !_ragdolling)
{
_ragdolling = true;
_ragdollRoutine = ((MonoBehaviour)this).StartCoroutine(RagdollLoop());
}
}
private void LateUpdate()
{
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
//IL_0340: Unknown result type (might be due to invalid IL or missing references)
//IL_0345: Unknown result type (might be due to invalid IL or missing references)
//IL_0371: Unknown result type (might be due to invalid IL or missing references)
//IL_0377: Unknown result type (might be due to invalid IL or missing references)
//IL_037c: Unknown result type (might be due to invalid IL or missing references)
//IL_0381: Unknown result type (might be due to invalid IL or missing references)
//IL_02de: Unknown result type (might be due to invalid IL or missing references)
//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0301: Unknown result type (might be due to invalid IL or missing references)
//IL_0306: Unknown result type (might be due to invalid IL or missing references)
//IL_031e: Unknown result type (might be due to invalid IL or missing references)
//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
//IL_040c: Unknown result type (might be due to invalid IL or missing references)
//IL_0434: Unknown result type (might be due to invalid IL or missing references)
//IL_0427: Unknown result type (might be due to invalid IL or missing references)
//IL_0508: Unknown result type (might be due to invalid IL or missing references)
if (!_built || (Object)(object)_player == (Object)null || _player.data == null)
{
return;
}
AnchorToPlayer();
_diagFrames++;
if (!_diagDone && _diagFrames >= 5 && _clonedRenderers != null)
{
_diagDone = true;
SkinnedMeshRenderer[] clonedRenderers = _clonedRenderers;
foreach (SkinnedMeshRenderer val in clonedRenderers)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
object[] obj = new object[8]
{
((Object)val).name,
((Renderer)val).isVisible,
((Renderer)val).enabled,
((Component)val).gameObject.activeSelf,
null,
null,
null,
null
};
Bounds bounds = ((Renderer)val).bounds;
obj[4] = ((Bounds)(ref bounds)).min;
bounds = ((Renderer)val).bounds;
obj[5] = ((Bounds)(ref bounds)).max;
obj[6] = _visualModel.transform.position;
obj[7] = ((Component)this).transform.position;
log.LogInfo((object)string.Format("Render check: '{0}' visible={1} enabled={2} active={3} boundsMin={4:F2} boundsMax={5:F2} modelPos={6:F2} playerPos={7:F2}", obj));
}
}
}
}
if (!_diagPostDone && _diagFrames >= 15 && _clonedRenderers != null)
{
_diagPostDone = true;
ForceCloneRenderers();
SkinnedMeshRenderer[] clonedRenderers2 = _clonedRenderers;
foreach (SkinnedMeshRenderer val2 in clonedRenderers2)
{
if ((Object)(object)val2 == (Object)null)
{
continue;
}
ZombePlayerMod instance2 = ZombePlayerMod.Instance;
if (instance2 != null)
{
ManualLogSource log2 = instance2.Log;
if (log2 != null)
{
log2.LogInfo((object)$"Render check (after force-enable): '{((Object)val2).name}' visible={((Renderer)val2).isVisible} enabled={((Renderer)val2).enabled} active={((Component)val2).gameObject.activeSelf}");
}
}
}
}
if (_diagFrames == 25)
{
ZombePlayerMod instance3 = ZombePlayerMod.Instance;
if (instance3 != null)
{
ManualLogSource log3 = instance3.Log;
if (log3 != null)
{
log3.LogInfo((object)$"Render track: modelPos={_visualModel.transform.position:F2} playerPos={((Component)this).transform.position:F2} hipPos={(((Object)(object)_playerHip != (Object)null) ? _playerHip.position : Vector3.zero):F2} modelOffset={((Component)this).transform.position - _visualModel.transform.position:F2} modelYaw={_visualModel.transform.eulerAngles.y:F1}");
}
}
_lastTrackPos = ((Component)this).transform.position;
}
if (_diagFrames >= 25 && _trackCount < 4)
{
Vector3 val3 = ((Component)this).transform.position - _lastTrackPos;
if (((Vector3)(ref val3)).sqrMagnitude > 2.25f)
{
_trackCount++;
_lastTrackPos = ((Component)this).transform.position;
ZombePlayerMod instance4 = ZombePlayerMod.Instance;
if (instance4 != null)
{
ManualLogSource log4 = instance4.Log;
if (log4 != null)
{
log4.LogInfo((object)$"Render move({_trackCount}): modelPos={_visualModel.transform.position:F2} playerPos={((Component)this).transform.position:F2} hipPos={(((Object)(object)_playerHip != (Object)null) ? _playerHip.position : Vector3.zero):F2}");
}
}
}
}
ForceCloneRenderers();
if (_player.data.dead)
{
if (!_ragdolling)
{
OnPlayerRagdollActivated();
}
return;
}
if (_ragdolling)
{
_ragdolling = false;
if (_ragdollRoutine != null)
{
((MonoBehaviour)this).StopCoroutine(_ragdollRoutine);
}
}
DriveFromPlayerRig();
if ((Object)(object)_player == (Object)(object)Player.localPlayer)
{
Camera main = Camera.main;
Transform cloneHead = GetCloneHead();
if ((Object)(object)main != (Object)null && (Object)(object)cloneHead != (Object)null)
{
((Component)main).transform.position = cloneHead.position;
}
}
}
private void Cleanup()
{
if ((Object)(object)_visualModel != (Object)null)
{
Object.Destroy((Object)(object)_visualModel);
_visualModel = null;
}
if (_playerRenderers == null)
{
return;
}
SkinnedMeshRenderer[] playerRenderers = _playerRenderers;
foreach (SkinnedMeshRenderer val in playerRenderers)
{
if ((Object)(object)val != (Object)null)
{
((Renderer)val).enabled = true;
}
}
if (!((Object)(object)_player != (Object)null))
{
return;
}
Renderer[] componentsInChildren = ((Component)_player).GetComponentsInChildren<Renderer>(true);
foreach (Renderer val2 in componentsInChildren)
{
if ((Object)(object)val2 != (Object)null)
{
val2.enabled = true;
}
}
}
private void OnDestroy()
{
Cleanup();
}
}
public static class ZombeNetworkHandler
{
public const uint MOD_ID = 5918018u;
private static bool _cwApiAvailable;
private static bool _checked;
public static bool IsCwApiAvailable => _cwApiAvailable;
public static void Init()
{
if (_checked)
{
return;
}
_checked = true;
try
{
_cwApiAvailable = Type.GetType("MyceliumNetworking.MyceliumNetwork, MyceliumNetworking", throwOnError: false) != null;
}
catch
{
_cwApiAvailable = false;
}
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogInfo((object)(_cwApiAvailable ? "Mycelium (CWAPI) detected; Zombe networking available." : "Mycelium (CWAPI) not installed; running in client-side mode (recommended for private lobbies)."));
}
}
}
public static ulong GetPlayerUserId(Player player)
{
try
{
if (player?.data == null)
{
return 0uL;
}
return player.data.userID;
}
catch
{
return 0uL;
}
}
}
[HarmonyPatch(typeof(Player))]
internal static class PlayerPatches
{
[HarmonyPatch("Start")]
[HarmonyPostfix]
internal static void OnPlayerStart(Player __instance)
{
try
{
if (!((Object)(object)__instance == (Object)null) && !__instance.ai && ZombePlayerMod.EnableModelReplacement.Value && (!((Object)(object)__instance == (Object)(object)Player.localPlayer) || ZombePlayerMod.ShowOwnModel.Value) && (Object)(object)((Component)__instance).GetComponent<ZombeModelController>() == (Object)null)
{
((Component)__instance).gameObject.AddComponent<ZombeModelController>();
}
}
catch (Exception arg)
{
ZombePlayerMod instance = ZombePlayerMod.Instance;
if (instance != null)
{
ManualLogSource log = instance.Log;
if (log != null)
{
log.LogError((object)$"Player.Start postfix error: {arg}");
}
}
}
}
[HarmonyPatch("Die")]
[HarmonyPostfix]
internal static void OnPlayerDie(Player __instance)
{
ZombeModelController zombeModelController = ((__instance != null) ? ((Component)__instance).GetComponent<ZombeModelController>() : null);
if ((Object)(object)zombeModelController != (Object)null)
{
zombeModelController.OnPlayerRagdollActivated();
}
}
}
[HarmonyPatch(typeof(PlayerRagdoll))]
internal static class PlayerRagdollPatches
{
[HarmonyPatch("Fall")]
[HarmonyPostfix]
internal static void OnRagdollFall(PlayerRagdoll __instance)
{
NotifyZombe(__instance);
}
[HarmonyPatch("CallFall")]
[HarmonyPostfix]
internal static void OnRagdollCallFall(PlayerRagdoll __instance)
{
NotifyZombe(__instance);
}
[HarmonyPatch("OnEnable")]
[HarmonyPostfix]
internal static void OnRagdollEnable(PlayerRagdoll __instance)
{
NotifyZombe(__instance);
}
private static void NotifyZombe(PlayerRagdoll ragdoll)
{
if ((Object)(object)ragdoll == (Object)null)
{
return;
}
Player componentInParent = ((Component)ragdoll).GetComponentInParent<Player>();
if (!((Object)(object)componentInParent == (Object)null))
{
ZombeModelController component = ((Component)componentInParent).GetComponent<ZombeModelController>();
if ((Object)(object)component != (Object)null)
{
component.OnPlayerRagdollActivated();
}
}
}
}
}