Decompiled source of RandomHandCosmetics v1.0.0

RandomHandCosmetics.dll

Decompiled 2 days ago
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RandomHandCosmetics")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RandomHandCosmetics")]
[assembly: AssemblyTitle("RandomHandCosmetics")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace RandomHandCosmetics;

[BepInPlugin("com.yourname.RandomHandCosmetics", "Random Hand Cosmetics", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(CL_CosmeticManager), "GetCosmeticInHand")]
	public static class GetCosmeticInHandPatch
	{
		private static bool Prefix(int i, ref Cosmetic_HandItem __result)
		{
			if (string.IsNullOrEmpty(leftSelectedId) || string.IsNullOrEmpty(rightSelectedId))
			{
				InitializeCosmetics();
				SelectRandomCosmetics();
			}
			string text = ((i == 0) ? leftSelectedId : rightSelectedId);
			if (!string.IsNullOrEmpty(text) && text != "default" && text != "climber")
			{
				FieldInfo field = typeof(CL_CosmeticManager).GetField("cosmeticHandDict", BindingFlags.Static | BindingFlags.NonPublic);
				if (field != null && field.GetValue(null) is Dictionary<string, Cosmetic_HandItem> dictionary && dictionary.TryGetValue(text, out var value))
				{
					__result = value;
					if (i == 0)
					{
						SettingsManager.settings.cosmeticSaveData.leftHandCosmetic.id = text;
					}
					else
					{
						SettingsManager.settings.cosmeticSaveData.rightHandCosmetic.id = text;
					}
					return false;
				}
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(ENT_Player), "Start")]
	public static class PlayerStartPatch
	{
		private static void Postfix(ENT_Player __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((GameEntity)__instance).dead)
			{
				ForceApplyCosmeticToHand(__instance, 0, leftSelectedId);
				ForceApplyCosmeticToHand(__instance, 1, rightSelectedId);
				if (!(ChangeInterval.Value <= 0f))
				{
					((MonoBehaviour)__instance).StartCoroutine(DynamicChangeRoutine(__instance));
				}
			}
		}

		private static IEnumerator DynamicChangeRoutine(ENT_Player player)
		{
			float interval = ChangeInterval.Value;
			while (true)
			{
				yield return (object)new WaitForSeconds(interval);
				if (!((Object)(object)player == (Object)null) && !((GameEntity)player).dead && !CL_GameManager.gMan.isPaused)
				{
					SelectRandomCosmetics();
					ForceApplyCosmeticToHand(player, 0, leftSelectedId);
					ForceApplyCosmeticToHand(player, 1, rightSelectedId);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Hand), "OnEnable")]
	public static class HandOnEnablePatch
	{
		private static void Postfix(Hand __instance)
		{
			ENT_Player player = __instance.GetPlayer();
			if (!((Object)(object)player == (Object)null) && !((GameEntity)player).dead)
			{
				string text = ((__instance.id == 0) ? leftSelectedId : rightSelectedId);
				if (!string.IsNullOrEmpty(text) && text != "default" && text != "climber")
				{
					ForceApplyCosmeticToHand(player, __instance.id, text);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Hand), "LateUpdate")]
	public static class HandLateUpdatePatch
	{
		private static void Postfix(Hand __instance)
		{
			ENT_Player player = __instance.GetPlayer();
			if (!((Object)(object)player == (Object)null) && !((GameEntity)player).dead && !CL_GameManager.gMan.isPaused)
			{
				string text = ((__instance.id == 0) ? leftSelectedId : rightSelectedId);
				if (!string.IsNullOrEmpty(text) && text != "default" && text != "climber")
				{
					ForceApplyCosmeticToHand(player, __instance.id, text);
				}
			}
		}
	}

	public static ConfigEntry<string> ExcludedIdsConfig;

	public static ConfigEntry<bool> SameCosmeticForBothHands;

	public static ConfigEntry<float> ChangeInterval;

	private static List<Cosmetic_HandItem> availableCosmetics = new List<Cosmetic_HandItem>();

	private static List<string> recentIds = new List<string>();

	private const int historySize = 4;

	private static bool isInitialized = false;

	private static string leftSelectedId = null;

	private static string rightSelectedId = null;

	private void Awake()
	{
		ExcludedIdsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ExcludedCosmeticIds", "default,climber", "English: List of cosmetic IDs (comma separated) to exclude from randomization.\nРусский: Список ID косметики (через запятую), исключаемых из рандома.");
		SameCosmeticForBothHands = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SameCosmeticForBothHands", false, "English: True = both hands get the same cosmetic; False = each hand gets its own.\nРусский: True = обе руки получают одинаковую косметику; False = каждая руку свою.");
		ChangeInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChangeInterval", 30f, "English: Interval in seconds between cosmetic changes (0 = disable dynamic change).\nРусский: Интервал смены скинов в секундах (0 = отключить динамическую смену).");
		SceneManager.sceneLoaded += OnSceneLoaded;
		Harmony.CreateAndPatchAll(typeof(GetCosmeticInHandPatch), (string)null);
		Harmony.CreateAndPatchAll(typeof(PlayerStartPatch), (string)null);
		Harmony.CreateAndPatchAll(typeof(HandOnEnablePatch), (string)null);
		Harmony.CreateAndPatchAll(typeof(HandLateUpdatePatch), (string)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"RandomHandCosmetics loaded with forced application.");
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		if (((Scene)(ref scene)).name == "Game-Main")
		{
			isInitialized = false;
			recentIds.Clear();
			leftSelectedId = null;
			rightSelectedId = null;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Cosmetic selection reset for new run.");
		}
	}

	private static void InitializeCosmetics()
	{
		if (isInitialized)
		{
			return;
		}
		CL_CosmeticManager.Initialize();
		FieldInfo field = typeof(CL_CosmeticManager).GetField("cosmeticHands", BindingFlags.Static | BindingFlags.NonPublic);
		if (field == null)
		{
			Debug.LogError((object)"cosmeticHands field not found.");
		}
		else if (field.GetValue(null) is List<Cosmetic_HandItem> { Count: not 0 } list)
		{
			HashSet<string> excludedIds = new HashSet<string> { "default", "climber" };
			string value = ExcludedIdsConfig.Value;
			if (!string.IsNullOrEmpty(value))
			{
				foreach (string item in from s in value.Split(',')
					select s.Trim())
				{
					excludedIds.Add(item);
				}
			}
			List<Cosmetic_HandItem> list2 = list.Where((Cosmetic_HandItem c) => ((Cosmetic_Base)c).IsUnlocked()).ToList();
			if (list2.Count == 0)
			{
				list2 = list;
			}
			availableCosmetics = (from c in list2
				where !excludedIds.Contains(c.cosmeticData.id) && !string.IsNullOrEmpty(c.cosmeticData.id)
				group c by c.cosmeticData.id into g
				select g.First()).ToList();
			isInitialized = true;
			Debug.Log((object)$"Initialized {availableCosmetics.Count} unique cosmetics.");
			if (availableCosmetics.Count > 0)
			{
				string text = string.Join(", ", availableCosmetics.Select((Cosmetic_HandItem c) => c.cosmeticData.id));
				Debug.Log((object)("Available IDs: " + text));
			}
		}
		else
		{
			Debug.LogWarning((object)"No cosmetics found.");
		}
	}

	private static void SelectRandomCosmetics()
	{
		if (availableCosmetics.Count == 0)
		{
			Debug.LogWarning((object)"No cosmetics available.");
			return;
		}
		List<Cosmetic_HandItem> list = availableCosmetics;
		if (recentIds.Count > 0)
		{
			list = availableCosmetics.Where((Cosmetic_HandItem c) => !recentIds.Contains(c.cosmeticData.id)).ToList();
			if (list.Count == 0)
			{
				list = availableCosmetics;
			}
		}
		List<Cosmetic_HandItem> list2 = list.Where((Cosmetic_HandItem c) => c.cosmeticData.id != "default" && c.cosmeticData.id != "climber").ToList();
		if (list2.Count > 0)
		{
			list = list2;
		}
		string text = null;
		string text2 = null;
		for (int num = 0; num < 30; num++)
		{
			if (!string.IsNullOrEmpty(text) && !(text == "default") && !(text == "climber"))
			{
				break;
			}
			text = list[Random.Range(0, list.Count)].cosmeticData.id;
		}
		if (string.IsNullOrEmpty(text) || text == "default" || text == "climber")
		{
			text = list[0].cosmeticData.id;
		}
		if (SameCosmeticForBothHands.Value)
		{
			text2 = text;
		}
		else
		{
			for (int num = 0; num < 30; num++)
			{
				if (!string.IsNullOrEmpty(text2) && !(text2 == "default") && !(text2 == "climber") && !(text2 == text))
				{
					break;
				}
				text2 = list[Random.Range(0, list.Count)].cosmeticData.id;
			}
			if (string.IsNullOrEmpty(text2) || text2 == "default" || text2 == "climber")
			{
				text2 = text;
			}
		}
		leftSelectedId = text;
		rightSelectedId = text2;
		if (!recentIds.Contains(text))
		{
			recentIds.Add(text);
		}
		if (!SameCosmeticForBothHands.Value && !recentIds.Contains(text2))
		{
			recentIds.Add(text2);
		}
		while (recentIds.Count > 4)
		{
			recentIds.RemoveAt(0);
		}
		Debug.Log((object)("Selected cosmetics: left=" + text + ", right=" + text2));
	}

	private static void ForceApplyCosmeticToHand(ENT_Player player, int handIndex, string id)
	{
		if (string.IsNullOrEmpty(id) || id == "default" || id == "climber" || handIndex >= player.hands.Length)
		{
			return;
		}
		Hand val = player.hands[handIndex];
		if (val == null || (Object)(object)val.handModel == (Object)null)
		{
			return;
		}
		FieldInfo field = typeof(CL_CosmeticManager).GetField("cosmeticHandDict", BindingFlags.Static | BindingFlags.NonPublic);
		if (!(field == null) && field.GetValue(null) is Dictionary<string, Cosmetic_HandItem> dictionary && dictionary.TryGetValue(id, out var value))
		{
			val.currentCosmetics.Clear();
			val.currentCosmetics.Add(value);
			Cosmetic_HandItem.ReturnSprites();
			value.SpriteSwap(((Component)val.handModel).gameObject, val);
			if (handIndex == 0)
			{
				SettingsManager.settings.cosmeticSaveData.leftHandCosmetic.id = id;
			}
			else
			{
				SettingsManager.settings.cosmeticSaveData.rightHandCosmetic.id = id;
			}
		}
	}
}