Decompiled source of HanestadSuits v1.0.2

BepInEx/plugins/HanestadSuits/HanestadSuits.dll

Decompiled 7 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 GameNetcodeStuff;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("HanestadSuits")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HanestadSuits")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("86eb1dc9-377e-4b41-aa4f-4f280c5b4e52")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HanestadSuits;

[BepInPlugin("no.hanestad.hanestadsuits", "Hanestad Suits", "2.1.9")]
public class Plugin : BaseUnityPlugin
{
	private int kjellaSuitID = -1;

	private float nextCheck;

	private StartOfRound currentRound;

	private readonly Dictionary<PlayerControllerB, List<GameObject>> partsByPlayer = new Dictionary<PlayerControllerB, List<GameObject>>();

	private PlayerControllerB playerBeingBuilt;

	private Material kjellaFatMaterial;

	private Material bellyMaterial;

	private Texture2D yellowTexture;

	private Texture2D bellyTexture;

	private void Awake()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"HanestadSuits 2.1.9 - multiplayer body fix");
	}

	private void Update()
	{
		if (Time.realtimeSinceStartup < nextCheck)
		{
			return;
		}
		nextCheck = Time.realtimeSinceStartup + 0.25f;
		StartOfRound instance = StartOfRound.Instance;
		if ((Object)(object)instance == (Object)null)
		{
			if ((Object)(object)currentRound != (Object)null)
			{
				ResetForNewRound();
			}
			return;
		}
		if ((Object)(object)instance != (Object)(object)currentRound)
		{
			ResetForNewRound();
			currentRound = instance;
		}
		if (kjellaSuitID < 0)
		{
			FindKjellaSuit();
		}
		if (kjellaSuitID < 0)
		{
			return;
		}
		PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
		if (allPlayerScripts == null)
		{
			return;
		}
		HashSet<PlayerControllerB> hashSet = new HashSet<PlayerControllerB>();
		PlayerControllerB[] array = allPlayerScripts;
		foreach (PlayerControllerB val in array)
		{
			if ((Object)(object)val == (Object)null || !val.isPlayerControlled || val.currentSuitID != kjellaSuitID)
			{
				continue;
			}
			hashSet.Add(val);
			if (partsByPlayer.TryGetValue(val, out var value))
			{
				bool flag = value.Count == 2;
				if (flag)
				{
					foreach (GameObject item in value)
					{
						if ((Object)(object)item == (Object)null || !item.transform.IsChildOf(((Component)val).transform))
						{
							flag = false;
							break;
						}
					}
				}
				if (flag)
				{
					continue;
				}
				RemoveKjellaBody(val);
			}
			CreateKjellaBody(val);
		}
		List<PlayerControllerB> list = new List<PlayerControllerB>();
		foreach (PlayerControllerB key in partsByPlayer.Keys)
		{
			if ((Object)(object)key == (Object)null || !hashSet.Contains(key))
			{
				list.Add(key);
			}
		}
		foreach (PlayerControllerB item2 in list)
		{
			RemoveKjellaBody(item2);
		}
	}

	private void CreateKjellaBody(PlayerControllerB player)
	{
		SkinnedMeshRenderer val = FindLOD1(player);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Transform val2 = FindBone(val, "spine.002") ?? FindBone(val, "spine.001") ?? FindBone(val, "spine");
		if ((Object)(object)val2 == (Object)null)
		{
			return;
		}
		if ((Object)(object)kjellaFatMaterial == (Object)null)
		{
			CreateFatMaterial(val);
			if ((Object)(object)kjellaFatMaterial == (Object)null)
			{
				return;
			}
			CreateBellyMaterial();
		}
		playerBeingBuilt = player;
		partsByPlayer[player] = new List<GameObject>();
		try
		{
			CreateTorsoBelly(val2);
			CreateHipsButt(val2);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("KJELLA kropp opprettet for spiller: " + player.playerUsername));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("KJELLA kropp: " + ex));
			RemoveKjellaBody(player);
		}
		finally
		{
			playerBeingBuilt = null;
		}
	}

	private void CreateTorsoBelly(Transform torso)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = CreatePart("KJELLA_TORSO_BELLY", torso);
		val.transform.localPosition = new Vector3(0f, 0.015f, -0.015f);
		val.AddComponent<MeshFilter>().sharedMesh = CreateTorsoBellyMesh();
		MeshRenderer val2 = val.AddComponent<MeshRenderer>();
		((Renderer)val2).sharedMaterial = (((Object)(object)bellyMaterial != (Object)null) ? bellyMaterial : kjellaFatMaterial);
		((Renderer)val2).shadowCastingMode = (ShadowCastingMode)1;
		((Renderer)val2).receiveShadows = true;
	}

	private Mesh CreateTorsoBellyMesh()
	{
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		float[,] array = new float[21, 4]
		{
			{ 0.36f, 0.27f, 0.18f, 0.17f },
			{ 0.31f, 0.29f, 0.19f, 0.2f },
			{ 0.26f, 0.31f, 0.2f, 0.24f },
			{ 0.21f, 0.325f, 0.21f, 0.28f },
			{ 0.16f, 0.34f, 0.22f, 0.32f },
			{ 0.11f, 0.35f, 0.23f, 0.36f },
			{ 0.06f, 0.36f, 0.24f, 0.39f },
			{ 0.01f, 0.365f, 0.25f, 0.42f },
			{ -0.04f, 0.37f, 0.25f, 0.44f },
			{ -0.09f, 0.372f, 0.25f, 0.44f },
			{ -0.14f, 0.37f, 0.24f, 0.43f },
			{ -0.19f, 0.365f, 0.23f, 0.42f },
			{ -0.24f, 0.355f, 0.22f, 0.41f },
			{ -0.29f, 0.345f, 0.21f, 0.39f },
			{ -0.34f, 0.338f, 0.2f, 0.37f },
			{ -0.39f, 0.33f, 0.19f, 0.34f },
			{ -0.44f, 0.315f, 0.18f, 0.31f },
			{ -0.48f, 0.295f, 0.17f, 0.27f },
			{ -0.515f, 0.27f, 0.15f, 0.23f },
			{ -0.54f, 0.235f, 0.13f, 0.18f },
			{ -0.555f, 0.19f, 0.1f, 0.13f }
		};
		int length = array.GetLength(0);
		List<Vector3> list = new List<Vector3>();
		List<int> list2 = new List<int>();
		List<Vector2> list3 = new List<Vector2>();
		for (int i = 0; i < length; i++)
		{
			float num = array[i, 0];
			float num2 = array[i, 1];
			float num3 = array[i, 2];
			float num4 = array[i, 3];
			for (int j = 0; j < 48; j++)
			{
				float num5 = (float)j / 48f * (float)Math.PI * 2f;
				float num6 = Mathf.Sin(num5);
				float num7 = Mathf.Cos(num5) * num2;
				float num8 = num;
				float num9;
				if (num6 >= 0f)
				{
					num9 = Mathf.Pow(num6, 0.78f) * num4;
					if (num <= -0.12f && num >= -0.5f)
					{
						float num10 = Mathf.InverseLerp(-0.12f, -0.5f, num);
						float num11 = Mathf.Max(0f, Mathf.Sin(num10 * (float)Math.PI));
						float num12 = Mathf.Pow(num6, 3.4f);
						num8 -= num11 * num12 * 0.07f;
						num9 += num11 * num12 * 0.01f;
					}
				}
				else
				{
					num9 = num6 * num3;
				}
				list.Add(new Vector3(num7, num8, num9));
				float num13 = ((j <= 24) ? (1f - 2f * (float)j / 48f) : 0.5f);
				float num14 = 1f - (float)i / (float)(length - 1);
				list3.Add(new Vector2(num13, num14));
			}
		}
		ConnectRings(list2, length, 48);
		CloseRingMesh(list, list2, list3, array, length, 48, 0.01f, 0.025f);
		return FinishMesh("KJELLA_TORSO_BELLY_218", list, list2, list3);
	}

	private void CreateHipsButt(Transform torso)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = CreatePart("KJELLA_HIPS_BUTT", torso);
		val.transform.localPosition = new Vector3(0f, -0.19f, -0.015f);
		val.AddComponent<MeshFilter>().sharedMesh = CreateHipsButtMesh();
		SetupRenderer(val.AddComponent<MeshRenderer>());
	}

	private Mesh CreateHipsButtMesh()
	{
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		float[,] array = new float[11, 4]
		{
			{ 0.24f, 0.31f, 0.1f, 0.22f },
			{ 0.19f, 0.33f, 0.1f, 0.27f },
			{ 0.14f, 0.345f, 0.1f, 0.32f },
			{ 0.09f, 0.36f, 0.1f, 0.36f },
			{ 0.04f, 0.37f, 0.1f, 0.4f },
			{ -0.01f, 0.375f, 0.095f, 0.43f },
			{ -0.06f, 0.378f, 0.09f, 0.44f },
			{ -0.11f, 0.375f, 0.085f, 0.43f },
			{ -0.16f, 0.365f, 0.08f, 0.4f },
			{ -0.21f, 0.35f, 0.075f, 0.36f },
			{ -0.26f, 0.335f, 0.07f, 0.31f }
		};
		int length = array.GetLength(0);
		List<Vector3> list = new List<Vector3>();
		List<int> list2 = new List<int>();
		List<Vector2> list3 = new List<Vector2>();
		for (int i = 0; i < length; i++)
		{
			float num = array[i, 0];
			float num2 = array[i, 1];
			float num3 = array[i, 2];
			float num4 = array[i, 3];
			for (int j = 0; j < 48; j++)
			{
				float num5 = (float)j / 48f * (float)Math.PI * 2f;
				float num6 = Mathf.Sin(num5);
				float num7 = Mathf.Cos(num5) * num2;
				float num8 = num;
				float num9;
				if (num6 >= 0f)
				{
					num9 = Mathf.Pow(num6, 0.9f) * num3;
				}
				else
				{
					num9 = (0f - Mathf.Pow(0f - num6, 0.8f)) * num4;
					if (num <= 0.08f && num >= -0.22f)
					{
						float num10 = Mathf.InverseLerp(0.08f, -0.22f, num);
						float num11 = Mathf.Max(0f, Mathf.Sin(num10 * (float)Math.PI));
						num9 -= num11 * Mathf.Pow(0f - num6, 2.4f) * 0.025f;
					}
				}
				list.Add(new Vector3(num7, num8, num9));
				list3.Add(new Vector2((float)j / 48f, (float)i / (float)(length - 1)));
			}
		}
		ConnectRings(list2, length, 48);
		CloseRingMesh(list, list2, list3, array, length, 48, -0.01f, -0.02f);
		return FinishMesh("KJELLA_HIPS_BUTT_218", list, list2, list3);
	}

	private void CreateBellyMaterial()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Expected O, but got Unknown
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Expected O, but got Unknown
		string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
		string text = Path.Combine(directoryName, "KjellaBelly.png");
		if (!File.Exists(text))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Mangler KjellaBelly.png: " + text));
			return;
		}
		try
		{
			bellyTexture = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(bellyTexture, File.ReadAllBytes(text)))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Kunne ikke laste KjellaBelly.png");
				Object.Destroy((Object)(object)bellyTexture);
				bellyTexture = null;
				return;
			}
			((Texture)bellyTexture).wrapMode = (TextureWrapMode)1;
			bellyMaterial = new Material(kjellaFatMaterial);
			((Object)bellyMaterial).name = "KJELLA_STYLIZED_BELLY";
			string[] array = new string[3] { "_MainTex", "_BaseMap", "_BaseColorMap" };
			foreach (string text2 in array)
			{
				if (bellyMaterial.HasProperty(text2))
				{
					bellyMaterial.SetTexture(text2, (Texture)(object)bellyTexture);
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"KJELLA magetekstur lastet");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("KJELLA teksturfeil: " + ex));
		}
	}

	private static Mesh FinishMesh(string name, List<Vector3> v, List<int> t, List<Vector2> uv)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		Mesh val = new Mesh();
		((Object)val).name = name;
		val.SetVertices(v);
		val.SetTriangles(t, 0);
		val.SetUVs(0, uv);
		val.RecalculateNormals();
		val.RecalculateTangents();
		val.RecalculateBounds();
		return val;
	}

	private static void ConnectRings(List<int> tris, int count, int segments)
	{
		for (int i = 0; i < count - 1; i++)
		{
			for (int j = 0; j < segments; j++)
			{
				int num = (j + 1) % segments;
				int item = i * segments + j;
				int item2 = i * segments + num;
				int item3 = (i + 1) * segments + j;
				int item4 = (i + 1) * segments + num;
				tris.Add(item);
				tris.Add(item2);
				tris.Add(item3);
				tris.Add(item2);
				tris.Add(item4);
				tris.Add(item3);
			}
		}
	}

	private static void CloseRingMesh(List<Vector3> v, List<int> t, List<Vector2> uv, float[,] rings, int count, int segments, float topZ, float bottomZ)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		int count2 = v.Count;
		v.Add(new Vector3(0f, rings[0, 0] + 0.012f, topZ));
		uv.Add(new Vector2(0.5f, 1f));
		for (int i = 0; i < segments; i++)
		{
			int item = (i + 1) % segments;
			t.Add(count2);
			t.Add(item);
			t.Add(i);
		}
		int count3 = v.Count;
		int num = (count - 1) * segments;
		v.Add(new Vector3(0f, rings[count - 1, 0] - 0.018f, bottomZ));
		uv.Add(new Vector2(0.5f, 0f));
		for (int j = 0; j < segments; j++)
		{
			int num2 = (j + 1) % segments;
			t.Add(count3);
			t.Add(num + j);
			t.Add(num + num2);
		}
	}

	private GameObject CreatePart(string name, Transform parent)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		GameObject val = new GameObject(name);
		val.transform.SetParent(parent, false);
		partsByPlayer[playerBeingBuilt].Add(val);
		return val;
	}

	private void SetupRenderer(MeshRenderer renderer)
	{
		((Renderer)renderer).sharedMaterial = kjellaFatMaterial;
		((Renderer)renderer).shadowCastingMode = (ShadowCastingMode)1;
		((Renderer)renderer).receiveShadows = true;
	}

	private void CreateFatMaterial(SkinnedMeshRenderer lod1)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Expected O, but got Unknown
		//IL_0070: 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_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: 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)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)((Renderer)lod1).sharedMaterial == (Object)null)
		{
			return;
		}
		kjellaFatMaterial = new Material(((Renderer)lod1).sharedMaterial);
		((Object)kjellaFatMaterial).name = "KJELLA_SOLID_YELLOW";
		Color val = default(Color);
		((Color)(ref val))..ctor(1f, 0.92f, 0f, 1f);
		yellowTexture = new Texture2D(2, 2, (TextureFormat)4, false);
		yellowTexture.SetPixels((Color[])(object)new Color[4] { val, val, val, val });
		yellowTexture.Apply();
		string[] array = new string[3] { "_MainTex", "_BaseMap", "_BaseColorMap" };
		foreach (string text in array)
		{
			if (kjellaFatMaterial.HasProperty(text))
			{
				kjellaFatMaterial.SetTexture(text, (Texture)(object)yellowTexture);
			}
		}
		string[] array2 = new string[2] { "_Color", "_BaseColor" };
		foreach (string text2 in array2)
		{
			if (kjellaFatMaterial.HasProperty(text2))
			{
				kjellaFatMaterial.SetColor(text2, Color.white);
			}
		}
	}

	private static SkinnedMeshRenderer FindLOD1(PlayerControllerB player)
	{
		SkinnedMeshRenderer[] componentsInChildren = ((Component)player).GetComponentsInChildren<SkinnedMeshRenderer>(true);
		foreach (SkinnedMeshRenderer val in componentsInChildren)
		{
			if (((Object)val).name == "LOD1")
			{
				return val;
			}
		}
		return null;
	}

	private static Transform FindBone(SkinnedMeshRenderer renderer, string name)
	{
		Transform[] bones = renderer.bones;
		foreach (Transform val in bones)
		{
			if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, name, StringComparison.OrdinalIgnoreCase))
			{
				return val;
			}
		}
		return null;
	}

	private void FindKjellaSuit()
	{
		if ((Object)(object)StartOfRound.Instance.unlockablesList == (Object)null)
		{
			return;
		}
		List<UnlockableItem> unlockables = StartOfRound.Instance.unlockablesList.unlockables;
		for (int i = 0; i < unlockables.Count; i++)
		{
			UnlockableItem val = unlockables[i];
			if (val != null && string.Equals(val.unlockableName?.Trim(), "KJELLA", StringComparison.OrdinalIgnoreCase))
			{
				kjellaSuitID = i;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("KJELLA ID=" + i));
				break;
			}
		}
	}

	private void RemoveKjellaBody(PlayerControllerB player)
	{
		if (!partsByPlayer.TryGetValue(player, out var value))
		{
			return;
		}
		foreach (GameObject item in value)
		{
			if (!((Object)(object)item == (Object)null))
			{
				MeshFilter component = item.GetComponent<MeshFilter>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null)
				{
					Object.Destroy((Object)(object)component.sharedMesh);
				}
				Object.Destroy((Object)(object)item);
			}
		}
		partsByPlayer.Remove(player);
	}

	private void ResetForNewRound()
	{
		List<PlayerControllerB> list = new List<PlayerControllerB>(partsByPlayer.Keys);
		foreach (PlayerControllerB item in list)
		{
			RemoveKjellaBody(item);
		}
		if ((Object)(object)kjellaFatMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)kjellaFatMaterial);
		}
		if ((Object)(object)yellowTexture != (Object)null)
		{
			Object.Destroy((Object)(object)yellowTexture);
		}
		if ((Object)(object)bellyMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)bellyMaterial);
		}
		if ((Object)(object)bellyTexture != (Object)null)
		{
			Object.Destroy((Object)(object)bellyTexture);
		}
		kjellaFatMaterial = null;
		yellowTexture = null;
		bellyMaterial = null;
		bellyTexture = null;
		playerBeingBuilt = null;
		kjellaSuitID = -1;
		currentRound = null;
	}

	private void OnDestroy()
	{
		ResetForNewRound();
	}
}