Decompiled source of ZBrolyReskin v1.0.0

BepInEx/plugins/ZBrolyReskin/ZBrolyReskin.dll

Decompiled 14 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ZBrolyReskin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZBrolyReskin")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4d0b937e-4c74-4d5b-8e26-f0628b3ba267")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ZBrolyReskin;

[BepInPlugin("com.zbroly.reskin", "Z Broly Reskin", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class ZBrolyReskinPlugin : BaseUnityPlugin
{
	private static GameObject brolyPrefab;

	private static AssetBundle brolyBundle;

	private Harmony harmony;

	private void Awake()
	{
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Expected O, but got Unknown
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Expected O, but got Unknown
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Expected O, but got Unknown
		string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		string text = Path.Combine(directoryName, "zbrolyassets");
		if (!File.Exists(text))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Z Broly AssetBundle missing!");
			return;
		}
		brolyBundle = AssetBundle.LoadFromFile(text);
		if ((Object)(object)brolyBundle == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Failed to load Z Broly AssetBundle!");
			return;
		}
		GameObject[] array = brolyBundle.LoadAllAssets<GameObject>();
		if (array.Length == 0)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"No Z Broly prefab found!");
			return;
		}
		brolyPrefab = array[0];
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Z Broly prefab loaded: " + ((Object)brolyPrefab).name));
		Type type = null;
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		foreach (Assembly assembly in assemblies)
		{
			if (assembly.GetName().Name != "FrenchPlatypus.BrolyCulo")
			{
				continue;
			}
			Type[] types = assembly.GetTypes();
			foreach (Type type2 in types)
			{
				if (type2.Name == "BrolyAI")
				{
					type = type2;
					break;
				}
			}
			break;
		}
		if (type == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"BrolyCulo AI not found!");
			return;
		}
		MethodInfo methodInfo = AccessTools.Method(type, "Start", (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"BrolyCulo Start method not found!");
			return;
		}
		harmony = new Harmony("com.zbroly.reskin");
		harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(ZBrolyReskinPlugin), "OnBCStart", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		MethodInfo methodInfo2 = AccessTools.Method(type, "AttackPlayerClientRpc", (Type[])null, (Type[])null);
		if (methodInfo2 != null)
		{
			harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(ZBrolyReskinPlugin), "OnBCGrab", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"BrolyCulo grab RPC patch installed!");
		}
		else
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Grab RPC unavailable; using attackingPlayer detection.");
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Z Broly Reskin initialized!");
	}

	public static void OnBCStart(object __instance)
	{
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Component val = (Component)((__instance is Component) ? __instance : null);
			if ((Object)(object)val == (Object)null || (Object)(object)brolyPrefab == (Object)null)
			{
				Debug.LogError((object)"[Z Broly Reskin] Missing enemy or prefab!");
			}
			else
			{
				if ((Object)(object)val.transform.Find("ZBrolyVisual") != (Object)null)
				{
					return;
				}
				GameObject val2 = Object.Instantiate<GameObject>(brolyPrefab, val.transform);
				((Object)val2).name = "ZBrolyVisual";
				val2.transform.localPosition = Vector3.zero;
				val2.transform.localRotation = val2.transform.localRotation * Quaternion.Euler(0f, 180f, 0f);
				val2.transform.localScale = Vector3.one;
				Animator component = val2.GetComponent<Animator>();
				if ((Object)(object)component == (Object)null)
				{
					Debug.LogError((object)"[Z Broly Reskin] Animator missing!");
					return;
				}
				component.applyRootMotion = false;
				component.speed = 1f;
				Debug.Log((object)("[Z Broly Reskin] Animator valid: " + ((Object)(object)component.avatar != (Object)null && component.avatar.isValid)));
				SkinnedMeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<SkinnedMeshRenderer>(true);
				int num = 0;
				SkinnedMeshRenderer[] array = componentsInChildren;
				foreach (SkinnedMeshRenderer val3 in array)
				{
					if (((Renderer)val3).enabled)
					{
						val3.updateWhenOffscreen = true;
						((Renderer)val3).forceRenderingOff = false;
						Material[] sharedMaterials = ((Renderer)val3).sharedMaterials;
						int num2 = Math.Max(1, sharedMaterials.Length);
						Material[] array2 = (Material[])(object)new Material[num2];
						for (int j = 0; j < num2; j++)
						{
							Material source = ((j < sharedMaterials.Length) ? sharedMaterials[j] : null);
							array2[j] = CreateTexturedMaterial(source);
						}
						((Renderer)val3).sharedMaterials = array2;
						num++;
					}
				}
				Debug.Log((object)("[Z Broly Reskin] Textured meshes: " + num));
				ZBrolyGrabSync zBrolyGrabSync = val2.AddComponent<ZBrolyGrabSync>();
				zBrolyGrabSync.Configure(val, component);
				ZBrolyWalkSync zBrolyWalkSync = val2.AddComponent<ZBrolyWalkSync>();
				zBrolyWalkSync.enemyRoot = val.transform;
				zBrolyWalkSync.brolyAnimator = component;
				zBrolyWalkSync.grabSync = zBrolyGrabSync;
				ZBrolyHideOriginalVisuals zBrolyHideOriginalVisuals = val2.AddComponent<ZBrolyHideOriginalVisuals>();
				zBrolyHideOriginalVisuals.enemyRoot = val.transform;
				zBrolyHideOriginalVisuals.zBrolyRoot = val2.transform;
				zBrolyHideOriginalVisuals.HideNow();
				Debug.Log((object)"[Z Broly Reskin] Z Broly ready!");
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[Z Broly Reskin] Spawn error: " + ex));
		}
	}

	public static void OnBCGrab(object __instance)
	{
		try
		{
			Component val = (Component)((__instance is Component) ? __instance : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform val2 = val.transform.Find("ZBrolyVisual");
			if (!((Object)(object)val2 == (Object)null))
			{
				ZBrolyGrabSync component = ((Component)val2).GetComponent<ZBrolyGrabSync>();
				if ((Object)(object)component != (Object)null)
				{
					component.TriggerGrab("AttackPlayerClientRpc");
				}
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[Z Broly Reskin] Grab hook error: " + ex));
		}
	}

	private static Material CreateTexturedMaterial(Material source)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: 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_010a: 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_0120: 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_0127: 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_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		Shader val = Shader.Find("HDRP/Unlit");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Unlit/Texture");
		}
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Unlit/Color");
		}
		if ((Object)(object)val == (Object)null)
		{
			throw new Exception("No compatible shader found!");
		}
		Material val2 = new Material(val);
		((Object)val2).name = (((Object)(object)source != (Object)null) ? ("ZBroly_" + ((Object)source).name) : "ZBroly_Fallback");
		Color color = Color.white;
		if ((Object)(object)source != (Object)null)
		{
			string[] array = new string[3] { "_UnlitColor", "_BaseColor", "_Color" };
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (source.HasProperty(text))
				{
					color = source.GetColor(text);
					break;
				}
			}
		}
		SetColorIfPresent(val2, "_UnlitColor", color);
		SetColorIfPresent(val2, "_BaseColor", color);
		SetColorIfPresent(val2, "_Color", color);
		Texture val3 = null;
		Vector2 val4 = Vector2.one;
		Vector2 val5 = Vector2.zero;
		if ((Object)(object)source != (Object)null)
		{
			string[] array3 = new string[4] { "_UnlitColorMap", "_BaseColorMap", "_BaseMap", "_MainTex" };
			string[] array4 = array3;
			foreach (string text2 in array4)
			{
				if (source.HasProperty(text2))
				{
					Texture texture = source.GetTexture(text2);
					if ((Object)(object)texture != (Object)null)
					{
						val3 = texture;
						val4 = source.GetTextureScale(text2);
						val5 = source.GetTextureOffset(text2);
						break;
					}
				}
			}
		}
		if ((Object)(object)val3 != (Object)null)
		{
			string[] array5 = new string[4] { "_UnlitColorMap", "_BaseColorMap", "_BaseMap", "_MainTex" };
			string[] array6 = array5;
			foreach (string text3 in array6)
			{
				if (val2.HasProperty(text3))
				{
					val2.SetTexture(text3, val3);
					val2.SetTextureScale(text3, val4);
					val2.SetTextureOffset(text3, val5);
				}
			}
		}
		if (val2.HasProperty("_SurfaceType"))
		{
			val2.SetFloat("_SurfaceType", 0f);
		}
		if ((Object)(object)val3 != (Object)null)
		{
			if (val2.HasProperty("_AlphaCutoffEnable"))
			{
				val2.SetFloat("_AlphaCutoffEnable", 1f);
			}
			if (val2.HasProperty("_AlphaCutoff"))
			{
				val2.SetFloat("_AlphaCutoff", 0.3f);
			}
			if (val2.HasProperty("_Cutoff"))
			{
				val2.SetFloat("_Cutoff", 0.3f);
			}
			val2.EnableKeyword("_ALPHATEST_ON");
			val2.renderQueue = 2450;
		}
		return val2;
	}

	private static void SetColorIfPresent(Material material, string property, Color color)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		if (material.HasProperty(property))
		{
			material.SetColor(property, color);
		}
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}
}
public class ZBrolyGrabSync : MonoBehaviour
{
	private Component originalEnemy;

	private Animator brolyAnimator;

	private FieldInfo attackingField;

	private bool configured;

	private bool hasGrabTrigger;

	private bool wasAttacking;

	private float lastGrabTriggerTime = -100f;

	private float grabHoldUntil = -100f;

	public bool IsGrabbing => wasAttacking || Time.time < grabHoldUntil;

	public void Configure(Component enemy, Animator animator)
	{
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Invalid comparison between Unknown and I4
		originalEnemy = enemy;
		brolyAnimator = animator;
		if ((Object)(object)enemy == (Object)null || (Object)(object)animator == (Object)null)
		{
			Debug.LogError((object)"[Z Broly Reskin] GrabSync missing references!");
			return;
		}
		attackingField = AccessTools.Field(((object)enemy).GetType(), "attackingPlayer");
		if (attackingField != null && attackingField.FieldType != typeof(bool))
		{
			attackingField = null;
		}
		AnimatorControllerParameter[] parameters = animator.parameters;
		foreach (AnimatorControllerParameter val in parameters)
		{
			if (val.name == "StartGrab" && (int)val.type == 9)
			{
				hasGrabTrigger = true;
				break;
			}
		}
		Debug.Log((object)("[Z Broly Reskin] Grab trigger found: " + hasGrabTrigger));
		configured = true;
	}

	public void TriggerGrab(string source)
	{
		if (configured && !((Object)(object)brolyAnimator == (Object)null) && hasGrabTrigger && !(Time.time - lastGrabTriggerTime < 0.35f))
		{
			lastGrabTriggerTime = Time.time;
			grabHoldUntil = Time.time + 1.25f;
			brolyAnimator.SetBool("IsWalking", false);
			brolyAnimator.ResetTrigger("StartGrab");
			brolyAnimator.SetTrigger("StartGrab");
			Debug.Log((object)("[Z Broly Reskin] GRAB TRIGGERED: " + source));
		}
	}

	private void Update()
	{
		if (!configured || (Object)(object)originalEnemy == (Object)null || attackingField == null)
		{
			return;
		}
		try
		{
			bool flag = (bool)attackingField.GetValue(originalEnemy);
			if (flag && !wasAttacking)
			{
				TriggerGrab("attackingPlayer flag");
			}
			wasAttacking = flag;
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("[Z Broly Reskin] Grab flag error: " + ex.Message));
			attackingField = null;
		}
	}
}
public class ZBrolyHideOriginalVisuals : MonoBehaviour
{
	public Transform enemyRoot;

	public Transform zBrolyRoot;

	private readonly List<Renderer> hiddenRenderers = new List<Renderer>();

	private float nextScanTime;

	public void HideNow()
	{
		if ((Object)(object)enemyRoot == (Object)null)
		{
			return;
		}
		Renderer[] componentsInChildren = ((Component)enemyRoot).GetComponentsInChildren<Renderer>(true);
		Renderer[] array = componentsInChildren;
		foreach (Renderer val in array)
		{
			if ((Object)(object)val == (Object)null || ((Object)(object)zBrolyRoot != (Object)null && ((Component)val).transform.IsChildOf(zBrolyRoot)))
			{
				continue;
			}
			string name = ((Object)((Component)val).gameObject).name;
			bool flag = string.Equals(name, "Broly", StringComparison.OrdinalIgnoreCase);
			bool flag2 = string.Equals(name, "Ass_L", StringComparison.OrdinalIgnoreCase);
			bool flag3 = string.Equals(name, "Ass_R", StringComparison.OrdinalIgnoreCase);
			if (flag || flag2 || flag3)
			{
				if (!hiddenRenderers.Contains(val))
				{
					hiddenRenderers.Add(val);
					Debug.Log((object)("[Z Broly Reskin] Hiding BC renderer: " + name));
				}
				val.enabled = false;
			}
		}
	}

	private void LateUpdate()
	{
		if ((Object)(object)enemyRoot == (Object)null)
		{
			((Behaviour)this).enabled = false;
			return;
		}
		foreach (Renderer hiddenRenderer in hiddenRenderers)
		{
			if ((Object)(object)hiddenRenderer != (Object)null && hiddenRenderer.enabled)
			{
				hiddenRenderer.enabled = false;
			}
		}
		if (Time.time >= nextScanTime)
		{
			nextScanTime = Time.time + 1f;
			HideNow();
		}
	}
}
public class ZBrolyWalkSync : MonoBehaviour
{
	public Transform enemyRoot;

	public Animator brolyAnimator;

	public ZBrolyGrabSync grabSync;

	private const float WALK_SPEED = 0.9f;

	private const float IDLE_SPEED = 1f;

	private const float GRAB_SPEED = 1.1111112f;

	private const float MOVE_THRESHOLD = 0.12f;

	private const float STOP_DELAY = 0.2f;

	private Vector3 lastPosition;

	private float lastMovementTime = -100f;

	private float nextDiagnosticTime;

	private bool initialized;

	private bool wasWalking;

	private bool hasWalkParameter;

	private float lastAppliedSpeed = -1f;

	private void Start()
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Invalid comparison between Unknown and I4
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)enemyRoot == (Object)null || (Object)(object)brolyAnimator == (Object)null)
		{
			Debug.LogError((object)"[Z Broly Reskin] WalkSync missing references!");
			((Behaviour)this).enabled = false;
			return;
		}
		AnimatorControllerParameter[] parameters = brolyAnimator.parameters;
		foreach (AnimatorControllerParameter val in parameters)
		{
			if (val.name == "IsWalking" && (int)val.type == 4)
			{
				hasWalkParameter = true;
				break;
			}
		}
		if (!hasWalkParameter)
		{
			Debug.LogError((object)"[Z Broly Reskin] IsWalking BOOL missing!");
			((Behaviour)this).enabled = false;
			return;
		}
		lastPosition = enemyRoot.position;
		lastMovementTime = -100f;
		brolyAnimator.SetBool("IsWalking", false);
		brolyAnimator.speed = 1f;
		initialized = true;
		Debug.Log((object)"[Z Broly Reskin] WalkSync initialized!");
		Debug.Log((object)("[Z Broly Reskin] Walk speed: " + 0.9f));
		Debug.Log((object)("[Z Broly Reskin] Grab speed multiplier: " + 1.1111112f.ToString("F3")));
	}

	private void LateUpdate()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		if (!initialized || (Object)(object)enemyRoot == (Object)null || (Object)(object)brolyAnimator == (Object)null)
		{
			return;
		}
		Vector3 position = enemyRoot.position;
		Vector3 val = position - lastPosition;
		val.y = 0f;
		float num = Mathf.Max(Time.deltaTime, 0.001f);
		float num2 = ((Vector3)(ref val)).magnitude / num;
		lastPosition = position;
		if (num2 > 0.12f)
		{
			lastMovementTime = Time.time;
		}
		bool flag = Time.time - lastMovementTime < 0.2f;
		bool flag2 = false;
		if (brolyAnimator.layerCount > 0)
		{
			AnimatorStateInfo currentAnimatorStateInfo = brolyAnimator.GetCurrentAnimatorStateInfo(0);
			flag2 = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Grab") || ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Base Layer.Grab");
			if (brolyAnimator.IsInTransition(0))
			{
				AnimatorStateInfo nextAnimatorStateInfo = brolyAnimator.GetNextAnimatorStateInfo(0);
				if (((AnimatorStateInfo)(ref nextAnimatorStateInfo)).IsName("Grab") || ((AnimatorStateInfo)(ref nextAnimatorStateInfo)).IsName("Base Layer.Grab"))
				{
					flag2 = true;
				}
			}
		}
		bool flag3 = flag2 || ((Object)(object)grabSync != (Object)null && grabSync.IsGrabbing);
		if (flag3)
		{
			flag = false;
		}
		brolyAnimator.SetBool("IsWalking", flag);
		float num3 = (flag3 ? 1.1111112f : ((!flag) ? 1f : 0.9f));
		brolyAnimator.speed = num3;
		if (Mathf.Abs(num3 - lastAppliedSpeed) > 0.001f)
		{
			lastAppliedSpeed = num3;
			Debug.Log((object)("[Z Broly Reskin] Playback speed: " + num3.ToString("F3") + " | " + (flag3 ? "GRAB" : (flag ? "WALK" : "IDLE"))));
		}
		if (flag != wasWalking)
		{
			Debug.Log((object)("[Z Broly Reskin] Animation changed: " + (flag ? "WALK" : "IDLE") + " | BC speed: " + num2.ToString("F2")));
			wasWalking = flag;
		}
		if (Time.time >= nextDiagnosticTime)
		{
			nextDiagnosticTime = Time.time + 3f;
			Debug.Log((object)("[Z Broly Reskin] Movement sample: " + num2.ToString("F2") + " | Walking: " + flag + " | Grabbing: " + flag3));
		}
	}
}