Decompiled source of MasteryCamos v2.2.3

NGAMasteryCamos.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("NGA")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Persistent player progression! Raid, stash loot, and deploy with seemless scene/loadout saving.")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("NGAMasteryCamos")]
[assembly: AssemblyTitle("BepInEx Plugin Title")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace NGA
{
	[BepInPlugin("NGA.MasteryCamos", "MasteryCamos", "0.0.1")]
	[BepInDependency("nrgill28.Sodalite", "1.4.1")]
	[BepInDependency("NGA.JsonFileIO", "0.0.0")]
	[BepInProcess("h3vr.exe")]
	public class MasteryCamos : BaseUnityPlugin
	{
		public class ApplyCamoAsync : MonoBehaviour
		{
			public static void StartApplyCamo(GameObject someGameObject, MasteryCamosGunState someGunState)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Expected O, but got Unknown
				GameObject val = new GameObject("CamoCoroutineHost");
				ApplyCamoAsync applyCamoAsync = val.AddComponent<ApplyCamoAsync>();
				((MonoBehaviour)applyCamoAsync).StartCoroutine(applyCamoAsync.ApplyCamoCoroutine(someGameObject, someGunState));
			}

			public IEnumerator ApplyCamoCoroutine(GameObject someGameObject, MasteryCamosGunState someGunState)
			{
				string camoid = someGunState.camo_id;
				Texture ooo = GetTexture(camoid);
				if ((Object)(object)ooo != (Object)null)
				{
					ApplySpecialCamoDeep(someGameObject, specialCamo);
					AddOrUpdateMCStateRecursively(someGameObject, someGunState);
				}
				else
				{
					Logger.LogError((object)("Error trying to load albedo null texture for " + camoid));
				}
				yield return null;
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		[HarmonyPatch(typeof(TNH_Manager))]
		[HarmonyPatch("SetPhase_Completed")]
		public class TNH_ManagerSetPhase_Completed : MonoBehaviour
		{
			private static void Postfix(TNH_Manager __instance)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: 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)
				FVRObject val = IM.OD["NGA_PaintTub"];
				GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)val).GetGameObject(), __instance.FinalItemSpawnerPoint.position + Vector3.up + 0.5f * Vector3.forward, __instance.FinalItemSpawnerPoint.rotation * Quaternion.Euler(0f, 180f, 0f));
			}
		}

		[HarmonyPatch(typeof(TNH_Manager))]
		[HarmonyPatch("SetPhase_Dead")]
		public class TNH_ManagerSetPhase_Dead : MonoBehaviour
		{
			private static void Postfix(TNH_Manager __instance)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: 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)
				FVRObject val = IM.OD["NGA_PaintTub"];
				GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)val).GetGameObject(), __instance.FinalItemSpawnerPoint.position + Vector3.up + 0.5f * Vector3.forward, __instance.FinalItemSpawnerPoint.rotation * Quaternion.Euler(0f, 180f, 0f));
			}
		}

		[HarmonyPatch(typeof(TNH_SupplyPoint))]
		[HarmonyPatch("SpawnConstructor")]
		public class TNH_SupplyPointSpawnConstructor : MonoBehaviour
		{
			private static void Postfix(TNH_SupplyPoint __instance)
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: 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_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				Transform val = __instance.SpawnPoints_Panels[0];
				FVRObject val2 = IM.OD["NGA_PaintTub"];
				GameObject val3 = Object.Instantiate<GameObject>(((AnvilAsset)val2).GetGameObject(), val.position + Vector3.up + 0.5f * Vector3.forward, val.rotation * Quaternion.Euler(0f, 180f, 0f));
			}
		}

		[HarmonyPatch(typeof(FVRPhysicalObject))]
		[HarmonyPatch("GetFlagDic")]
		public class FVRPhysicalObjectGetFlagDic : MonoBehaviour
		{
			private static void Postfix(FVRPhysicalObject __instance, ref Dictionary<string, string> __result)
			{
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: 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)
				MasteryCamosGunState mCState = GetMCState(((Component)__instance).gameObject);
				if ((Object)(object)mCState != (Object)null)
				{
					if (mCState.camo_id != "")
					{
						string flagDicCamoIdKey = MasteryCamos.flagDicCamoIdKey;
						string camo_id = mCState.camo_id;
						__result.Add(flagDicCamoIdKey, camo_id);
					}
					if (mCState.shader_params_v1 != null)
					{
						string flagDicSpecialCamoKey = MasteryCamos.flagDicSpecialCamoKey;
						string value = JsonUtility.ToJson((object)mCState.shader_params_v1, true);
						__result.Add(flagDicSpecialCamoKey, value);
					}
				}
				Transform val = ((Component)__instance).transform;
				while ((Object)(object)val.parent != (Object)null)
				{
					val = val.parent;
				}
				Vector3 localScale = val.localScale;
				if (localScale != Vector3.one)
				{
					string flagDicChangedScaleKey = MasteryCamos.flagDicChangedScaleKey;
					string value2 = JsonUtility.ToJson((object)localScale);
					__result.Add(flagDicChangedScaleKey, value2);
				}
			}
		}

		[HarmonyPatch(typeof(FVRPhysicalObject))]
		[HarmonyPatch("ConfigureFromFlagDic")]
		public class FVRPhysicalObjectConfigureFromFlagDic : MonoBehaviour
		{
			private static void Postfix(FVRPhysicalObject __instance, ref Dictionary<string, string> f)
			{
				//IL_00b3: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
				MasteryCamosGunState masteryCamosGunState = new MasteryCamosGunState();
				if (f.ContainsKey(flagDicSpecialCamoKey))
				{
					string text = f[flagDicSpecialCamoKey];
					masteryCamosGunState.shader_params_v1 = JsonUtility.FromJson<SpecialCamo>(text);
					ApplyCamo(((Component)__instance).gameObject, masteryCamosGunState);
					AddOrUpdateMCStateSingle(((Component)__instance).gameObject, masteryCamosGunState);
				}
				else if (f.ContainsKey(flagDicCamoIdKey))
				{
					string camo_id = f[flagDicCamoIdKey];
					masteryCamosGunState.camo_id = camo_id;
					ApplyCamo(((Component)__instance).gameObject, masteryCamosGunState);
					AddOrUpdateMCStateSingle(((Component)__instance).gameObject, masteryCamosGunState);
				}
				if (f.ContainsKey(flagDicChangedScaleKey))
				{
					string text2 = f[flagDicChangedScaleKey];
					Vector3 localScale = JsonUtility.FromJson<Vector3>(text2);
					((Component)__instance).transform.localScale = localScale;
				}
			}
		}

		private class OgScale : MonoBehaviour
		{
			public Vector3 og_local_scale;
		}

		[HarmonyPatch(typeof(FVRPhysicalObject))]
		[HarmonyPatch("Awake")]
		public class FVRPhysicalObjectAwake : MonoBehaviour
		{
			private static void Postfix(FVRPhysicalObject __instance)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				OgScale ogScale = ((Component)__instance).gameObject.AddComponent<OgScale>();
				ogScale.og_local_scale = ((Component)__instance).transform.localScale;
			}
		}

		[HarmonyPatch(typeof(TNH_SupplyPoint))]
		[HarmonyPatch("ConfigureAtBeginning")]
		public class TNH_SupplyPointConfigureAtBeginning : MonoBehaviour
		{
			private static void Postfix(TNH_SupplyPoint __instance, ref TNH_CharacterDef c)
			{
				//IL_0023: 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)
				FVRObject val = IM.OD["NGA_PaintTub"];
				GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)val).GetGameObject(), __instance.SpawnPoints_SmallItem[0].position, __instance.SpawnPoints_SmallItem[0].rotation);
				__instance.M.AddObjectToTrackedList(val2);
			}
		}

		[HarmonyPatch(typeof(FVRFireArmChamber))]
		[HarmonyPatch("EjectRound")]
		[HarmonyPatch(new Type[]
		{
			typeof(Vector3),
			typeof(Vector3),
			typeof(Vector3),
			typeof(bool)
		})]
		public class FVRFireArmChamberEjectRound1 : MonoBehaviour
		{
			private static void Postfix(FVRFireArmChamber __instance, ref FVRFireArmRound __result, Vector3 EjectionPosition, Vector3 EjectionVelocity, Vector3 EjectionAngularVelocity, bool ForceCaseLessEject = false)
			{
			}
		}

		[HarmonyPatch(typeof(FVRFireArmChamber))]
		[HarmonyPatch("EjectRound")]
		[HarmonyPatch(new Type[]
		{
			typeof(Vector3),
			typeof(Vector3),
			typeof(Vector3),
			typeof(Vector3),
			typeof(Quaternion),
			typeof(bool)
		})]
		public class FVRFireArmChamberEjectRound2 : MonoBehaviour
		{
			private static void Postfix(FVRFireArmChamber __instance, ref FVRFireArmRound __result, Vector3 EjectionPosition, Vector3 EjectionVelocity, Vector3 EjectionAngularVelocity, bool ForceCaseLessEject = false)
			{
			}
		}

		[HarmonyPatch(typeof(FVRFireArmMagazine))]
		[HarmonyPatch("RemoveRound")]
		[HarmonyPatch(new Type[] { typeof(bool) })]
		public class FVRFireArmMagazineRemoveRound1 : MonoBehaviour
		{
			private static void Postfix(FVRFireArmMagazine __instance, ref GameObject __result, bool b)
			{
			}
		}

		[HarmonyPatch(typeof(FVRFireArmClip))]
		[HarmonyPatch("RemoveRound")]
		[HarmonyPatch(new Type[] { typeof(bool) })]
		public class FVRFireArmClipRemoveRound : MonoBehaviour
		{
			private static void Postfix(FVRFireArmClip __instance, ref GameObject __result, bool b)
			{
			}
		}

		[HarmonyPatch(typeof(FVRFireArmMagazine))]
		[HarmonyPatch("DuplicateFromSpawnLock")]
		public class FVRFireArmMagazineDuplicateFromSpawnLock : MonoBehaviour
		{
			private static void Postfix(FVRFireArmMagazine __instance, ref GameObject __result, ref FVRViveHand hand)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				__result.transform.localScale = ((Component)__instance).transform.localScale;
				MasteryCamosGunState mCState = GetMCState(((Component)__instance).gameObject);
				if ((Object)(object)mCState != (Object)null)
				{
					ApplyCamo(__result, mCState);
				}
			}
		}

		[HarmonyPatch(typeof(FVRFireArmRound))]
		[HarmonyPatch("DuplicateFromSpawnLock")]
		public class FVRFireArmRoundDuplicateFromSpawnLock : MonoBehaviour
		{
			private static void Postfix(FVRFireArmRound __instance, ref GameObject __result, ref FVRViveHand hand)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				__result.transform.localScale = ((Component)__instance).transform.localScale;
				ApplyCamoFromMCState((FVRPhysicalObject)(object)__instance, ref __result, ref hand);
			}
		}

		[HarmonyPatch(typeof(FVRFireArmClip))]
		[HarmonyPatch("DuplicateFromSpawnLock")]
		public class FVRFireArmClipDuplicateFromSpawnLock : MonoBehaviour
		{
			private static void Postfix(FVRFireArmClip __instance, ref GameObject __result, ref FVRViveHand hand)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				__result.transform.localScale = ((Component)__instance).transform.localScale;
				MasteryCamosGunState mCState = GetMCState(((Component)__instance).gameObject);
				if ((Object)(object)mCState != (Object)null)
				{
					ApplyCamo(__result, mCState);
				}
			}
		}

		[HarmonyPatch(typeof(FVRGrenade))]
		[HarmonyPatch("DuplicateFromSpawnLock")]
		public class FVRGrenadeDuplicateFromSpawnLock : MonoBehaviour
		{
			private static void Postfix(FVRGrenade __instance, ref GameObject __result, ref FVRViveHand hand)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				__result.transform.localScale = ((Component)__instance).transform.localScale;
				MasteryCamosGunState mCState = GetMCState(((Component)__instance).gameObject);
				if ((Object)(object)mCState != (Object)null)
				{
					ApplyCamo(__result, mCState);
				}
			}
		}

		[HarmonyPatch(typeof(PinnedGrenade))]
		[HarmonyPatch("DuplicateFromSpawnLock")]
		public class PinnedGrenadeDuplicateFromSpawnLock : MonoBehaviour
		{
			private static void Postfix(PinnedGrenade __instance, ref GameObject __result, ref FVRViveHand hand)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				__result.transform.localScale = ((Component)__instance).transform.localScale;
				MasteryCamosGunState mCState = GetMCState(((Component)__instance).gameObject);
				if ((Object)(object)mCState != (Object)null)
				{
					ApplyCamo(__result, mCState);
				}
			}
		}

		[HarmonyPatch(typeof(Speedloader))]
		[HarmonyPatch("DuplicateFromSpawnLock")]
		public class SpeedloaderDuplicateFromSpawnLock : MonoBehaviour
		{
			private static void Postfix(Speedloader __instance, ref GameObject __result, ref FVRViveHand hand)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				__result.transform.localScale = ((Component)__instance).transform.localScale;
				MasteryCamosGunState mCState = GetMCState(((Component)__instance).gameObject);
				if ((Object)(object)mCState != (Object)null)
				{
					ApplyCamo(__result, mCState);
				}
			}
		}

		[HarmonyPatch(typeof(TNH_Manager))]
		[HarmonyPatch("IncrementScoringStat")]
		public class TNH_ManagerIncrementScoringStat : MonoBehaviour
		{
			private static void Postfix(TNH_Manager __instance, ref ScoringEvent ev, int num)
			{
				List<string> weaponsOnBody = GetWeaponsOnBody();
				foreach (string item in weaponsOnBody)
				{
					if (item == null || item == "")
					{
						Logger.LogError((object)"Empty gun name when updating score. Please hold weapon while scoring event occurs.");
						break;
					}
					bool flag = false;
					if (!questsState.questDictionary.ContainsKey(item))
					{
						BindMasteryQuestsToGun(item);
						flag = true;
					}
					if (questsState.questDictionary.ContainsKey(item))
					{
						flag = flag || IncrementQuests(item, (int)ev);
					}
					else
					{
						Logger.LogError((object)"This shouldnt have happened, there's no quests even after adding mastery?");
					}
					if (flag)
					{
						FileStuff.RefreshSaveFile();
					}
				}
			}
		}

		public class CamoPacks
		{
			public List<string> CamoNames { get; private set; } = new List<string>();


			public Dictionary<string, string> CamoNameToCamoFile { get; private set; } = new Dictionary<string, string>();


			public Dictionary<string, string> CamoToSpecialCamoFile { get; private set; } = new Dictionary<string, string>();


			public Dictionary<string, Dictionary<string, List<string>>> PackTypeCamos { get; private set; } = new Dictionary<string, Dictionary<string, List<string>>>();


			public void AddCamo(string pack, string type, string camoName, string fullFileName = "")
			{
				CamoNames.Add(camoName);
				if (fullFileName.EndsWith(".json"))
				{
					CamoToSpecialCamoFile.Add(camoName, fullFileName);
				}
				else
				{
					CamoNameToCamoFile.Add(camoName, fullFileName);
				}
				if (!PackTypeCamos.ContainsKey(pack))
				{
					PackTypeCamos[pack] = new Dictionary<string, List<string>>();
				}
				if (!PackTypeCamos[pack].ContainsKey(type))
				{
					PackTypeCamos[pack][type] = new List<string>();
				}
				if (!PackTypeCamos[pack][type].Contains(camoName))
				{
					PackTypeCamos[pack][type].Add(camoName);
				}
			}

			public string GetCamoFile(string camoName)
			{
				string text = camoName;
				if (camoName.EndsWith(".png"))
				{
					text = camoName.Substring(0, camoName.Length - 4);
				}
				int num = text.LastIndexOf('/');
				if (num != -1)
				{
					text = text.Substring(num + 1);
				}
				if (CamoNameToCamoFile.ContainsKey(text))
				{
					return CamoNameToCamoFile[text];
				}
				if (camoName.EndsWith(".png"))
				{
					return FindFileInPlugin(camoName);
				}
				return "";
			}

			public string GetSpecialCamo(string camoName)
			{
				if (CamoToSpecialCamoFile.ContainsKey(camoName))
				{
					return CamoToSpecialCamoFile[camoName];
				}
				return "";
			}

			public List<string> GetCamos(string pack, string type)
			{
				if (PackTypeCamos.ContainsKey(pack))
				{
					if (PackTypeCamos[pack].ContainsKey(type))
					{
						return PackTypeCamos[pack][type];
					}
					Logger.LogError((object)("Camo type name does not exist: " + type));
				}
				else
				{
					Logger.LogError((object)("Camo pack name does not exist: " + pack));
				}
				return new List<string>();
			}
		}

		public class FileStuff
		{
			public static void InitializeSaveFile()
			{
				string text = FileIO.ReadFile(mod_save_folder_name, save_file_name);
				if (text == null)
				{
					text = CreateDefaultSaveFile();
					FileIO.WriteToFile(mod_save_folder_name, save_file_name, text);
				}
				else
				{
					myDic = ExtensibleDictionary.FromJson(text);
				}
			}

			public static string CreateDefaultSaveFile()
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Expected O, but got Unknown
				myDic = new ExtensibleDictionary();
				questsState = new QuestsState();
				questsState.InitNow();
				string text = JsonConvert.SerializeObject((object)questsState, (Formatting)1);
				myDic.AddEntry("questsState", text);
				return myDic.ToJson();
			}

			public static void ReadVarsFromSaveFile()
			{
				myDic = ExtensibleDictionary.FromJson(FileIO.ReadFile(mod_save_folder_name, save_file_name));
				questsState = JsonConvert.DeserializeObject<QuestsState>(myDic.GetValue("questsState"));
			}

			public static void WriteVarsToMyDic()
			{
				if (myDic == null)
				{
					Logger.LogError((object)"myDic is not initialized.");
					return;
				}
				string text = JsonConvert.SerializeObject((object)questsState, (Formatting)1);
				myDic.InsertOrUpdateEntry("questsState", text);
			}

			public static void RefreshSaveFile()
			{
				WriteVarsToMyDic();
				FileIO.WriteToFile(mod_save_folder_name, save_file_name, myDic.ToJson());
				ReadVarsFromSaveFile();
			}
		}

		[Serializable]
		public struct Quest
		{
			public string gun_name;

			public int quest_type;

			public string camo_reward;

			public int target_goal;

			public int current_progress;

			public string description_key;

			public Quest(string descriptionKey = "", int questType = -1, int targetGoal = 0, string gunName = "", string camoReward = "", int currentProgress = 0)
			{
				gun_name = gunName;
				quest_type = questType;
				camo_reward = camoReward;
				target_goal = targetGoal;
				current_progress = currentProgress;
				description_key = descriptionKey;
			}
		}

		public class QuestsPool
		{
			public static List<Quest> DefaultQuests { get; private set; } = new List<Quest>();


			public static Dictionary<string, List<Quest>> QuestDictionary { get; private set; } = new Dictionary<string, List<Quest>>();


			public static List<Quest> AllMasteryQuests { get; private set; } = new List<Quest>();


			public QuestsPool()
			{
				AllMasteryQuests.AddRange(CreateEmptyS1MasteryQuests());
				DefaultQuests.AddRange(CreateDefaultQuests());
				CreateMelonSpecialQuests();
				TdParadiseSpecialQuests();
			}

			public static void AddQuestToDic(string key, Quest quest)
			{
				if (!QuestDictionary.ContainsKey(key))
				{
					QuestDictionary.Add(key, new List<Quest> { quest });
				}
				else
				{
					QuestDictionary[key].Add(quest);
				}
			}

			public static List<Quest> GetCamoQuests(string camoName)
			{
				ExtractPackAndType(camoName, out var pack, out var type, out var _);
				if (QuestDictionary.ContainsKey(camoName))
				{
					return QuestDictionary[camoName];
				}
				if (QuestDictionary.ContainsKey(pack + "_" + type))
				{
					return QuestDictionary[pack + "_" + type];
				}
				if (QuestDictionary.ContainsKey(pack))
				{
					return QuestDictionary[pack];
				}
				return DefaultQuests;
			}

			public static string GetQuestDescription(string description_key)
			{
				if (description_key == null)
				{
					return "ERROR: Could not find description. Null key.";
				}
				if (!QuestDescriptionsDic.ContainsKey(description_key))
				{
					return "ERROR: Could not find description under given key.";
				}
				string text = QuestDescriptionsDic[description_key];
				return (!(description_key == "unlockCarnNum")) ? (text + "\nGun binded to this challenge must be held or in Quickbelt while event happens.") : (text + "\nQuest tracks regardless of whether you're using gun.");
			}

			public static List<Quest> CreateEmptyS1MasteryQuests()
			{
				List<Quest> list = new List<Quest>();
				Quest quest = default(Quest);
				quest.gun_name = "";
				quest.quest_type = -1;
				quest.camo_reward = "xx_mastery_s1_gold-scuffed";
				quest.target_goal = 100;
				quest.current_progress = 0;
				quest.description_key = "challengeXP";
				Quest quest2 = quest;
				AddQuestToDic("xx_mastery_s1_gold-scuffed", quest2);
				quest = default(Quest);
				quest.gun_name = "";
				quest.target_goal = 1000;
				quest.current_progress = 0;
				quest.camo_reward = "xx_mastery_s1_alien-carniverous";
				quest.quest_type = -1;
				quest.description_key = "challengeXP";
				Quest item = quest;
				AddQuestToDic("xx_mastery_s1_alien-carniverous", quest2);
				quest = default(Quest);
				quest.gun_name = "";
				quest.target_goal = 3;
				quest.current_progress = 0;
				quest.camo_reward = "xx_mastery_s1_GoldTerra";
				quest.quest_type = -2;
				quest.description_key = "unlockCarnNum";
				Quest quest3 = quest;
				AddQuestToDic("xx_mastery_s1_GoldTerra", quest3);
				list.Add(quest3);
				list.Add(quest2);
				list.Add(item);
				return list;
			}

			public static List<Quest> CreateMelonSpecialQuests()
			{
				List<Quest> list = new List<Quest>();
				Quest quest = default(Quest);
				quest.gun_name = "";
				quest.quest_type = 3;
				quest.camo_reward = "xx_MELON_special_MelonStripe";
				quest.target_goal = 5;
				quest.current_progress = 0;
				quest.description_key = "holdPhaseNoDamage";
				Quest quest2 = quest;
				AddQuestToDic("xx_MELON_special_MelonStripe", quest2);
				list.Add(quest2);
				quest = default(Quest);
				quest.gun_name = "";
				quest.quest_type = 3;
				quest.camo_reward = "xx_MELON_special_MelonStripeDARK";
				quest.target_goal = 5;
				quest.current_progress = 0;
				quest.description_key = "holdPhaseNoDamage";
				Quest quest3 = quest;
				AddQuestToDic("xx_MELON_special_MelonStripeDARK", quest3);
				list.Add(quest3);
				quest = default(Quest);
				quest.gun_name = "";
				quest.quest_type = 13;
				quest.camo_reward = "xx_MELON_special_HoneyStripe";
				quest.target_goal = 500;
				quest.current_progress = 0;
				quest.description_key = "takeKillGuardUnaware";
				Quest quest4 = quest;
				AddQuestToDic("xx_MELON_special_HoneyStripe", quest4);
				list.Add(quest4);
				quest = default(Quest);
				quest.gun_name = "";
				quest.quest_type = 10;
				quest.camo_reward = "xx_MELON_special_CanPat";
				quest.target_goal = 15;
				quest.current_progress = 0;
				quest.description_key = "holdKillStreakBonus";
				Quest quest5 = quest;
				AddQuestToDic("xx_MELON_special_CanPat", quest5);
				list.Add(quest5);
				quest = default(Quest);
				quest.gun_name = "";
				quest.quest_type = 10;
				quest.camo_reward = "xx_MELON_special_CanPatDARK";
				quest.target_goal = 15;
				quest.current_progress = 0;
				quest.description_key = "holdKillStreakBonus";
				Quest quest6 = quest;
				AddQuestToDic("xx_MELON_special_CanPatDARK", quest6);
				list.Add(quest6);
				return list;
			}

			public static List<Quest> TdParadiseSpecialQuests()
			{
				List<Quest> list = new List<Quest>();
				Quest quest = default(Quest);
				quest.gun_name = "";
				quest.quest_type = -1;
				quest.camo_reward = "xx_Skitsuphrenia_TD_Bronzeworthy";
				quest.target_goal = 50;
				quest.current_progress = 0;
				quest.description_key = "challengeXP";
				Quest quest2 = quest;
				AddQuestToDic("xx_Skitsuphrenia_TD_Bronzeworthy", quest2);
				list.Add(quest2);
				quest = default(Quest);
				quest.gun_name = "";
				quest.target_goal = 100;
				quest.current_progress = 0;
				quest.camo_reward = "xx_Skitsuphrenia_TD_SilverStallion";
				quest.quest_type = -1;
				quest.description_key = "challengeXP";
				Quest quest3 = quest;
				AddQuestToDic("xx_Skitsuphrenia_TD_SilverStallion", quest3);
				list.Add(quest3);
				quest = default(Quest);
				quest.gun_name = "";
				quest.target_goal = 250;
				quest.current_progress = 0;
				quest.camo_reward = "xx_Skitsuphrenia_TD_GoldEntropy";
				quest.quest_type = -1;
				quest.description_key = "challengeXP";
				Quest quest4 = quest;
				AddQuestToDic("xx_Skitsuphrenia_TD_GoldEntropy", quest4);
				list.Add(quest4);
				quest = default(Quest);
				quest.gun_name = "";
				quest.target_goal = 500;
				quest.current_progress = 0;
				quest.camo_reward = "xx_Skitsuphrenia_TD_FourthHorseman";
				quest.quest_type = -1;
				quest.description_key = "challengeXP";
				Quest quest5 = quest;
				AddQuestToDic("xx_Skitsuphrenia_TD_FourthHorseman", quest5);
				list.Add(quest5);
				return list;
			}

			public static List<Quest> CreateDefaultQuests()
			{
				List<Quest> list = new List<Quest>();
				list.Add(new Quest("completeHoldPhase", 0, 3));
				list.Add(new Quest("holdWaveNoDamage", 4, 2));
				list.Add(new Quest("holdPhaseNoDamage", 3, 1));
				list.Add(new Quest("holdKill", 4, 30));
				list.Add(new Quest("holdHeadshotKill", 5, 15));
				list.Add(new Quest("holdKillDistanceBonus", 9, 2));
				list.Add(new Quest("holdKillStreakBonus", 10, 10));
				list.Add(new Quest("takeCompleteNoAlert", 12, 3));
				list.Add(new Quest("takeKillGuardUnaware", 13, 4));
				return list;
			}
		}

		public class QuestsState
		{
			[SerializeField]
			public Dictionary<string, List<Quest>> questDictionary;

			[SerializeField]
			public List<string> unlockedCamos;

			[SerializeField]
			public Dictionary<string, List<string>> masteryCamosUnlocked;

			private void Start()
			{
				InitNow();
			}

			public void InitNow()
			{
				questDictionary = new Dictionary<string, List<Quest>>();
				unlockedCamos = new List<string>();
				masteryCamosUnlocked = new Dictionary<string, List<string>>();
			}

			public void AddQuest(Quest quest)
			{
				if (!questDictionary.ContainsKey(quest.gun_name))
				{
					questDictionary.Add(quest.gun_name, new List<Quest> { quest });
				}
				else
				{
					questDictionary[quest.gun_name].Add(quest);
				}
			}

			public void RemoveQuest(Quest quest)
			{
				if (questDictionary.ContainsKey(quest.gun_name))
				{
					questDictionary[quest.gun_name].Remove(quest);
				}
				else
				{
					Logger.LogWarning((object)"Not supposed to happen: Someone asked me to unbind a quest from a gun that's not being quest-tracked.");
				}
			}

			public void UnlockCamo(string camo)
			{
				if (!unlockedCamos.Contains(camo))
				{
					unlockedCamos.Add(camo);
				}
			}

			public List<Quest> GetQuestsByRewardCamo(string rewardCamo)
			{
				List<Quest> list = new List<Quest>();
				foreach (List<Quest> value in questDictionary.Values)
				{
					foreach (Quest item in value)
					{
						if (item.camo_reward == rewardCamo)
						{
							list.Add(item);
						}
					}
				}
				return list;
			}

			public void UnlockMasteryCamo(string gunName, string camo)
			{
				if (!masteryCamosUnlocked.ContainsKey(gunName))
				{
					masteryCamosUnlocked[gunName] = new List<string>();
				}
				if (!masteryCamosUnlocked[gunName].Contains(camo))
				{
					masteryCamosUnlocked[gunName].Add(camo);
				}
			}

			public void StaticCamoQuestsCheck()
			{
				int num = 0;
				foreach (List<string> value2 in masteryCamosUnlocked.Values)
				{
					if (value2.Contains("xx_mastery_s1_alien-carniverous"))
					{
						num++;
					}
				}
				List<string> list = new List<string>(questDictionary.Keys);
				for (int i = 0; i < list.Count; i++)
				{
					string text = list[i];
					List<Quest> list2 = questDictionary[text];
					for (int j = 0; j < list2.Count; j++)
					{
						Quest value = list2[j];
						if (value.camo_reward == "xx_mastery_s1_GoldTerra")
						{
							value.current_progress = num;
							list2[j] = value;
							if (value.current_progress >= value.target_goal)
							{
								UnlockMasteryCamo(text, "xx_mastery_s1_GoldTerra");
							}
						}
					}
					questDictionary[text] = list2;
				}
			}

			public List<string> GetMasteryCamosForGun(string gunName)
			{
				if (masteryCamosUnlocked.TryGetValue(gunName, out var value))
				{
					return value;
				}
				return new List<string>();
			}

			public List<Quest> GetActiveCamosForGun(string gunName)
			{
				if (questDictionary.ContainsKey(gunName))
				{
					StaticCamoQuestsCheck();
					return questDictionary[gunName];
				}
				return new List<Quest>();
			}
		}

		public static ExtensibleDictionary myDic;

		public static string mod_folder_name = "NGA-MasteryCamos";

		public static string mod_save_folder_name = "NGA-ProfileSaveFolder";

		public static string save_file_name = "nga_mastery_camos.json";

		public static QuestsState questsState;

		public static string flagDicCamoIdKey = "nga_mc_camoid";

		public static string flagDicSpecialCamoKey = "nga_mc_specialcamo";

		public static string flagDicChangedScaleKey = "nga_mc_changedScale";

		public static CamoPacks camoPacks;

		public static QuestsPool questsPool;

		public static int maxQuestsPerGun = 5;

		public static SpecialCamo specialCamo;

		public static Shader specialShader;

		private const string whileHolding = "Gun binded to this challenge must be held or in Quickbelt while event happens.";

		private const string staticChall = "Quest tracks regardless of whether you're using gun.";

		private const string masteryExclusive = "Unlocks only for this gun.";

		private const string completeHoldPhase = "Complete Hold Points in TnH.";

		private const string holdSecsRemaining = "You get 10 points for every second saved if you finish a TnH Hold early.";

		private const string holdWaveNoDamage = "Receive no damage during waves inside a Hold point in TnH.";

		private const string holdPhaseNoDamage = "Receive no damage during entire Hold point in TnH.";

		private const string holdKill = "Kill sosigs inside a Hold in TnH.";

		private const string holdHeadshotKill = "Kill sosigs with headshots inside a Hold in TnH.";

		private const string holdMeleeKill = "Kill sosigs using Melee (not necessarily using gun) inside a Hold in TnH.";

		private const string holdKillDistanceBonus = "Get 1 point for every 25 meters segment between you and your target killed in a Hold in TnH.";

		private const string holdKillStreakBonus = "Get 1 point for every kill in your kill-streak. Example: Triple kill yields 3 points.";

		private const string takeCompleteNoAlert = "Stealthily take a hold point. That is, press the blue orb in TnH without setting off alert.";

		private const string takeKillGuardUnaware = "Kill unaware guards at a hold point during take phase in TnH.";

		private const string challengeXP = "XP CHALLENGE: You get points for doing literally almost anything in TnH. Kill a sosig, 1 point, was it a headshot, 1 point, so on.\nMastery camos need to be unlocked for each gun.";

		private const string unlockCarnNum = "Unlock the 'Alien Carniverous' camo on 3 guns.\nThis camo will unlock for ALL guns.";

		private static List<string> freebieCamos = new List<string>
		{
			"xx_MW19_digital_Artic", "xx_MW19_dragon_Asphalt", "xx_MW19_reptile_Anaconda", "xx_MW19_skulls_CorpseDigger", "xx_MW19_splinter_Angles", "xx_MW19_spray_ChainLink", "xx_MW19_stripes_Africa", "xx_MW19_tiger_Abominable", "xx_MW19_topo_Barren", "xx_MW19_woodland_Canopy",
			"xx_July4_2024_bigflag", "xx_July4_2024_crossflag", "xx_July4_2024_eagleflag", "xx_July4_2024_embroided", "xx_July4_2024_rhombus", "xx_July4_2024_stars", "xx_July4_2024_winding"
		};

		public static Dictionary<string, string> QuestDescriptionsDic = new Dictionary<string, string>
		{
			{ "completeHoldPhase", "Complete Hold Points in TnH." },
			{ "holdSecsRemaining", "You get 10 points for every second saved if you finish a TnH Hold early." },
			{ "holdWaveNoDamage", "Receive no damage during waves inside a Hold point in TnH." },
			{ "holdPhaseNoDamage", "Receive no damage during entire Hold point in TnH." },
			{ "holdKill", "Kill sosigs inside a Hold in TnH." },
			{ "holdHeadshotKill", "Kill sosigs with headshots inside a Hold in TnH." },
			{ "holdMeleeKill", "Kill sosigs using Melee (not necessarily using gun) inside a Hold in TnH." },
			{ "holdKillDistanceBonus", "Get 1 point for every 25 meters segment between you and your target killed in a Hold in TnH." },
			{ "holdKillStreakBonus", "Get 1 point for every kill in your kill-streak. Example: Triple kill yields 3 points." },
			{ "takeCompleteNoAlert", "Stealthily take a hold point. That is, press the blue orb in TnH without setting off alert." },
			{ "takeKillGuardUnaware", "Kill unaware guards at a hold point during take phase in TnH." },
			{ "challengeXP", "XP CHALLENGE: You get points for doing literally almost anything in TnH. Kill a sosig, 1 point, was it a headshot, 1 point, so on.\nMastery camos need to be unlocked for each gun." },
			{ "unlockCarnNum", "Unlock the 'Alien Carniverous' camo on 3 guns.\nThis camo will unlock for ALL guns." }
		};

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Harmony val = new Harmony("NGA.MasteryCamos");
			SetUpConfigFields();
			InitializeCamos();
			FileStuff.InitializeSaveFile();
			FileStuff.ReadVarsFromSaveFile();
			InitializeQuests();
			Logger.LogMessage((object)"Initialized :)");
			val.PatchAll();
			Logger.LogMessage((object)"Hello, world! Sent from NGA.MasteryCamos 0.0.1");
		}

		private void SetUpConfigFields()
		{
		}

		public static void ApplyCamo(GameObject obj, MasteryCamosGunState gunstate)
		{
			if ((Object)(object)specialShader == (Object)null)
			{
				InitializeShader();
			}
			if ((Object)(object)specialShader == (Object)null)
			{
				Logger.LogError((object)"Special shader NULL after try initialize");
			}
			else if (gunstate.shader_params_v1 != null)
			{
				ApplyCamoV3(obj, gunstate.shader_params_v1);
			}
			else if (gunstate.camo_id != "")
			{
				SpecialCamo specialCamo = new SpecialCamo();
				specialCamo.ColorTexture = gunstate.camo_id;
				ApplyCamoV3(obj, specialCamo);
			}
			else
			{
				Logger.LogError((object)"Apply Camo ERROR: gunstate didn't have any valid inputs");
			}
		}

		public static void ApplyCamoV2(GameObject obj, SpecialCamo camo)
		{
			if (camo == null)
			{
				Logger.LogError((object)"ApplyCamoV2 camo Null");
			}
			camo.ReadTextures();
			ApplySpecialCamoDeep(obj, camo);
			MasteryCamosGunState masteryCamosGunState = new MasteryCamosGunState();
			masteryCamosGunState.shader_params_v1 = camo;
			AddOrUpdateMCStateRecursively(obj, masteryCamosGunState);
		}

		public static void ApplyCamoV3(GameObject obj, SpecialCamo camo)
		{
			if (camo == null)
			{
				Logger.LogError((object)"ApplyCamoV3 camo Null");
			}
			camo.ReadTextures();
			ApplySpecialCamoDeepV2(obj, camo);
			MasteryCamosGunState masteryCamosGunState = new MasteryCamosGunState();
			masteryCamosGunState.shader_params_v1 = camo;
			AddOrUpdateMCStateRecursively(obj, masteryCamosGunState);
		}

		public static void ApplyCamoFromMCState(FVRPhysicalObject __instance, ref GameObject __result, ref FVRViveHand hand)
		{
			MasteryCamosGunState mCState = GetMCState(((Component)__instance).gameObject);
			if ((Object)(object)mCState != (Object)null)
			{
				ApplyCamo(__result, mCState);
			}
		}

		public static List<string> GetWeaponsOnBody()
		{
			List<string> list = new List<string>();
			for (int i = 0; i < GM.CurrentMovementManager.Hands.Length; i++)
			{
				if ((Object)(object)GM.CurrentMovementManager.Hands[i].CurrentInteractable != (Object)null && GM.CurrentMovementManager.Hands[i].CurrentInteractable is FVRFireArm && !list.Contains(((Object)((Component)GM.CurrentMovementManager.Hands[i].CurrentInteractable).gameObject).name))
				{
					list.Add(((Object)((Component)GM.CurrentMovementManager.Hands[i].CurrentInteractable).gameObject).name);
				}
			}
			for (int j = 0; j < GM.CurrentPlayerBody.QBSlots_Internal.Count; j++)
			{
				if ((Object)(object)GM.CurrentPlayerBody.QBSlots_Internal[j].CurObject != (Object)null)
				{
					FVRPhysicalObject curObject = GM.CurrentPlayerBody.QBSlots_Internal[j].CurObject;
					if ((Object)(object)curObject != (Object)null && curObject.IsDeepBelted() && curObject is FVRFireArm && !list.Contains(((Object)((Component)curObject).gameObject).name))
					{
						list.Add(((Object)((Component)curObject).gameObject).name);
					}
				}
			}
			return list;
		}

		public static bool IncrementQuests(string gun_name, int eventKey)
		{
			bool result = false;
			List<Quest> list = questsState.questDictionary[gun_name];
			for (int i = 0; i < list.Count; i++)
			{
				Quest value = list[i];
				if (value.current_progress >= value.target_goal)
				{
					continue;
				}
				if (eventKey == value.quest_type || value.quest_type == -1)
				{
					value.current_progress++;
				}
				else if (value.quest_type == 6 && (eventKey == 7 || eventKey == 8))
				{
					value.current_progress++;
				}
				if (value.current_progress >= value.target_goal)
				{
					if (value.quest_type != -1)
					{
						questsState.UnlockCamo(value.camo_reward);
					}
					else
					{
						questsState.UnlockMasteryCamo(value.gun_name, value.camo_reward);
					}
				}
				questsState.questDictionary[value.gun_name][i] = value;
				result = true;
			}
			return result;
		}

		public static Texture GetTexture(string camo_file_name)
		{
			string text = camoPacks.GetCamoFile(camo_file_name);
			if (text == "")
			{
				text = Paths.PluginPath + "/" + mod_folder_name + "/" + camo_file_name + ".png";
			}
			Texture val = LoadPngTexture(text);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Logger.LogError((object)("Error loading texture path: " + text));
			return null;
		}

		public static Texture LoadPngTexture(string image_path)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			if (!string.IsNullOrEmpty(image_path))
			{
				byte[] array;
				try
				{
					array = File.ReadAllBytes(image_path);
				}
				catch (IOException ex)
				{
					Logger.LogError((object)("Error reading file: " + ex.Message));
					return null;
				}
				Texture2D val = new Texture2D(2, 2);
				if (val.LoadImage(array))
				{
					return (Texture)(object)val;
				}
				Logger.LogError((object)"Failed to LoadImage");
				return null;
			}
			Logger.LogError((object)"Image path is not specified.");
			return null;
		}

		public static void AddOrUpdateMCStateRecursively(GameObject obj, MasteryCamosGunState state)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			if ((Object)(object)obj == (Object)null)
			{
				Logger.LogError((object)"AddOrUpdateMCStateRecursively had a null obj?");
				return;
			}
			FVRPhysicalObject component = obj.GetComponent<FVRPhysicalObject>();
			if ((Object)(object)component != (Object)null)
			{
				MasteryCamosGunState component2 = obj.GetComponent<MasteryCamosGunState>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.CopyState(state);
				}
				else
				{
					component2 = obj.gameObject.AddComponent<MasteryCamosGunState>();
					component2.CopyState(state);
				}
			}
			foreach (Transform item in obj.transform)
			{
				Transform val = item;
				AddOrUpdateMCStateRecursively(((Component)val).gameObject, state);
			}
		}

		public static void AddOrUpdateMCStateSingle(GameObject obj, MasteryCamosGunState state)
		{
			if ((Object)(object)obj == (Object)null)
			{
				Logger.LogError((object)"AddOrUpdateMCStateRecursively had a null obj?");
				return;
			}
			FVRPhysicalObject component = obj.GetComponent<FVRPhysicalObject>();
			if ((Object)(object)component != (Object)null)
			{
				MasteryCamosGunState component2 = obj.GetComponent<MasteryCamosGunState>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.CopyState(state);
					return;
				}
				component2 = obj.gameObject.AddComponent<MasteryCamosGunState>();
				component2.CopyState(state);
			}
		}

		public static MasteryCamosGunState GetMCState(GameObject parentObject)
		{
			return parentObject.GetComponent<MasteryCamosGunState>();
		}

		public static void ChangeAlbedo(GameObject obj, Texture newAlbedoTexture)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			if (((Object)obj).name.StartsWith("MuzzleSmoke") || ((Object)obj).name.StartsWith("MuzzleFire") || ((Object)obj).name.StartsWith("VolumetricLight") || ((Object)obj).name.StartsWith("Lens") || ((Object)obj).name.StartsWith("Render") || ((Object)obj).name.StartsWith("PSystem") || (Object)(object)obj.GetComponent<HolographicSight>() != (Object)null || (Object)(object)obj.GetComponent<ParticleSystem>() != (Object)null)
			{
				return;
			}
			Renderer component = obj.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null && component.materials.Length != 0)
			{
				Material val = new Material(component.materials[0]);
				val.mainTexture = newAlbedoTexture;
				component.material = val;
			}
			foreach (Transform item in obj.transform)
			{
				Transform val2 = item;
				ChangeAlbedo(((Component)val2).gameObject, newAlbedoTexture);
			}
		}

		public static void ApplySpecialCamoDeep(GameObject obj, SpecialCamo camo)
		{
			MeshRenderer[] componentsInChildren = obj.GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Object)(object)((Renderer)val).material != (Object)null))
				{
					continue;
				}
				GameObject gameObject = ((Component)((Component)val).transform).gameObject;
				if (!((Object)gameObject).name.StartsWith("MuzzleSmoke") && !((Object)gameObject).name.StartsWith("MuzzleFire") && !((Object)gameObject).name.StartsWith("VolumetricLight") && !((Object)gameObject).name.StartsWith("Lens") && !((Object)gameObject).name.StartsWith("Render") && !((Object)gameObject).name.StartsWith("PSystem") && !((Object)(object)gameObject.GetComponent<HolographicSight>() != (Object)null) && !((Object)(object)gameObject.GetComponent<ParticleSystem>() != (Object)null) && ((Object)((Renderer)val).material.shader).name.Contains("Alloy/Core"))
				{
					if ((Object)(object)specialShader == (Object)null)
					{
						Logger.LogError((object)"Special shader is NULL!!");
						break;
					}
					camo.ApplyCamo(((Renderer)val).material, specialShader);
				}
			}
		}

		public static void ApplySpecialCamoDeepV2(GameObject obj, SpecialCamo camo)
		{
			if ((Object)(object)specialShader == (Object)null)
			{
				Logger.LogError((object)"Special shader is NULL!!");
				return;
			}
			List<Renderer> list = new List<Renderer>();
			Renderer[] componentsInChildren = obj.GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				GameObject gameObject = ((Component)((Component)val).transform).gameObject;
				if (!((Object)gameObject).name.StartsWith("MuzzleSmoke") && !((Object)gameObject).name.StartsWith("MuzzleFire") && !((Object)gameObject).name.StartsWith("VolumetricLight") && !((Object)gameObject).name.StartsWith("Lens") && !((Object)gameObject).name.StartsWith("Render") && !((Object)gameObject).name.StartsWith("PSystem") && !((Object)(object)gameObject.GetComponent<HolographicSight>() != (Object)null) && !((Object)(object)gameObject.GetComponent<ParticleSystem>() != (Object)null))
				{
					list.Add(val);
				}
			}
			Renderer[] array = list.ToArray();
			if (array == null)
			{
				Logger.LogError((object)"Renderers null");
			}
			else if (camo == null)
			{
				Logger.LogError((object)"Camo null");
			}
			else if ((Object)(object)specialShader == (Object)null)
			{
				Logger.LogError((object)"specialShader null");
			}
			else
			{
				camo.ApplyCamoMultiple(array, specialShader);
			}
		}

		public static SpecialCamo LoadSpecialCamoFromFile(string fullFilename)
		{
			if (fullFilename == "")
			{
				return null;
			}
			SpecialCamo specialCamo = new SpecialCamo();
			if (Directory.Exists(Path.GetDirectoryName(fullFilename)))
			{
				if (File.Exists(fullFilename))
				{
					return JsonUtility.FromJson<SpecialCamo>(File.ReadAllText(fullFilename));
				}
				Logger.LogError((object)"Load Special Camofromfile: FILE DNE");
			}
			else
			{
				Logger.LogError((object)"Load Special Camofromfile: DIRECTORY DNE");
			}
			return null;
		}

		public static string FindFileInPlugin(string fileName)
		{
			string pluginPath = Paths.PluginPath;
			string[] directories = Directory.GetDirectories(pluginPath);
			string result = "";
			string[] array = directories;
			foreach (string path in array)
			{
				string[] files = Directory.GetFiles(path, fileName);
				string[] array2 = files;
				foreach (string text in array2)
				{
					result = text;
				}
			}
			return result;
		}

		public static void InitializeCamos()
		{
			questsPool = new QuestsPool();
			string pluginPath = Paths.PluginPath;
			string[] directories = Directory.GetDirectories(pluginPath);
			camoPacks = new CamoPacks();
			specialCamo = new SpecialCamo();
			string[] array = directories;
			foreach (string path in array)
			{
				string[] files = Directory.GetFiles(path, "xx_*.png");
				string[] array2 = files;
				foreach (string path2 in array2)
				{
					string fullPath = Path.GetFullPath(path2);
					string fileName = Path.GetFileName(path2);
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
					string[] array3 = fileNameWithoutExtension.Split(new char[1] { '_' });
					if (array3.Length >= 3)
					{
						string pack = array3[1];
						string type = array3[2];
						camoPacks.AddCamo(pack, type, fileNameWithoutExtension, fullPath);
					}
					else
					{
						Logger.LogError((object)("Camo name is malformatted: " + fileNameWithoutExtension));
					}
				}
				string[] files2 = Directory.GetFiles(path, "xx_*.json");
				string[] array4 = files2;
				foreach (string path3 in array4)
				{
					string fullPath2 = Path.GetFullPath(path3);
					string fileName2 = Path.GetFileName(path3);
					string fileNameWithoutExtension2 = Path.GetFileNameWithoutExtension(fileName2);
					string[] array5 = fileNameWithoutExtension2.Split(new char[1] { '_' });
					if (array5.Length >= 3)
					{
						string pack2 = array5[1];
						string type2 = array5[2];
						camoPacks.AddCamo(pack2, type2, fileNameWithoutExtension2, fullPath2);
					}
					else
					{
						Logger.LogError((object)("Camo name is malformatted: " + fileNameWithoutExtension2));
					}
				}
			}
			foreach (string camoName in camoPacks.CamoNames)
			{
			}
			foreach (KeyValuePair<string, Dictionary<string, List<string>>> packTypeCamo in camoPacks.PackTypeCamos)
			{
				foreach (KeyValuePair<string, List<string>> item in packTypeCamo.Value)
				{
					foreach (string item2 in item.Value)
					{
					}
				}
			}
		}

		public static void InitializeQuests()
		{
			List<string> list = questsState.questDictionary.Keys.ToList();
			foreach (string item in list)
			{
				BindMasteryQuestsToGun(item);
			}
			foreach (string freebieCamo in freebieCamos)
			{
				questsState.UnlockCamo(freebieCamo);
			}
		}

		public static void InitializeShader()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			FVRObject val = IM.OD["NGA_ShaderHolder"];
			GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)val).GetGameObject(), Vector3.up, Quaternion.identity);
			if ((Object)(object)val2 == (Object)null)
			{
				Logger.LogError((object)"Initializing shader FAILED: ShaderHolder obj null");
				return;
			}
			Transform transform = val2.transform;
			if ((Object)(object)transform == (Object)null)
			{
				Logger.LogError((object)"Initializing shader FAILED: ShaderHolder transform is null");
				return;
			}
			Renderer component = ((Component)transform).GetComponent<Renderer>();
			if ((Object)(object)component == (Object)null)
			{
				Logger.LogError((object)"Initializing shader FAILED: ShaderHolder baseRenderer is null");
			}
			else
			{
				specialShader = component.material.shader;
			}
		}

		public static void ExtractPackAndType(string camoName, out string pack, out string type, out string cleanName)
		{
			string[] array = camoName.Split(new char[1] { '_' });
			if (array.Length >= 4)
			{
				pack = array[1];
				type = array[2];
				cleanName = array[3];
			}
			else
			{
				pack = string.Empty;
				type = string.Empty;
				cleanName = string.Empty;
			}
		}

		public static void BindMasteryQuestsToGun(string d_gun_name)
		{
			List<Quest> activeCamosForGun = questsState.GetActiveCamosForGun(d_gun_name);
			List<Quest> allMasteryQuests = QuestsPool.AllMasteryQuests;
			for (int i = 0; i < allMasteryQuests.Count; i++)
			{
				Quest quest = allMasteryQuests[i];
				bool flag = false;
				for (int j = 0; j < activeCamosForGun.Count; j++)
				{
					if (activeCamosForGun[j].camo_reward == quest.camo_reward)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					quest.gun_name = d_gun_name;
					questsState.AddQuest(quest);
				}
			}
		}

		public static int CountChallengesForGun(string gunName)
		{
			if (!questsState.questDictionary.ContainsKey(gunName))
			{
				return 0;
			}
			List<Quest> list = questsState.questDictionary[gunName];
			int num = 0;
			foreach (Quest quest in list)
			{
				if (!QuestsPool.AllMasteryQuests.Exists((Quest masteryQuest) => masteryQuest.camo_reward == quest.camo_reward))
				{
					num++;
				}
			}
			return num;
		}
	}
	public class MasteryCamosGunState : MonoBehaviour
	{
		public string camo_id = "";

		public SpecialCamo shader_params_v1;

		public void CopyState(MasteryCamosGunState state)
		{
			camo_id = state.camo_id;
			string text = JsonUtility.ToJson((object)state.shader_params_v1);
			shader_params_v1 = JsonUtility.FromJson<SpecialCamo>(text);
		}
	}
	[Serializable]
	public class SpecialCamo
	{
		public string ColorTexture = "";

		public string PBRTexture = "";

		public float CamoStrength = 1f;

		public float CamoPBRStrength = 1f;

		public float CamoMetallic = 0f;

		public float CamoRoughness = 0.35f;

		public float CamoSpecularity = 0.5f;

		public float Scale = 6f;

		public Vector3 Scroll = Vector3.zero;

		public bool UseUVProjection = false;

		public Vector2 UVScale = Vector2.one;

		public Vector2 UVOffset = Vector2.zero;

		public float TriplanarEdgeBlend = 0.25f;

		public Vector3 TriplanarPosition = Vector3.zero;

		public string SecondaryColorTexture = "";

		public string SecondaryPBRTexture = "";

		public float SecondaryCamoMaskCutoff = 0.1f;

		public bool SecondaryCamoMaskInvert = false;

		public float SecondaryCamoStrength = 1f;

		public float SecondaryCamoPBRStrength = 1f;

		public float SecondaryCamoMetallic = 1f;

		public float SecondaryCamoRoughness = 1f;

		public float SecondaryCamoSpecularity = 0.5f;

		public string CamoMaskChannel = "";

		public float CamoMaskMin = 0f;

		public float CamoMaskMax = 1f;

		public float CamoMaskSharpness = 0.5f;

		public bool InvertCamoMask = false;

		[NonSerialized]
		public Texture2D _ColorTexture = null;

		[NonSerialized]
		public Texture2D _PBRTexture = null;

		[NonSerialized]
		public Texture2D _SecondaryColorTexture = null;

		[NonSerialized]
		public Texture2D _SecondaryPBRTexture = null;

		private static string[] baseKeywords = new string[4] { "_ALPHABLEND_ON", "_ALPHAPREMULTIPLY_ON", "_ALPHATEST_ON", "_EMISSION" };

		private static string[] baseFloats = new string[15]
		{
			"_BumpScale", "_Cutoff", "_DstBlend", "_SrcBlend", "_Emission", "_EmissionWeight", "_EnableInstancing", "_MainTexUV", "_Metal", "_Occlusion",
			"_RenderQueue", "_Roughness", "_Specularity", "_SpecularTint", "_ZWrite"
		};

		private static string[] baseVectors = new string[3] { "_Color", "_EmissionColor", "_MainTex_ST" };

		private static string[] baseTextures = new string[4] { "_BumpMap", "_EmissionMap", "_MainTex", "_SpecTex" };

		public float GetMaskType()
		{
			string text = CamoMaskChannel.ToLower();
			if (text.Contains("metal"))
			{
				return 1f;
			}
			if (text.Contains("rough"))
			{
				return 4f;
			}
			if (text.Contains("spec"))
			{
				return 2f;
			}
			if (text.Contains("occlu") || text.Contains("ambi") || text.Contains("ao"))
			{
				return 3f;
			}
			return 0f;
		}

		public string GetTexturePath(string texturePath)
		{
			if (texturePath == "")
			{
				return "";
			}
			return MasteryCamos.camoPacks.GetCamoFile(texturePath);
		}

		public Texture2D ReadTexture(string path, bool linear)
		{
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			if (string.IsNullOrEmpty(path) || path == "")
			{
				return null;
			}
			string text = path;
			path = GetTexturePath(path);
			try
			{
				if (!Directory.Exists(Path.GetDirectoryName(path)))
				{
					Debug.LogError((object)("Directory does not exist: " + Path.GetDirectoryName(path)));
					return null;
				}
				if (!File.Exists(path))
				{
					Debug.LogError((object)("File does not exist: " + path));
					return null;
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Error checking directory or file existence: " + ex.Message + "\n file:" + text + "->" + path + "."));
				return null;
			}
			if (!Directory.Exists(Path.GetDirectoryName(path)))
			{
				return null;
			}
			if (!File.Exists(path))
			{
				return null;
			}
			byte[] array = File.ReadAllBytes(path);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false, linear);
			val.LoadImage(array);
			return val;
		}

		public void ReadTextures()
		{
			_ColorTexture = ReadTexture(ColorTexture, linear: false);
			_PBRTexture = ReadTexture(PBRTexture, linear: true);
			_SecondaryColorTexture = ReadTexture(SecondaryColorTexture, linear: false);
			_SecondaryPBRTexture = ReadTexture(SecondaryPBRTexture, linear: true);
		}

		public void ApplyCamo(Material m, Shader camoShader = null)
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)camoShader != (Object)null)
			{
				m.shader = camoShader;
			}
			m.SetTexture("_CamoAlbedo", (Texture)(object)_ColorTexture);
			m.SetTexture("_CamoPacked", (Texture)(object)_PBRTexture);
			m.SetFloat("_CamoStrength", CamoStrength);
			m.SetFloat("_CamoPBRStrength", CamoPBRStrength);
			m.SetFloat("_CamoMetallic", CamoMetallic);
			m.SetFloat("_CamoRoughness", CamoRoughness);
			m.SetFloat("_CamoSpecularity", CamoSpecularity);
			m.SetFloat("_CamoScale", Scale);
			m.SetVector("_CamoScroll", new Vector4(Scroll.x, Scroll.y, Scroll.z, 0f));
			m.SetFloat("_CamoProjection", UseUVProjection ? 0f : 1f);
			if (UseUVProjection)
			{
				m.DisableKeyword("_CAMO_TRIPLANAR");
			}
			else
			{
				m.EnableKeyword("_CAMO_TRIPLANAR");
			}
			m.SetVector("_CamoAlbedo_ST", new Vector4(UVScale.x, UVScale.y, UVOffset.x, UVOffset.y));
			m.SetFloat("_CamoTriplanarBlendOffset", TriplanarEdgeBlend);
			m.SetVector("_CamoTriplanarPositionOffset", new Vector4(TriplanarPosition.x, TriplanarPosition.y, TriplanarPosition.z, 0f));
			if ((Object)(object)_SecondaryColorTexture != (Object)null || (Object)(object)_SecondaryPBRTexture != (Object)null)
			{
				m.SetFloat("_CamoDual", 1f);
				m.EnableKeyword("_CAMO_DUAL");
				m.SetTexture("_Camo2Albedo", (Texture)(object)_SecondaryColorTexture);
				m.SetTexture("_Camo2Packed", (Texture)(object)_SecondaryPBRTexture);
				m.SetFloat("_Camo2Cutoff", SecondaryCamoMaskCutoff);
				m.SetFloat("_Camo2MaskInvert", SecondaryCamoMaskInvert ? 1f : 0f);
				m.SetFloat("_Camo2Strength", SecondaryCamoStrength);
				m.SetFloat("_Camo2PBRStrength", SecondaryCamoPBRStrength);
				m.SetFloat("_Camo2Metallic", SecondaryCamoMetallic);
				m.SetFloat("_Camo2Roughness", SecondaryCamoRoughness);
				m.SetFloat("_Camo2Specularity", SecondaryCamoSpecularity);
			}
			else
			{
				m.SetFloat("_CamoDual", 0f);
				m.DisableKeyword("_CAMO_DUAL");
			}
			m.SetFloat("_CamoMaskType", GetMaskType());
			m.SetFloat("_CamoMaskInvert", InvertCamoMask ? 1f : 0f);
			m.SetFloat("_CamoMaskMin", CamoMaskMin);
			m.SetFloat("_CamoMaskMax", CamoMaskMax);
			m.SetFloat("_CamoMaskSharpness", CamoMaskSharpness);
		}

		private bool CompareMaterialKeywords(Material a, Material b)
		{
			for (int i = 0; i < baseKeywords.Length; i++)
			{
				if (a.IsKeywordEnabled(baseKeywords[i]) != b.IsKeywordEnabled(baseKeywords[i]))
				{
					return false;
				}
			}
			return true;
		}

		private bool CompareMaterialFloats(Material a, Material b)
		{
			for (int i = 0; i < baseFloats.Length; i++)
			{
				if (a.GetFloat(baseFloats[i]) != b.GetFloat(baseFloats[i]))
				{
					return false;
				}
			}
			return true;
		}

		private bool CompareMaterialVectors(Material a, Material b)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < baseVectors.Length; i++)
			{
				if (a.GetVector(baseVectors[i]) != b.GetVector(baseVectors[i]))
				{
					return false;
				}
			}
			return true;
		}

		private bool CompareMaterialTextures(Material a, Material b)
		{
			for (int i = 0; i < baseTextures.Length; i++)
			{
				if ((Object)(object)a.GetTexture(baseTextures[i]) != (Object)(object)b.GetTexture(baseTextures[i]))
				{
					return false;
				}
			}
			return true;
		}

		public bool CompareBaseMaterials(Material a, Material b)
		{
			if (!CompareMaterialKeywords(a, b))
			{
				return false;
			}
			if (!CompareMaterialFloats(a, b))
			{
				return false;
			}
			if (!CompareMaterialVectors(a, b))
			{
				return false;
			}
			if (!CompareMaterialTextures(a, b))
			{
				return false;
			}
			return true;
		}

		public void ApplyCamoMultiple(Renderer[] renderers, Shader shader)
		{
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Expected O, but got Unknown
			List<List<Renderer>> list = new List<List<Renderer>>();
			foreach (Renderer val in renderers)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMaterial == (Object)null || (Object)(object)val.sharedMaterial.shader == (Object)null || !((Object)val.sharedMaterial.shader).name.Contains("Alloy/Core") || !((Object)val.sharedMaterial.shader).name.Contains("Alloy/Core"))
				{
					continue;
				}
				bool flag = false;
				for (int j = 0; j < list.Count; j++)
				{
					if (list[j].Count > 0 && CompareBaseMaterials(val.sharedMaterial, list[j][0].sharedMaterial))
					{
						list[j].Add(val);
						flag = true;
					}
				}
				if (!flag)
				{
					List<Renderer> list2 = new List<Renderer>();
					list2.Add(val);
					list.Add(list2);
				}
			}
			for (int k = 0; k < list.Count; k++)
			{
				if (list[k].Count <= 0)
				{
					continue;
				}
				Material val2 = new Material(shader);
				val2.CopyPropertiesFromMaterial(list[k][0].sharedMaterial);
				((Object)val2).name = ((Object)list[k][0].sharedMaterial).name;
				if (!((Object)val2).name.EndsWith("_Camo"))
				{
					((Object)val2).name = ((Object)val2).name + "_Camo";
				}
				ApplyCamo(val2, shader);
				foreach (Renderer item in list[k])
				{
					item.sharedMaterial = val2;
				}
			}
		}
	}
}