Decompiled source of MagiRu v2.0.5

BepInEx/plugins/MagiRu/MagiRu.Bepin.dll

Decompiled a week 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.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyProduct("MagiRu.Bepin")]
[assembly: AssemblyTitle("MagiRu.Bepin")]
[assembly: AssemblyTrademark("")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: ComVisible(false)]
[assembly: Guid("79350c2e-e03c-4118-9285-41af64b28394")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace MagiRu;

public class CoroutineRunner : MonoBehaviour
{
}
[BepInPlugin("Astetrio.CrazyMan.MagiRu", "MagiRu", "2.0.5")]
public class MagiRu : BaseUnityPlugin
{
	public class Result<T> where T : class
	{
		public T value;
	}

	public const string GUID = "Astetrio.CrazyMan.MagiRu";

	public const string Name = "MagiRu";

	public const string Version = "2.0.5";

	private CoroutineRunner _coroutineRunner;

	private Coroutine _fixSceneSpecificProblemsCoroutine;

	private Coroutine _downloadingNewVersionCoroutine;

	private Text _uiVersion;

	private string _currentGameVersion = "";

	private bool _isRewardSpellUIFixed;

	public static MagiRu Instance { get; private set; }

	public static bool NeedFixesBefore1043 { get; private set; }

	public static bool NeedFixesAfter1046 { get; private set; }

	private void Awake()
	{
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Expected O, but got Unknown
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Expected O, but got Unknown
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Expected O, but got Unknown
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Expected O, but got Unknown
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Инициализация MagiRu 2.0.5");
		Instance = this;
		try
		{
			Type type = AccessTools.TypeByName("VersionSO");
			int num = (int)AccessTools.Method(type, "AsInt", (Type[])null, (Type[])null).Invoke(AccessTools.Property(type, "Inst").GetValue(null), null);
			NeedFixesBefore1043 = num.CompareTo(ParseVersionToInt("1.0.43")) < 0;
			NeedFixesAfter1046 = num.CompareTo(ParseVersionToInt("1.0.46")) >= 0;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Текущая версия игры: {num} = {FormatVersionToString(num)}");
		}
		catch
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Не удалось проверить версию игры");
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Патчим некоторые методы");
		Harmony val = new Harmony("Astetrio.CrazyMan.MagiRu");
		if (TryGetMethod("TextConfig+Initializer", "ApplyResult", out var method))
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Patches), "ApplyResult_TextConfigInitializer", (Type[])null, (Type[])null);
			val.Patch(method, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		try
		{
			method = AccessTools.Method(typeof(InputBinding), "ToDisplayString", new Type[4]
			{
				typeof(string).MakeByRefType(),
				typeof(string).MakeByRefType(),
				typeof(DisplayStringOptions),
				typeof(InputControl)
			}, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Patches), "ToDisplayString_InputBinding", (Type[])null, (Type[])null);
			val.Patch(method, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
		}
		SceneManager.activeSceneChanged += OnSceneChanged;
		GameObject val2 = new GameObject("MagiRu Coroutine Runner");
		((Object)val2).hideFlags = (HideFlags)(((Object)val2).hideFlags | 0x3D);
		Object.DontDestroyOnLoad((Object)(object)val2);
		_coroutineRunner = val2.AddComponent<CoroutineRunner>();
		((MonoBehaviour)_coroutineRunner).StartCoroutine(AsyncAwake());
		ExportFilteredDictionaryToCSV(Translation.AllDictionariesConcated, LoadKeysFromCSV("base-localization.csv"), "russian-localization4.csv");
	}

	public static List<int> LoadKeysFromCSV(string filePath)
	{
		List<int> list = new List<int>();
		try
		{
			using (StreamReader streamReader = new StreamReader(filePath))
			{
				bool flag = true;
				string text;
				while ((text = streamReader.ReadLine()) != null)
				{
					if (flag)
					{
						flag = false;
						continue;
					}
					string[] array = text.Split(new char[1] { ',' });
					if (array.Length > 1 && int.TryParse(array[1], out var result))
					{
						list.Add(result);
					}
				}
			}
			Debug.Log((object)$"Keys loaded from {filePath}: {list.Count}");
		}
		catch (IOException ex)
		{
			Debug.LogError((object)("Failed to load keys from CSV file: " + ex.Message));
		}
		return list;
	}

	public static void ExportFilteredDictionaryToCSV(IReadOnlyDictionary<int, string> data, List<int> keys, string outputPath)
	{
		if (data == null || keys == null || keys.Count == 0)
		{
			Debug.LogError((object)"Data or keys are null/empty. Nothing to export.");
			return;
		}
		try
		{
			using (StreamWriter streamWriter = new StreamWriter(outputPath))
			{
				streamWriter.WriteLine("Key,Value");
				foreach (int key in keys)
				{
					if (data.TryGetValue(key, out var value))
					{
						streamWriter.WriteLine($"{key}^{EscapeCSVValue(value)}");
					}
				}
			}
			Debug.Log((object)("Filtered CSV file created at: " + outputPath));
		}
		catch (IOException ex)
		{
			Debug.LogError((object)("Failed to write CSV file: " + ex.Message));
		}
	}

	private static string EscapeCSVValue(string value)
	{
		if (string.IsNullOrEmpty(value))
		{
			return value;
		}
		if (value.Contains("\"") || value.Contains(",") || value.Contains("\n") || value.Contains("\r"))
		{
			value = value.Replace("\"", "\"\"");
			value = "\"" + value + "\"";
		}
		return value;
	}

	private IEnumerator AsyncAwake()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Чиним размеры некоторых менюшек");
		Result<Transform> result1 = new Result<Transform>();
		Result<Text> result2 = new Result<Text>();
		Result<RectTransform> result3 = new Result<RectTransform>();
		yield return this.SearchFor<Text>(result2, (Transform)null, "Version", searchSame: true, -1f);
		_uiVersion = result2.value;
		((Graphic)_uiVersion).raycastTarget = false;
		((Graphic)_uiVersion).rectTransform.pivot = new Vector2(0f, 0.5f);
		((Graphic)_uiVersion).rectTransform.anchoredPosition = new Vector2(10f, 10f);
		((Graphic)_uiVersion).rectTransform.sizeDelta = new Vector2(1200f, 20f);
		_currentGameVersion = _uiVersion.text;
		if (!NeedFixesAfter1046)
		{
			yield return this.SearchFor<Transform>(result1, (Transform)null, "UIInfoWand_Hover", searchSame: false, -1f);
			Transform uiInfoWandHover = result1.value;
			yield return this.SearchFor<Text>(result2, uiInfoWandHover, "Text_CoolDown", searchSame: true, -1f);
			Text textCooldownHover = result2.value;
			yield return this.SearchFor<Text>(result2, uiInfoWandHover, "Text_ShootInterval", searchSame: true, -1f);
			Text textIntervalHover = result2.value;
			yield return this.SearchFor<Text>(result2, uiInfoWandHover, "Text_MPRecover", searchSame: true, -1f);
			Text value = result2.value;
			RectTransform rectTransform = ((Graphic)textCooldownHover).rectTransform;
			rectTransform.sizeDelta += new Vector2(60f, 0f);
			RectTransform rectTransform2 = ((Graphic)textIntervalHover).rectTransform;
			rectTransform2.sizeDelta += new Vector2(60f, 0f);
			RectTransform rectTransform3 = ((Graphic)value).rectTransform;
			rectTransform3.sizeDelta += new Vector2(60f, 0f);
			yield return this.SearchFor<Transform>(result1, (Transform)null, "Panel_Interact", searchSame: true, -1f);
			Transform value2 = result1.value;
			yield return this.SearchFor<Transform>(result1, value2, "UIInfoWand", searchSame: false, -1f);
			Transform uiInfoWandInteractive = result1.value;
			yield return this.SearchFor<Text>(result2, uiInfoWandInteractive, "Text_CoolDown", searchSame: true, -1f);
			Text textCooldownInteractive = result2.value;
			yield return this.SearchFor<Text>(result2, uiInfoWandInteractive, "Text_ShootInterval", searchSame: true, -1f);
			Text textIntervalInteractive = result2.value;
			yield return this.SearchFor<Text>(result2, uiInfoWandInteractive, "Text_MPRecover", searchSame: true, -1f);
			Text value3 = result2.value;
			RectTransform rectTransform4 = ((Graphic)textCooldownInteractive).rectTransform;
			rectTransform4.sizeDelta += new Vector2(60f, 0f);
			RectTransform rectTransform5 = ((Graphic)textIntervalInteractive).rectTransform;
			rectTransform5.sizeDelta += new Vector2(60f, 0f);
			RectTransform rectTransform6 = ((Graphic)value3).rectTransform;
			rectTransform6.sizeDelta += new Vector2(60f, 0f);
			yield return this.SearchFor<Transform>(result1, (Transform)null, "UIPlaceNameMgr", searchSame: true, -1f);
			Transform value4 = result1.value;
			yield return this.SearchFor<Text>(result2, value4, "Text (Legacy)", searchSame: true, -1f);
			RectTransform rectTransform7 = ((Graphic)result2.value).rectTransform;
			rectTransform7.sizeDelta += new Vector2(1000f, 0f);
			yield return this.SearchFor<Transform>(result1, (Transform)null, "Image_Location4", searchSame: true, -1f);
			Transform value5 = result1.value;
			yield return this.SearchFor<Text>(result2, value5, "Text (Legacy)", searchSame: true, -1f);
			RectTransform rectTransform8 = ((Graphic)result2.value).rectTransform;
			rectTransform8.sizeDelta -= new Vector2(20f, 0f);
			yield return this.SearchFor<RectTransform>(result3, (Transform)null, "Panel_InteractBtn", searchSame: true, -1f);
			RectTransform value6 = result3.value;
			try
			{
				value6.sizeDelta += new Vector2(60f, 0f);
				Transform child = ((Transform)value6).GetChild(0);
				Transform obj = ((child is RectTransform) ? child : null);
				((RectTransform)obj).anchoredPosition = ((RectTransform)obj).anchoredPosition - new Vector2(30f, 0f);
				Transform child2 = ((Transform)value6).GetChild(1);
				((RectTransform)((child2 is RectTransform) ? child2 : null)).sizeDelta = Vector2.zero;
				Transform child3 = ((Transform)value6).GetChild(2);
				Transform obj2 = ((child3 is RectTransform) ? child3 : null);
				((RectTransform)obj2).anchoredPosition = ((RectTransform)obj2).anchoredPosition - new Vector2(30f, 0f);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Не удалось починить кнопку взаимодействия\n" + ex.ToString()));
			}
		}
		yield return this.SearchFor<Transform>(result1, (Transform)null, "UIGeneralCompoundMaterialData", searchSame: true, -1f);
		Transform value7 = result1.value;
		try
		{
			((Component)value7.GetChild(8)).gameObject.SetActive(false);
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Не удалось убрать показ сломанного текста у котла\n" + ex2.ToString()));
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"MagiRu Инициализирован");
	}

	private void TryRunFixSceneSpecificProblems(Scene newScene)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		if (_fixSceneSpecificProblemsCoroutine != null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Починка специфичных проблем для сцены (" + ((Scene)(ref newScene)).name + ") была остановлена"));
			((MonoBehaviour)_coroutineRunner).StopCoroutine(_fixSceneSpecificProblemsCoroutine);
			_fixSceneSpecificProblemsCoroutine = null;
		}
		_fixSceneSpecificProblemsCoroutine = ((MonoBehaviour)_coroutineRunner).StartCoroutine(FixSceneSpecificProblems());
		IEnumerator FixSceneSpecificProblems()
		{
			float startFixingTime = Time.time;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Начата починка специфичных проблем для сцены (" + ((Scene)(ref newScene)).name + ")"));
			if (((Scene)(ref newScene)).name == "MainMenu")
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Добавляем кнопку пожертвования");
				Result<Transform> result2 = new Result<Transform>();
				yield return this.SearchFor<Transform>(result2, (Transform)null, "Btn_ReportBug", searchSame: true, -1f);
				Transform value = result2.value;
				GameObject gameObject = ((Component)value.parent).gameObject;
				Transform val = Object.Instantiate<Transform>(value, gameObject.transform);
				((Component)val).transform.SetSiblingIndex(((Component)value).transform.GetSiblingIndex() + 1);
				MonoBehaviour[] components = ((Component)val).GetComponents<MonoBehaviour>();
				foreach (MonoBehaviour val2 in components)
				{
					if (((object)val2).GetType().Assembly.GetName().Name == "Assembly-CSharp")
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Компонент " + ((object)val2).GetType().Name + " уничтожен"));
						Object.Destroy((Object)(object)val2);
						break;
					}
				}
				((Object)val).name = "Btn_Donate";
				((Component)val).GetComponentInChildren<Text>().text = "Дать деняк переводчику :3";
				RectTransform component = ((Component)val).GetComponent<RectTransform>();
				component.anchoredPosition += new Vector2(0f, 96f);
				component.sizeDelta += new Vector2(0f, 16f);
				Button component2 = ((Component)val).GetComponent<Button>();
				component2.onClick = new ButtonClickedEvent();
				((UnityEvent)component2.onClick).AddListener(new UnityAction(OnDonateClicked));
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Кнопка пожертвования добавлена");
			}
			else if (((Scene)(ref newScene)).name == "Battle")
			{
				Result<RectTransform> result1 = new Result<RectTransform>();
				Result<Text> result3 = new Result<Text>();
				if (!_isRewardSpellUIFixed)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Чиним UI выбора нового заклинания");
					GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
					foreach (GameObject val3 in array)
					{
						if (((Object)val3).name == "UIRewardSpell")
						{
							yield return this.SearchFor<Text>(result3, val3.transform, "Text_Info", searchSame: true, -1f);
							Text value2 = result3.value;
							RectTransform rectTransform = ((Graphic)value2).rectTransform;
							rectTransform.sizeDelta += new Vector2(0f, 45f);
							value2.resizeTextForBestFit = true;
							value2.resizeTextMaxSize = 17;
							_isRewardSpellUIFixed = true;
							break;
						}
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)"UI выбора нового заклинания починен");
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Чиним кнопку перековки");
				yield return this.SearchFor<RectTransform>(result1, (Transform)null, "UIPCReroll", searchSame: true, -1f);
				RectTransform uiPcReroll = result1.value;
				if ((Object)(object)uiPcReroll != (Object)null)
				{
					yield return this.SearchFor<RectTransform>(result1, (Transform)(object)uiPcReroll, "Btn_Reroll", searchSame: true, -1f);
					RectTransform value3 = result1.value;
					try
					{
						value3.sizeDelta += new Vector2(60f, 0f);
						value3.anchoredPosition += new Vector2(30f, 0f);
						Transform child = ((Transform)value3).GetChild(0);
						Transform obj = ((child is RectTransform) ? child : null);
						((RectTransform)obj).sizeDelta = ((RectTransform)obj).sizeDelta + new Vector2(50f, 0f);
						Transform child2 = ((Transform)value3).GetChild(1);
						Transform obj2 = ((child2 is RectTransform) ? child2 : null);
						((RectTransform)obj2).anchoredPosition = ((RectTransform)obj2).anchoredPosition + new Vector2(30f, 0f);
						Transform child3 = ((Transform)value3).GetChild(2);
						Transform obj3 = ((child3 is RectTransform) ? child3 : null);
						((RectTransform)obj3).anchoredPosition = ((RectTransform)obj3).anchoredPosition + new Vector2(30f, 0f);
						Transform child4 = ((Transform)value3).GetChild(3);
						Transform obj4 = ((child4 is RectTransform) ? child4 : null);
						((RectTransform)obj4).anchoredPosition = ((RectTransform)obj4).anchoredPosition - new Vector2(30f, 0f);
						Transform child5 = ((Transform)value3).GetChild(4);
						Transform obj5 = ((child5 is RectTransform) ? child5 : null);
						((RectTransform)obj5).anchoredPosition = ((RectTransform)obj5).anchoredPosition - new Vector2(30f, 0f);
						((BaseUnityPlugin)this).Logger.LogInfo((object)"Кнопка перековки починена");
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)this).Logger.LogError((object)("Кнопка перековки не починена\n" + ex.ToString()));
					}
					yield return this.SearchFor<RectTransform>(result1, (Transform)(object)uiPcReroll, "Panel_BtnMask", searchSame: true, -1f);
					RectTransform value4 = result1.value;
					if ((Object)(object)value4 != (Object)null)
					{
						value4.sizeDelta += new Vector2(60f, 0f);
						value4.anchoredPosition += new Vector2(30f, 0f);
					}
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Кнопка перековки не починена");
				}
			}
			UpdateVersionText();
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Специфичные проблемы для сцены ({((Scene)(ref newScene)).name}) починены за ({Time.time - startFixingTime})");
			_fixSceneSpecificProblemsCoroutine = null;
		}
	}

	public void Log(string str, LogLevel logLevel = 16)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		((BaseUnityPlugin)this).Logger.Log(logLevel, (object)str);
	}

	public IEnumerator SearchFor<T>(Result<T> result, Transform parent, string name, bool searchSame = true, float time = -1f) where T : Object
	{
		WaitForSecondsRealtime delay = new WaitForSecondsRealtime(1f);
		float startTime = Time.time;
		result.value = default(T);
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("SearchFor({0}, {1}, {2}, {3})", ((Object)(object)parent != (Object)null) ? ((Object)parent).name : "null", name, searchSame, time));
		Func<string, string, bool> comparator = (string x, string y) => x == y;
		if (!searchSame)
		{
			comparator = (string x, string y) => x.Contains(y);
		}
		if ((Object)(object)parent == (Object)null)
		{
			while ((Object)(object)result.value == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Ищем " + name));
				T[] array = Object.FindObjectsOfType<T>(true);
				foreach (T val in array)
				{
					if (comparator(((Object)val).name, name))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Объект найден " + ((Object)val).name));
						result.value = val;
						break;
					}
				}
				if ((Object)(object)result.value == (Object)null)
				{
					yield return delay;
				}
				if (time >= 0f && Time.time - startTime > time)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Объект не найден");
					break;
				}
			}
		}
		else
		{
			while ((Object)(object)result.value == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Ищем " + name + " внутри " + ((Object)parent).name));
				T[] componentsInChildren = ((Component)parent).GetComponentsInChildren<T>(true);
				foreach (T val2 in componentsInChildren)
				{
					if (comparator(((Object)val2).name, name))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Объект найден " + ((Object)val2).name));
						result.value = val2;
						break;
					}
				}
				if ((Object)(object)result.value == (Object)null)
				{
					yield return delay;
				}
				if (time >= 0f && Time.time - startTime > time)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Объект не найден");
					break;
				}
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"SearchFor({name}) завершён за {Time.time - startTime}s");
	}

	public IEnumerator SearchForAll<T>(List<T> results, Transform parent, string name, float time = -1f) where T : Object
	{
		WaitForSecondsRealtime delay = new WaitForSecondsRealtime(1f);
		float startTime = Time.time;
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("SearchForAll({0}, {1}, {2})", ((Object)(object)parent != (Object)null) ? ((Object)parent).name : "null", name, time));
		if ((Object)(object)parent == (Object)null)
		{
			while (results.Count < 1)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Ищем " + name));
				T[] array = Object.FindObjectsOfType<T>(true);
				foreach (T val in array)
				{
					if (((Object)val).name.Contains(name))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Объект найден " + ((Object)val).name));
						results.Add(val);
					}
				}
				if (results.Count < 1)
				{
					yield return delay;
				}
				if (time >= 0f && Time.time - startTime > time)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Объект не найден");
					break;
				}
			}
		}
		else
		{
			while (results.Count < 1)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Ищем " + name + " внутри " + ((Object)parent).name));
				T[] componentsInChildren = ((Component)parent).GetComponentsInChildren<T>(true);
				foreach (T val2 in componentsInChildren)
				{
					if (((Object)val2).name.Contains(name))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Объект найден " + ((Object)val2).name));
						results.Add(val2);
					}
				}
				if (results.Count < 1)
				{
					yield return delay;
				}
				if (time >= 0f && Time.time - startTime > time)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Объект не найден");
					break;
				}
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"SearchForAll({name}) завершён за {Time.time - startTime}s");
	}

	private bool TryGetMethod(string className, string methodName, out MethodBase method)
	{
		method = null;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Ищем класс " + className));
		Type type = AccessTools.TypeByName(className);
		if (type == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Класс " + className + " не найден"));
			return false;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Ищем метод " + methodName));
		method = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
		if (method == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Метод " + methodName + " не найден"));
			return false;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Метод " + methodName + " найден"));
		return true;
	}

	private IEnumerator DownloadYandexDiskFile(string targetURL, string checksum = null, Action<byte[]> downloaded = null, Action error = null)
	{
		string text = "https://cloud-api.yandex.net/v1/disk/public/resources/download?public_key=" + targetURL;
		UnityWebRequest request = UnityWebRequest.Get(text);
		try
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Посылаем запрос на получение ссылки для скачивания");
			yield return request.SendWebRequest();
			if ((int)request.result == 1)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Пытаемся распарсить результат");
				string targetURL2;
				try
				{
					targetURL2 = ((JToken)JObject.Parse(request.downloadHandler.text)).Value<string>((object)"href");
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)ex);
					yield break;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Начинаем скачивание файла");
				yield return DownloadFile(targetURL2, checksum, 5, downloaded, error);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Не удалось получить ссылку для скачивания файла! (Ошибка: " + request.error + ")"));
			}
		}
		finally
		{
			((IDisposable)request)?.Dispose();
		}
	}

	private IEnumerator DownloadFile(string targetURL, string checksum = null, int maxAttempts = 5, Action<byte[]> downloaded = null, Action error = null)
	{
		if (string.IsNullOrEmpty(targetURL))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"targetURL в DownloadFile пуст");
			yield break;
		}
		int attempts = 0;
		bool success = false;
		while (!success && attempts < maxAttempts)
		{
			attempts++;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Начинаем скачивание файла (попытка {attempts})");
			UnityWebRequest request = UnityWebRequest.Get(targetURL);
			try
			{
				yield return request.SendWebRequest();
				if ((int)request.result == 1)
				{
					byte[] data = request.downloadHandler.data;
					if (string.IsNullOrEmpty(checksum) || VerifyChecksum(data, checksum))
					{
						success = true;
						((BaseUnityPlugin)this).Logger.LogInfo((object)"Файл успешно скачан");
						downloaded?.Invoke(data);
					}
					else
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)"Контрольная сумма отличается. Пробуем ещё раз...");
					}
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Не удалось скачать файл! (Ошибка: " + request.error + ")"));
				}
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
			if (!success && attempts < maxAttempts)
			{
				yield return (object)new WaitForSeconds(1f);
			}
		}
		if (!success)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"Не удалось скачать файл после {maxAttempts} попыток");
			error?.Invoke();
		}
	}

	private bool VerifyChecksum(byte[] data, string expectedMD5)
	{
		using MD5 mD = MD5.Create();
		string text = BitConverter.ToString(mD.ComputeHash(data)).Replace("-", "").ToLowerInvariant();
		((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " && " + expectedMD5));
		return text == expectedMD5.ToLowerInvariant();
	}

	public string GetVersionText()
	{
		return _currentGameVersion + " (Перевод на русский — MagiRu от CrazyMan v2.0.5t)";
	}

	private void UpdateVersionText()
	{
		if ((Object)(object)_uiVersion != (Object)null)
		{
			_uiVersion.text = GetVersionText();
		}
	}

	private static (GameObject, RectTransform) CreateUIElement(string name, Transform parent = null)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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_002d: Expected O, but got Unknown
		GameObject val = new GameObject(name);
		val.transform.SetParent(parent);
		val.layer = LayerMask.NameToLayer("UI");
		return (val, val.AddComponent<RectTransform>());
	}

	private static void ShowPopup(string text, string actionName, float width, Action clickedCallback = null)
	{
		//IL_006e: 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_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Expected O, but got Unknown
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0241: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Expected O, but got Unknown
		GameObject go = CreateUIElement("MagiRu popup canvas").Item1;
		Canvas val = go.AddComponent<Canvas>();
		val.renderMode = (RenderMode)0;
		val.sortingOrder = 32767;
		go.AddComponent<GraphicRaycaster>();
		var (val2, val3) = CreateUIElement("Shadow", ((Component)val).transform);
		val3.anchorMin = Vector2.zero;
		val3.anchorMax = Vector2.one;
		val3.anchoredPosition = Vector2.zero;
		val3.sizeDelta = Vector2.zero;
		((Graphic)val2.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.5f);
		var (val4, val5) = CreateUIElement("Popup", ((Component)val).transform);
		val5.sizeDelta = new Vector2(width, 512f);
		val5.anchoredPosition = Vector2.zero;
		((Graphic)val4.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.5f);
		VerticalLayoutGroup obj = val4.AddComponent<VerticalLayoutGroup>();
		((LayoutGroup)obj).childAlignment = (TextAnchor)4;
		((HorizontalOrVerticalLayoutGroup)obj).spacing = 32f;
		((LayoutGroup)obj).padding = new RectOffset(32, 32, 32, 32);
		ContentSizeFitter obj2 = val4.AddComponent<ContentSizeFitter>();
		obj2.horizontalFit = (FitMode)0;
		obj2.verticalFit = (FitMode)2;
		GameObject item = CreateUIElement("Text", val4.transform).Item1;
		TextMeshProUGUI obj3 = item.AddComponent<TextMeshProUGUI>();
		((TMP_Text)obj3).text = text;
		((TMP_Text)obj3).alignment = (TextAlignmentOptions)258;
		((Graphic)obj3).color = Color.white;
		var (val6, val7) = CreateUIElement("Button", val4.transform);
		val7.sizeDelta = new Vector2(100f, 30f);
		val7.anchoredPosition = new Vector2(0f, -50f);
		Image val8 = val6.AddComponent<Image>();
		((Graphic)val8).color = new Color(0.8f, 0.8f, 0.8f, 1f);
		Button obj4 = val6.AddComponent<Button>();
		LayoutElement obj5 = val6.AddComponent<LayoutElement>();
		obj5.preferredHeight = 64f;
		obj5.flexibleWidth = 1f;
		var (val9, val10) = CreateUIElement("ButtonText", val6.transform);
		val10.anchorMax = Vector2.one;
		val10.anchorMin = Vector2.zero;
		val10.sizeDelta = Vector2.zero;
		val10.anchoredPosition = Vector2.zero;
		TextMeshProUGUI obj6 = val9.AddComponent<TextMeshProUGUI>();
		((TMP_Text)obj6).text = actionName;
		((TMP_Text)obj6).alignment = (TextAlignmentOptions)514;
		((Graphic)obj6).color = Color.black;
		((Selectable)obj4).targetGraphic = (Graphic)(object)val8;
		((UnityEvent)obj4.onClick).AddListener((UnityAction)delegate
		{
			EventSystem.current.sendNavigationEvents = true;
			clickedCallback?.Invoke();
			Object.Destroy((Object)(object)go);
		});
		((Selectable)obj4).Select();
		EventSystem.current.sendNavigationEvents = false;
	}

	private static string FormatVersionToString(int version)
	{
		List<string> list = new List<string>();
		if (version % 100 != 0)
		{
			list.Add($"f{version % 10}");
		}
		version /= 100;
		list.Insert(0, (version % 100).ToString());
		list.Insert(0, ".");
		version /= 100;
		list.Insert(0, (version % 1000).ToString());
		list.Insert(0, ".");
		version /= 1000;
		list.Insert(0, version.ToString());
		return string.Join("", list);
	}

	private static int ParseVersionToInt(string version)
	{
		string[] array = version.Trim().ToLower().Split(new char[1] { '.' }, StringSplitOptions.None);
		int num = int.Parse(array[0]);
		int num2 = int.Parse(array[1]);
		array = array[2].Split(new char[1] { 'f' }, StringSplitOptions.None);
		int num3 = int.Parse(array[0]);
		return ((array.Length > 1) ? int.Parse(array[1]) : 0) + num3 * 100 + num2 * 10000 + num * 10000000;
	}

	private void OnSceneChanged(Scene from, Scene to)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		TryRunFixSceneSpecificProblems(to);
	}

	private static void OnDonateClicked()
	{
		Application.OpenURL("https://www.donationalerts.com/r/crazyman_ik");
	}
}
public static class Translation
{
	private const string _HPColor = "";

	private const string _ManaColor = "";

	private const string _CritColor = "#FE5D00";

	private const string _ShieldColor = "#C500FE";

	private const string _MultishotColor = "#7F5AFC";

	private const string _PostEnergyColor = "#E086EC";

	private const string _TempShieldColor = "#9D9D9B";

	private const string _FinalDamageColor = "#DC143C";

	private const string _EffectRadiusColor = "#FFD700";

	public static readonly IReadOnlyDictionary<int, string> Set = new Dictionary<int, string>
	{
		{ 10000001, "Оригинал" },
		{ 10000002, "Набор Фокусника" },
		{ 10000003, "Набор Призывателя" },
		{ 10000004, "Набор Уклониста" },
		{ 10000005, "Набор Духа" },
		{ 10000006, "Набор Мага-Воина" },
		{ 10000007, "Набор Би Ань/(Кроссовер с Warm Snow)" },
		{ 10000008, "Набор Жнеца/(Кроссовер с Backpack Battles)" },
		{ 10000009, "Набор Бина/(Кроссовер с Bing in Wonderland)" },
		{ 10100001, "" },
		{ 10100002, "" },
		{ 10100003, " Заверши Главу 2" },
		{ 10100004, " Заверши Главу 3 на Нормальной Сложности" },
		{ 10100005, " Экипируй одновременно 3 жезла с Духом Жезла" },
		{ 10100006, " Убей int1 врагов Мечом-Светозаром" },
		{ 10100007, " Убей любого Босса Клинком Правосудия" },
		{ 10100008, " Достигни int1 стаков отравления на враге" },
		{ 10100009, " Открой int1 Наборов" }
	};

	public static readonly IReadOnlyDictionary<int, string> ActivateGirl = new Dictionary<int, string>
	{
		{ 11000001, "Набор Элементальных Заклинаний" },
		{ 11000002, "Мешочек со Всячиной" },
		{ 11000003, "Набор Заклинаний-Триггеров" },
		{ 11000004, "Набор Накопительных Заклинаний" },
		{ 11000005, "Набор Мастера Призывов" },
		{ 11000006, "Набор Вдохновения" },
		{ 11000007, "Набор Полезных Заклинаний" },
		{ 11000008, "Набор для Продвинутых Призывов" },
		{ 11000009, "Набор Калибрующих Камней" },
		{ 11000010, "Набор Звёздной Пыли" },
		{ 11000011, "Набор Максимизации" },
		{ 11000012, "Набор Заклинаний 12" },
		{ 11000013, "Набор Заклинаний 13" },
		{ 11000014, "Набор Заклинаний 14" },
		{ 11000101, "Магическая Предрасположенность" },
		{ 11000102, "Сумка с Реликвиями" },
		{ 11000103, "Закрепление Заклинаний" },
		{ 11000104, "Магическая Предрасположенность+" },
		{ 11000201, "Чутьё Девушки-Монстра" },
		{ 11000202, "Чутьё Девушки-Монстра+" },
		{ 11000203, "Чутьё Девушки-Монстра++" },
		{ 11100001, "" },
		{ 11100002, "" },
		{ 11100003, "" },
		{ 11100004, "" },
		{ 11100005, "" },
		{ 11100006, "" },
		{ 11100007, "" },
		{ 11100008, "" },
		{ 11100009, "" },
		{ 11100010, "" },
		{ 11100011, "" },
		{ 11100012, "" },
		{ 11100013, "" },
		{ 11100014, "" },
		{ 11100101, "При подборе заклинания, будет даваться выбор из 3 заклинаний" },
		{ 11100102, "" },
		{ 11100103, "Ты сможешь закреплять заклинания до следующего выбора" },
		{ 11100104, "При подборе заклинания, будет даваться выбор из 4 заклинаний" },
		{ 11100201, "Лимит отключений заклинаний +int1, бесплатные отключения +int2" },
		{ 11100202, "Лимит отключений заклинаний +int1, бесплатные отключения +int2" },
		{ 11100203, "Лимит отключений заклинаний +int1, бесплатные отключения +int2" }
	};

	public static readonly IReadOnlyDictionary<int, string> Resource = new Dictionary<int, string>
	{
		{ 6000011, "Монета" },
		{ 6000012, "Алмаз" },
		{ 6000013, "Изумруд" },
		{ 6000021, "Ключ" },
		{ 6000022, "2 Ключа" },
		{ 6000031, "Малое Здоровье" },
		{ 6000032, "Здоровье" },
		{ 6000033, "Большое Здоровье" },
		{ 6000041, "Малый Щит" },
		{ 6000042, "Щит" },
		{ 6000043, "Большой Щит" },
		{ 6000101, "Магический Кристалл" },
		{ 6000102, "Магический Кристалл" },
		{ 6000103, "Магический Кристалл" },
		{ 6000111, "Древняя Кровь" },
		{ 6000112, "Древняя Кровь" },
		{ 6000113, "Древняя Кровь" },
		{ 6000121, "Ядро Хаоса" },
		{ 6100011, "Монета x1" },
		{ 6100012, "Монета x5" },
		{ 6100013, "Монета x50" },
		{ 6100021, "Используется для открытия запертых объектов" },
		{ 6100022, "Используется для открытия запертых объектов" },
		{
			6100031,
			"Востанавливает int1 " + Colorize("ОЗ", "")
		},
		{
			6100032,
			"Востанавливает int1 " + Colorize("ОЗ", "")
		},
		{
			6100033,
			"Востанавливает int1 " + Colorize("ОЗ", "")
		},
		{
			6100041,
			"Даёт int1 " + Colorize("Щитов", "#C500FE")
		},
		{
			6100042,
			"Даёт int1 " + Colorize("Щитов", "#C500FE")
		},
		{
			6100043,
			"Даёт int1 " + Colorize("Щитов", "#C500FE")
		},
		{ 6100101, "Магический Кристалл" },
		{ 6100102, "Магический Кристалл" },
		{ 6100103, "Магический Кристалл" },
		{ 6100111, "Древняя Кровь" },
		{ 6100112, "Древняя Кровь" },
		{ 6100113, "Древняя Кровь" },
		{ 6100121, "Ядро Хаоса" }
	};

	public static readonly IReadOnlyDictionary<int, string> Research = new Dictionary<int, string>
	{
		{ 9000011, "Секретный Путь" },
		{ 9000012, "Секретный Путь 2" },
		{ 9000021, "Энциклопедия" },
		{ 9000031, "Патронташ для Зелий" },
		{ 9000032, "Патронташ для Зелий+" },
		{ 9000033, "Патронташ для Зелий++" },
		{ 9000041, "Пополнение Магазина" },
		{ 9000042, "Пополнение Магазина+" },
		{ 9000043, "Пополнение Магазина++" },
		{ 9000044, "Пополнение Магазина+++" },
		{ 9000051, "Поддерживающий Модуль" },
		{ 9000052, "Поддерживающий Модуль+" },
		{ 9000061, "Брелок" },
		{ 9000062, "Брелок 2" },
		{ 9000063, "Брелок 3" },
		{ 9000111, "Ягодный Куст" },
		{ 9000121, "Хранилище Сокровищ" },
		{ 9000131, "Падальщики" },
		{ 9000141, "xxx" },
		{ 9000211, "Прокаченные Манекены" },
		{ 9000221, "Короткий Путь (Лес Реликвий)" },
		{ 9000311, "Преобразователь Ресурсов" },
		{ 9000321, "<size=20>Короткий Путь (Вечная Крепость)</size>" },
		{ 9000411, "<size=20>Короткий Путь (Тропа Паломников)</size>" },
		{
			9100011,
			"Даёт шанс найти комнату с фонтаном. Он позволяет восстановить int1% " + Colorize("ОЗ", "")
		},
		{
			9100012,
			"Даёт шанс найти комнату с фонтаном. Он позволяет восстановить int1% " + Colorize("ОЗ", "")
		},
		{ 9100021, "Записывает различные встречи и открытия во время твоего приключения" },
		{ 9100031, "Вместимость Зелий +int1" },
		{ 9100032, "Вместимость Зелий +int1" },
		{ 9100033, "Вместимость Зелий +int1" },
		{ 9100041, "Даёт ×int1 переброса в Магазине" },
		{ 9100042, "Даёт ×int1 переброса в Магазине" },
		{ 9100043, "Даёт ×int1 перебросов в Магазине" },
		{ 9100044, "Даёт ×int1 перебросов в Магазине" },
		{ 9100051, "Повышает прочность Перековальни" },
		{ 9100052, "Значительно повышает прочность Перековальни" },
		{ 9100061, "Даёт int1 доп. ключ перед стартом приключения" },
		{ 9100062, "Даёт int1 доп. ключа перед стартом приключения" },
		{ 9100063, "Даёт int1 доп. ключа перед стартом приключения" },
		{ 9100111, "Повышает шанс нахождения ягодных кустов в Лесу Реликвий. Они помогут восстановить твои силы" },
		{ 9100121, "Повышает шанс нахождения ящиков с сокровищами в Вечной Крепости. Они хранят в себе ценные предметы" },
		{ 9100131, "Даёт шанс встретить Падальщиков на Тропе Паломников. Они любят собирать заклинания, которые падают рядом с бездной" },
		{ 9100141, "Даёт шанс найти xxx в Бездне Минувших Дней" },
		{ 9100211, "Тренировочные манекены, которые могут показывать более детальную информацию. А также, их можно будет включать/выключать" },
		{ 9100221, "Даёт шанс найти короткий путь в Лесу Реликвий (эквивалентно прохождению 4 комнат за раз и получению 4 наград)" },
		{ 9100311, "Позволяет преобразовывать Магические Кристаллы, Древнюю Кровь и Ядра Хаоса между собой" },
		{ 9100321, "Даёт шанс найти короткий путь в Вечной Крепости (эквивалентно прохождению 4 комнат за раз и получению 4 наград)" },
		{ 9100411, "Даёт шанс найти короткий путь на Тропе Паломников (эквивалентно прохождению 4 комнат за раз и получению 4 наград)" }
	};

	public static readonly IReadOnlyDictionary<int, string> Handbook = new Dictionary<int, string>
	{
		{ 14000001, "Удобное Управление" },
		{ 14000002, "Про жезлы" },
		{ 14000003, "Про заклинания" },
		{ 14000101, "Быстрое Надевание/Снятие Заклинаний" },
		{ 14000102, "Групповое Надевание/Снятие Заклинаний" },
		{ 14000103, "Быстрая Смена Жезла" },
		{
			14000201,
			Colorize("Мана", "") ?? ""
		},
		{
			14000202,
			"Реген. " + Colorize("Маны", "")
		},
		{ 14000203, "Интервал" },
		{ 14000204, "Задержка" },
		{ 14000205, "Разброс" },
		{ 14000206, "Вместимость Блока Заклинаний" },
		{ 14000207, "Вторичные Слоты" },
		{ 14000301, "Урон" },
		{ 14000302, "УВС" },
		{
			14000303,
			Colorize("Радиус Эффекта", "#FFD700") ?? ""
		},
		{ 14000304, "Лимит Призыва" },
		{
			14000305,
			"Стоимость " + Colorize("Маны", "")
		},
		{ 14000306, "Продолжительный Каст" },
		{
			14000307,
			Colorize("Крит. Шанс", "#FE5D00") ?? ""
		},
		{
			14000308,
			Colorize("Множитель Урона", "#DC143C") ?? ""
		},
		{ 14000309, "Пробивание Заклинаний" },
		{ 14000310, "Используемые Слоты" },
		{ 14000311, "Слоты Заклинаний" },
		{ 14000312, "Число Выстрелов" },
		{ 14000313, "Заряжаемый Каст" },
		{
			14000314,
			Colorize("ОЗ", "") ?? ""
		},
		{ 14100101, "Нажатие правой кнопкой мыши по заклинаниям позволяет быстро надевать или снимать их." },
		{ 14100102, "Удерживание кнопки Shift и наведение на заклинания мышкой, позволяет быстро надевать или снимать их." },
		{ 14100103, "Использование колёсика мыши позволяет быстро переключать жезлы." },
		{ 14100201, "Как много магии имеется в жезле." },
		{
			14100202,
			"Количество " + Colorize("Маны", "") + ", восстанавливаемой за 1 секунду."
		},
		{ 14100203, "Жезлы кастуют заклинания слева направо. Временной интервал между кастом этих заклинаний называется Интервал Каста." },
		{ 14100204, "После того как жезл заканчивает кастить все свои заклинания, у него начинается задержка. Как только задержка заканчивается, жезл может снова начать кастовать заклинания." },
		{ 14100205, "Разброс задаёт угол области атаки. Чем больше значение, тем шире конус поражения: от прямой линии при 0° до полного круга при 360°" },
		{
			14100206,
			"Определяет количество заклинаний, которые можно поместить в один блок заклинаний. Эти заклинания будут кастоваться " + Colorize("одновременно", "#7F5AFC") + ", а не по очереди."
		},
		{
			14100207,
			"При соблюдении указанного условия, Вторичные Слоты восстанавливают " + Colorize("энергию", "#E086EC") + ". Когда " + Colorize("энергия", "#E086EC") + " во Вторичных Слотах достигнет общей Стоимости " + Colorize("Маны", "") + " всех Вторичных Слотов, они будут " + Colorize("одновременно", "#7F5AFC") + " активированы."
		},
		{ 14100301, "Все бонусы к урону (от заклинаний, реликвий и проклятий) складываются в общий процент усиления перед применением к Базовому Урону." },
		{ 14100302, "Некоторые заклинания наносят урон несколько раз за 1 секунду. Для простоты, их урон отображается как урон в секунду." },
		{
			14100303,
			"Только некоторые заклинания имеют данный атрибут. На заклинания имеющие данный аттрибут, влияет увеличение " + Colorize("Радиуса Эффекта", "#FFD700") + "."
		},
		{ 14100304, "Некоторые призывающие заклинания имеют лимит призыва. Когда число призванных существ превышает данное значение, первое призванное существо будет мгновенно убито. Если же лимит призыва не указан, значит что для данного заклинания нет ограничений на количество призывов." },
		{ 14100305, "Как правило, данное значение влияет на конечную стоимость заклинания" },
		{ 14100306, "При касте заклинаний, помеченных продолжительным кастом, ты не можешь использовать другие заклинания." },
		{
			14100307,
			"Базовое значение " + Colorize("Крит. Урона", "#FE5D00") + " равняется 200%."
		},
		{
			14100308,
			"Некоторые модификаторы урона имеют приписку " + Colorize("Множитель", "#DC143C") + ", это обозначает, что этот модификатор добавляется отдельным множителем, а не суммируется в бонусный (как это делают остальные модификаторы урона)."
		},
		{ 14100309, "Пробивание позволяет заклинанию проходить сквозь врагов, не останавливаясь. Значение Пробивания показывает, через скольких врагов пройдёт заклинание перед тем, как остановится." },
		{ 14100310, "Заклинания могут занимать несколько слотов." },
		{
			14200001,
			"Попади по врагу для " + Colorize("зарядки", "#E086EC")
		},
		{
			14200002,
			"Стой для " + Colorize("зарядки", "#E086EC")
		},
		{ 14200003, "Нормальный урон" },
		{ 14200004, "Критический урон" }
	};

	public static readonly IReadOnlyDictionary<int, string> Potion = new Dictionary<int, string>
	{
		{ 3000001, "Змеиная Кровь" },
		{ 3000002, "Зелье Щита" },
		{ 3000003, "Святая Вода" },
		{ 3000004, "Зелье Перековки" },
		{ 3000005, "Зелье Иллюзий" },
		{ 3000006, "Зелье Пробуждения" },
		{ 3000007, "Зелье Обновления" },
		{ 3000008, "Зелье-Отмычка" },
		{ 3000009, "Зелье Мидаса" },
		{ 3000010, "Зелье Скидки" },
		{ 3000011, "Зелье Левитации" },
		{ 3000012, "Зелье Невидимости" },
		{ 3000013, "Зелье Неуязвимости" },
		{ 3000014, "Зелье Окаменения" },
		{ 3000015, "Зелье Ловкости" },
		{ 3000016, "Зелье Размера" },
		{ 3000017, "Кристальное Зелье" },
		{ 3000018, "Нестабильное Красное Зелье" },
		{ 3000019, "Нестабильное Синее Зелье" },
		{ 3000020, "Зелье Очищения" },
		{ 3000021, "Зелье Обогащения" },
		{ 3000022, "Слёзы Богини" },
		{ 3000023, "Зелье Реликвии" },
		{ 3000024, "Зелье Переброса" },
		{ 3000025, "Жертвенное Зелье" },
		{ 3000026, "Зелье Слесаря" },
		{ 3000027, "Чистое Касторовое Масло" },
		{ 3000028, "Зелье Дублирования" },
		{ 3000029, "Зелье Магической Силы" },
		{ 3000030, "Зелье Сокровищ" },
		{ 3000031, "Экстренное Зелье" },
		{ 3000032, "Зелье Конверсии" },
		{ 3000033, "Зелье Крита" },
		{ 3000034, "Зелье Хаоса" },
		{ 3000035, "Ультимативное Зелье" },
		{
			3100001,
			"Востанавливает случайное количество " + Colorize("ОЗ", "") + " от int1 до int2"
		},
		{
			3100002,
			"Генерирует столько " + Colorize("Щитов", "#C500FE") + ", сколько сейчас потеряно " + Colorize("ОЗ", "") + " (Но не больше int1)"
		},
		{ 3100003, "Снимает случайное проклятие" },
		{ 3100004, "Перековывает все заклинания в инвентаре" },
		{ 3100005, "Замедляет время на float1 сек." },
		{
			3100006,
			"Временно увеличивает Реген. " + Colorize("Маны", "") + " для ваших жезлов на int1% в течении float1 сек."
		},
		{ 3100007, "Обновляет покупаемые предметы и доступные двери во всех комнатах" },
		{ 3100008, "Открывает абсолютно все запертые объекты в текущей комнате (сундуки, проклятые сундуки, сундуки с шипами и боковые двери)" },
		{ 3100009, "Превращает всех врагов в комнате, не являющихся боссами, в монеты" },
		{ 3100010, "Применяет скидку ко всем покупаемым предметам в текущей комнате" },
		{ 3100011, "Ты левитируешь! Длится до входа в следующую комнату" },
		{ 3100012, "Даёт невидимость на float1 сек.\\Атаки не раскрывают тебя" },
		{ 3100013, "Даёт неуязвимость на float1 сек." },
		{ 3100014, "Окаменяет тебя и даёт иммунитет к любому урону на float1 сек.\\Движение заканчивает окаменение преждевременно" },
		{ 3100015, "Навсегда увеличивает Скорость Передвижения на +int1%" },
		{ 3100016, "Навсегда увеличивает или уменьшает тебя" },
		{
			3100017,
			"Навсегда увеличивает Реген. " + Colorize("Маны", "") + " на +int1"
		},
		{
			3100018,
			"Навсегда изменяет Макс. " + Colorize("ОЗ", "") + " на int1 или +int2"
		},
		{
			3100019,
			"Навсегда изменяет Макс. " + Colorize("Маны", "") + " на int1 или +int2"
		},
		{
			3100020,
			"Снимает все проклятия\\Удаляет все " + Colorize("Щиты", "#C500FE") + " и " + Colorize("Временные Щиты", "#9D9D9B") + ", и устанавливает текущие " + Colorize("ОЗ", "") + " на 1"
		},
		{ 3100021, "Даёт монеты, равные float1% от имеющихся" },
		{ 3100022, "Снимает все проклятия, если на тебе ровно int1 уникальных проклятий" },
		{ 3100023, "Улучшает одну из твоих реликвий. Если ни одна реликвия не может быть улучшена, даёт одну обычную реликвию" },
		{ 3100024, "Позволяет перековать одну выбранную реликвию" },
		{
			3100025,
			"Забирает у тебя int1% текущих " + Colorize("ОЗ", "") + " давая соответствующее количество монет"
		},
		{ 3100026, "Удваивает текущее количество ключей, либо добавляет int1 если нет ни одного" },
		{ 3100027, "Даёт иммунитет к яду и слизи в текущей комнате\\Накладывает яд и замедляет врагов позади тебя в течении float1 сек." },
		{ 3100028, "Дублирует все лечилки, щиты, монеты, монетные кучки и ключи в текущей комнате" },
		{ 3100029, "Навсегда увеличивает весь наносимый игроком урон на int1%" },
		{ 3100030, "Даёт случайный сундук сокровищ" },
		{
			3100031,
			"Генерирует столько " + Colorize("Временных Щитов", "#9D9D9B") + ", сколько сейчас потеряно " + Colorize("ОЗ", "")
		},
		{
			3100032,
			"Забирает int1% текущих " + Colorize("ОЗ", "") + " давая соответствующее количество " + Colorize("Щитов", "#C500FE")
		},
		{
			3100033,
			"Навсегда увеличивает " + Colorize("Крит. Шанс", "#FE5D00") + " на int1%"
		},
		{ 3100034, "Даёт 1-4 случайных проклятия и 1-2 случайные реликвии" },
		{
			3100035,
			"Уменьшает текущие " + Colorize("ОЗ", "") + " до 1, конвертируя int1% потерянных " + Colorize("ОЗ", "") + " в Макс. " + Colorize("ОЗ", "")
		}
	};

	public static readonly IReadOnlyDictionary<int, string> Curse = new Dictionary<int, string>
	{
		{ 2000001, "Просроченная Награда" },
		{ 2000002, "Туманные Врата" },
		{ 2000003, "Улучшенные Ловушки" },
		{ 2000004, "Кровожадные Приспешники" },
		{ 2000005, "Мстительные Духи" },
		{ 2000006, "Суета" },
		{ 2000007, "Нестабильный Телепортит" },
		{ 2000008, "Необратимый Ущерб" },
		{ 2000009, "Оглушение" },
		{ 2000010, "Фальшивые Алмазы" },
		{ 2000011, "Мышечная Атрофия" },
		{ 2000012, "Робкость" },
		{ 2000013, "Изжога" },
		{ 2000014, "Слабость" },
		{ 2000015, "Медлительность" },
		{ 2000016, "Терновые Врата" },
		{ 2000017, "Сложные Замки" },
		{ 2000018, "Дырявый Кошелёк" },
		{ 2000019, "Дикое Размножение" },
		{ 2000020, "Проржавевшие Монеты" },
		{ 2000021, "Нарушенный Центр Тяжести" },
		{ 2000022, "Куриная Слепота" },
		{ 2000023, "Спешка" },
		{ 2000024, "Подавление Магии" },
		{ 2000025, "Неэффективные Заклятия" },
		{ 2000026, "Шаткое Равновесие" },
		{ 2000027, "Кощунство" },
		{ 2000028, "Неистовая Кровь" },
		{ 2000029, "Растерянность" },
		{ 2000030, "Неудача" },
		{ 2000031, "Роковая Судьба" },
		{ 2000032, "Афазия" },
		{ 2000033, "Дезориентация" },
		{ 2000034, "Кандалы" },
		{ 2000035, "Уменьшенный Рюкзак" },
		{ 2000036, "Аллергия на Зелья" },
		{ 2000037, "Бомбическая Погоня" },
		{ 2000038, "Утрата" },
		{ 2000039, "Истощение" },
		{ 2000040, "Сделка с Дьяволом" },
		{ 2000041, "Старинные Часы" },
		{ 2000042, "Утечка Маны" },
		{ 2000043, "Косоглазие" },
		{ 2000044, "Ленивый Магазин" },
		{ 2000045, "Близорукость" },
		{ 2000046, "Неряшливость" },
		{ 2000047, "Безжалостная Улитка" },
		{ 2000048, "Старая Рана" },
		{ 2000049, "Обратная Тяга" },
		{ 2000050, "Уязвимость" },
		{ 2000051, "Сжатие" },
		{ 2000052, "Ненависть к Богачам" },
		{ 2000053, "Обратные Заклинания" },
		{ 2000054, "Трудности" },
		{ 2000055, "Нейродегенерация" },
		{ 2000056, "Нулевое Трение" },
		{ 2000057, "Скользящее Отклонение" },
		{ 2000058, "Воришка" },
		{ 2000059, "Сундук-Мимик" },
		{ 2000060, "Блеф" },
		{ 2000061, "Забыл Ключ Дома" },
		{ 2000999, "Конец Всего" },
		{ 2100001, "Ресурсы исчезают если не подобрать их в течении float1 сек." },
		{ 2100002, "Невозможно рассмотреть куда ведут двери" },
		{ 2100003, "Ловушки наносят на +int1% больше урона по тебе и твоим призванным существам" },
		{ 2100004, "Скорость передвижения врагов увеличена на int1%" },
		{ 2100005, "Когда враги погибают, они имеют int1% шанс превратиться в духов, которые будут гоняться за тобой в течении float1 сек." },
		{
			2100006,
			"При получении урона по " + Colorize("ОЗ", "") + ", ты теряешь несколько монет (int1)"
		},
		{
			2100007,
			"При получении урона по " + Colorize("ОЗ", "") + ", ты телепортируешься в случайную позицию"
		},
		{
			2100008,
			"При получении урона по " + Colorize("ОЗ", "") + ", есть int1% шанс одновременно потерять столько же Макс. " + Colorize("ОЗ", "")
		},
		{
			2100009,
			"Невозможно атаковать в течении float1 сек. после получения урона по " + Colorize("ОЗ", "")
		},
		{ 2100010, "Все алмазы становятся монетами" },
		{ 2100011, "Уменьшает Скорость Передвижения на -int1%" },
		{ 2100012, "Невозможно кастовать заклинания в течении float1 сек. при входе в комнату" },
		{ 2100013, "Уменьшает скорость полёта снарядов заклинаний на int1%" },
		{ 2100014, "Уменьшает весь наносимый игроком урон на int1%" },
		{ 2100015, "Увеличивает интервал и задержку каста жезлов на int1%" },
		{ 2100016, "Ты получаешь несколько урона (int1) при входе в комнату" },
		{ 2100017, "Все запертые объекты теперь требуют 2 ключа для открытия" },
		{ 2100018, "Ты теряешь несколько монет (int1) при входе в комнату" },
		{ 2100019, "Есть int1% шанс появления двойного количества врагов, кроме боссов" },
		{ 2100020, "Есть int1% шанс получения int2 урона при подборе монет или алмазов" },
		{ 2100021, "Заклинания теперь притягивают врагов, а не отталкивают" },
		{ 2100022, "Твоё поле зрения ограничено" },
		{
			2100023,
			"Реген. " + Colorize("Маны", "") + " уменьшен на int1%"
		},
		{
			2100024,
			"Макс. " + Colorize("Маны", "") + " уменьшен на int1%"
		},
		{
			2100025,
			"Стоимость " + Colorize("Маны", "") + " ×int1%"
		},
		{ 2100026, "Отдача +int1%" },
		{ 2100027, "Количество реликвий на выбор -int1" },
		{
			2100028,
			"Реген. " + Colorize("ОЗ", "") + " врагов +int1"
		},
		{
			2100029,
			"Отключает возможность видеть " + Colorize("ОЗ", "") + ", " + Colorize("Ману", "") + " и ресурсы"
		},
		{ 2100030, "Проклятие, которое меняется с каждой комнатой" },
		{ 2100031, "Проклятие, которое меняется с каждой комнатой" },
		{ 2100032, "Текст становится неразборчивым" },
		{ 2100033, "Инверсивное передвижение" },
		{ 2100034, "К тебе прикован шар на цепи" },
		{ 2100035, "Слоты инвентаря -int1" },
		{ 2100036, "Наносит int1 урона каждый раз, когда ты используешь зелье" },
		{ 2100037, "Возле тебя периодически появляется бомба" },
		{ 2100038, "Удаляет случайную реликвию\\После срабатывания, данное проклятие очищается" },
		{
			2100039,
			"Макс. " + Colorize("ОЗ", "") + " -int1"
		},
		{
			2100040,
			"При завершении комнат с получением урона по " + Colorize("ОЗ", "") + " — Макс. " + Colorize("ОЗ", "") + " уменьшается на int1\\При завершении комнат без получения урона по " + Colorize("ОЗ", "") + " — Макс. " + Colorize("ОЗ", "") + " увеличивается на int2"
		},
		{ 2100041, "Периодически отматывает тебя туда, где ты был float1 сек. назад" },
		{
			2100042,
			"При входе в комнату, все жезлы имеют 0 " + Colorize("Маны", "")
		},
		{
			2100043,
			"Весь " + Colorize("Крит. Шанс", "#FE5D00") + " int1%"
		},
		{ 2100044, "Количество предметов в магазине -int1" },
		{ 2100045, "Разброс +int1" },
		{ 2100046, "Лимит призываемых существ в int1 раза меньше (дробная часть округляется вверх)" },
		{ 2100047, "Медленная и бессмертная улитка постоянно следует за тобой" },
		{ 2100048, "У этого проклятия нет эффекта, но его очищение наносит int1 урона" },
		{ 2100049, "Отдача заклинаний инверсирована" },
		{ 2100050, "Увеличивает весь получаемый игроком урон на +int1%" },
		{
			2100051,
			"Уменьшает " + Colorize("Радиус Эффекта", "#FFD700") + " заклинаний и реликвий на int1%"
		},
		{ 2100052, "За каждые несколько имеющихся монет (int1), увеличивает весь получаемый игроком урон на +int2% (вплоть до float1%)" },
		{ 2100053, "Заклинания выпускаются в обратном направлении" },
		{ 2100054, "Уменьшает получаемый врагами урон на int1%" },
		{ 2100055, "Каст замедляет тебя гораздо сильнее" },
		{ 2100056, "Теперь ты постоянно движешься с небольшой скоростью без возможности полностью остановиться" },
		{ 2100057, "Теперь можно стрелять только по четырём диагональным направлениям" },
		{ 2100058, "Когда на земле появляются предметы, может появиться хитрый воришка, который попытается украсть их" },
		{ 2100059, "Сундуки имеют шанс показать свою пасть!" },
		{
			2100060,
			"При полных " + Colorize("ОЗ", "") + " увеличивает весь наносимый игроком урон на +int1%\\При неполных " + Colorize("ОЗ", "") + " уменьшает весь наносимый игроком урон на int2%"
		},
		{ 2100061, "Ты потеряешь все ключи\\После срабатывания, данное проклятие очищается" },
		{
			2100999,
			"Если ты видишь данное проклятие, значит, ты активировал все проклятия\\Макс. " + Colorize("ОЗ", "") + " всех врагов +int1%"
		}
	};

	public static readonly IReadOnlyDictionary<int, string> Relic = new Dictionary<int, string>
	{
		{ 4000001, "Наплечники Титана" },
		{ 4000002, "Ботинки Рейнджера" },
		{ 4000003, "Кулон Лесного Духа" },
		{ 4000004, "Талисман Концентрации" },
		{ 4000005, "Копирка" },
		{ 4000006, "Кровожадный Взгляд" },
		{ 4000007, "Шкатулка Душ" },
		{ 4000008, "Душекостный Доспех" },
		{ 4000009, "Электро-Корона" },
		{ 4000010, "Хвост Костяного Демона" },
		{ 4000011, "Ботинки Рыцаря" },
		{ 4000012, "Дух-Хранитель" },
		{ 4000013, "Крылья Эльфа" },
		{ 4000014, "Перчатка Старателя" },
		{ 4000015, "Жилетка Старателя" },
		{ 4000016, "Душекостные Наплечники" },
		{ 4000017, "Наплечники Энта" },
		{ 4000018, "Золотая Чаша, Золотая" },
		{ 4000019, "Роба Энта" },
		{ 4000020, "Маска Жнеца" },
		{ 4000021, "Багровый Браслет" },
		{ 4000022, "Шляпа Мерлина" },
		{ 4000023, "Роба Мерлина" },
		{ 4000024, "Счастливые Серьги" },
		{ 4000025, "Борода Мерлина" },
		{ 4000026, "Целебный Пояс" },
		{ 4000027, "Бесконечный Эликсир" },
		{ 4000028, "Безделушка Продавца" },
		{ 4000029, "Ботинки Мерлина" },
		{ 4000030, "Венок Энта" },
		{ 4000031, "Нагрудник Рыцаря" },
		{ 4000032, "Застывшая Капля" },
		{ 4000033, "Душекостная Корона" },
		{ 4000034, "Маска Ведьмака" },
		{ 4000035, "Кубик D6" },
		{ 4000036, "Уши Эльфа" },
		{ 4000037, "Пыльное Сокровище" },
		{ 4000038, "Роба Фокусника" },
		{ 4000039, "Четырёхлистный Клевер" },
		{ 4000040, "Кирка Старателя" },
		{ 4000041, "Бур" },
		{ 4000042, "Накидка Разбойника" },
		{ 4000043, "Песочные Часы" },
		{ 4000044, "Тлеющее Сердце" },
		{ 4000045, "Маска Демона" },
		{ 4000046, "Семя Жадности" },
		{ 4000047, "Талисман Охотника" },
		{ 4000048, "Звериные Клыки" },
		{ 4000049, "Пронзатель Небес" },
		{ 4000050, "Линза для Жезлов" },
		{ 4000051, "Шлем Рыцаря" },
		{ 4000052, "Клинок Ярости" },
		{ 4000053, "Лупа" },
		{ 4000054, "Дикие Тентакли" },
		{ 4000055, "Лысина Сайтамы" },
		{ 4000056, "Серебрянный Ключ" },
		{ 4000057, "Яростный Глаз" },
		{ 4000058, "Пристальное Наблюдение" },
		{ 4000059, "Кровавый Ключ" },
		{ 4000060, "Перчатка Конечности" },
		{ 4000061, "Шляпа Исследователя" },
		{ 4000062, "Энергетическая Печать" },
		{ 4000063, "Чёрная Метка" },
		{ 4000064, "Серебрянный Компас" },
		{ 4000065, "Сундук-Матрёшка" },
		{ 4000066, "Ключ Перезапуска" },
		{ 4000067, "Ящик Пандоры" },
		{ 4000068, "Ветренное Ухо" },
		{ 4000069, "Разноцветный Плащ" },
		{ 4000070, "Печать Цзянши" },
		{ 4000071, "Невидимые Крылья" },
		{ 4000072, "Шевелюра Супер Сайяна" },
		{ 4000073, "Хладагент" },
		{ 4000901, "Счастливое Ухо Зайца" },
		{ 4000902, "Кубик D8" },
		{ 4000931, "Духовное Зеркало" },
		{ 4000932, "Плащ Мечника" },
		{ 4000933, "Би Ань" },
		{ 4000934, "Жнец" },
		{ 4000935, "Истинная Форма" },
		{ 4000999, "Мистический Артефакт" },
		{
			4100001,
			"Макс. " + Colorize("ОЗ", "") + " +int1\\Размер Персонажа ×int2%\\Отдача int3%"
		},
		{ 4100002, "Скорость Передвижения +int1%\\Даёт иммунитет к замедляющим эффектам (кроме замедления, вызванного кастом заклинаний)" },
		{
			4100003,
			"Медленно восстанавливает твои " + Colorize("ОЗ", "") + " до int1 когда их меньше int1"
		},
		{ 4100004, "Постепенно уменьшает задержку каста, интервал каста, и разброс на int1% когда стоишь на месте" },
		{ 4100005, "При касте заклинания, есть int1% шанс выпустить копию в случайном направлении" },
		{
			4100006,
			"При убийстве врага, есть int1% шанс восстановить int2 " + Colorize("ОЗ", "")
		},
		{ 4100007, "При убийстве врага, есть int1% шанс призвать следующего за врагами духа и наносящего int2&DMG урона" },
		{ 4100008, "При убийстве врага, есть int1% шанс создать костяной щит, летающий вокруг тебя" },
		{
			4100009,
			"При получении урона, наносит всем врагам урон, равный int1&DMG + float1% Макс. " + Colorize("ОЗ", "") + " всех врагов (float2% для боссов)"
		},
		{
			4100010,
			"При убийстве врага, создаёт обычную Волшебную Пулю, которая следует за тобой. Она наносит урон равный int1% Макс. " + Colorize("ОЗ", "") + " убитого врага"
		},
		{ 4100011, "Даёт иммунитет к напольным шипам, и лужам яда и слизи" },
		{ 4100012, "Призывает несколько духов (int1) которые могут прервать заклинания врагов" },
		{ 4100013, "Позволяют тебе левитировать" },
		{ 4100014, "При убийстве врага, есть int1% шанс появления монетки" },
		{
			4100015,
			"При подборе монет, ты восстанавливаешь " + Colorize("ОЗ", "")
		},
		{
			4100016,
			"Даёт int1 " + Colorize("Щитов", "#C500FE") + "\\Даёт int3 " + Colorize("Щит", "#C500FE") + " за каждые int2 убийства врагов"
		},
		{
			4100017,
			"Даёт несколько " + Colorize("Щитов", "#C500FE") + " (int1) при входе в комнату"
		},
		{ 4100018, "Наполняет воздух ароматом монет. Каждый раз при входе в следующую комнату, даёт дополнительные монеты в виде int1% от имеющихся (но не больше int2)" },
		{
			4100019,
			"Восстанавливает int1 " + Colorize("ОЗ", "") + " при входе в комнату"
		},
		{ 4100020, "float1% шанс мгновенно убить любого врага, кроме боссов" },
		{ 4100021, "Уменьшает Скорость Передвижения до int1%\\Увеличивает Скорость Передвижения до int2% если не получать урон в течении float1 сек." },
		{
			4100022,
			"Макс. " + Colorize("Маны", "") + " +int1"
		},
		{
			4100023,
			"Реген. " + Colorize("Маны", "") + " +int1/s"
		},
		{ 4100024, "Количество реликвий на выбор +int1" },
		{ 4100025, "Лимит призванных существ ×int1. Этот эффект распространяется только на те существа, что призываются непосредственно самим игроком" },
		{
			4100026,
			"Каждое использование зелья, увеличивает Макс. " + Colorize("ОЗ", "") + " на int1 и Макс. " + Colorize("Маны", "") + " на int2"
		},
		{ 4100027, "При использовании зелья есть int1% шанс получить ещё одно случайное зелье" },
		{ 4100028, "Специальная комната будет всегда появляться при входе в магазин или комнату обработки" },
		{
			4100029,
			"Восстанавливает int1 " + Colorize("Маны", "") + " при убийстве врагов"
		},
		{
			4100030,
			"Даёт int1 " + Colorize("Временных Щитов", "#9D9D9B") + " при входе в комнату"
		},
		{ 4100031, "Уменьшает весь получаемый игроком урон на int1%" },
		{
			4100032,
			"Замедляет большинство снарядов врагов в " + Colorize("Радиусе Эффекта", "#FFD700") + " float1&range метров"
		},
		{
			4100033,
			"Даёт int2 " + Colorize("Временный Щит", "#9D9D9B") + " при убийстве int1 врагов"
		},
		{ 4100034, "За каждое имеющееся уникальное проклятие, наносимый игроком урон увеличивается на int1%" },
		{ 4100035, "У тебя есть несколько перебросов (int1), при получении реликвии" },
		{ 4100036, "Каст заклинаний больше не замедляет тебя" },
		{ 4100037, "Улучшает одну из твоих реликвий. Если ни одна реликвия не может быть улучшена, даёт одну обычную реликвию" },
		{
			4100038,
			"Ты можешь управлять своим жезлом на расстоянии вплоть до float1 метров\\" + Colorize("Радиус Эффектов", "#FFD700") + " заклинаний: int1%"
		},
		{ 4100039, "Даёт int1% шанс уклониться от атаки" },
		{ 4100040, "Увеличивает наносимый игроком урон на int2% за каждые несколько монет (int1)" },
		{ 4100041, "Слоты заклинаний у жезлов +int1" },
		{ 4100042, "Даёт невидимость если не атаковать в течении float1 сек.\\Атака делает тебя снова видимым" },
		{
			4100043,
			"При смерти восстанавливают твои " + Colorize("ОЗ", "") + " до int1%\\Исчезают после использования"
		},
		{
			4100044,
			"Наносит int1&DMG урона в секунду всем врагам в " + Colorize("Радиусе Эффекта", "#FFD700") + " float1&range метров"
		},
		{
			4100045,
			"Увеличивает весь " + Colorize("Крит. Шанс", "#FE5D00") + " на +int1%"
		},
		{
			4100046,
			"Поглощает всё последующее лечение\\После поглощения int1 лечения, вырастает и увеличивает твой Макс. " + Colorize("ОЗ", "") + " на int2"
		},
		{ 4100047, "Увеличивает дальность зрения" },
		{ 4100048, "Увеличивает весь наносимый игроком урон на int1%" },
		{ 4100049, "Заклинания могут проходить сквозь стены" },
		{ 4100050, "Отталкивание врагов заклинаниями +int1%" },
		{ 4100051, "Уменьшает неразборчивый урон получаемый игроком до float1%" },
		{
			4100052,
			"Увеличивает " + Colorize("Крит. Урон", "#FE5D00") + " с 200% до int1%"
		},
		{
			4100053,
			"Увеличивает " + Colorize("Радиус Эффектов", "#FFD700") + " заклинаний и реликвий на +int1%"
		},
		{ 4100054, "Скорость Передвижения +int1%" },
		{ 4100055, "Увеличивает весь наносимый игроком урон на +int1%\\Увеличивает весь получаемый игроком урон на +int2%" },
		{ 4100056, "Даёт доступ ко всем сундукам и дверям, заблокированным на ключ" },
		{
			4100057,
			"За каждые int1 отсутствующих " + Colorize("ОЗ", "") + ", увеличивает весь наносимый игроком урон на float1%"
		},
		{
			4100058,
			"Показывает полоску " + Colorize("ОЗ", "") + " у всех существ\\На втором уровне будет показывать численное значение"
		},
		{ 4100059, "После убийства босса, будет всегда появляться комната с Алыми Реликвиями" },
		{ 4100060, "Перчатка время от времени убивает половину врагов в комнате не являющихся боссами" },
		{ 4100061, "Обычные уровни имеют на один выбор двери больше" },
		{
			4100062,
			"Увеличивает эффективность " + Colorize("зарядки", "#E086EC") + " Вторичных Слотов на всех жезлах на +int1%"
		},
		{ 4100063, "Один случайный товар в магазине теперь бесплатный" },
		{ 4100064, "Каждая комната с врагами будет гарантированно иметь сундук или алтарь" },
		{ 4100065, "При открытии сундука, есть int1% шанс создать ещё один" },
		{ 4100066, "Перековывает все жезлы, заклинания, реликвии, зелья и проклятия\\Возвращает в начало текущей главы, после чего, эта реликвия исчезает" },
		{ 4100067, "При входе в комнату, первые несколько слотов заклинаний в инвентаре (int1) будут перекованы" },
		{ 4100068, "При получении урона, твоя Скорость Передвижения мгновенно увеличится на ×int1% и ты станешь неуязвимым\\Длится в течении float1 сек." },
		{ 4100069, "На выпущенные заклинания добавляется случайный элементальный эффект" },
		{ 4100070, "При каждом входе в следующую комнату, есть int1% шанс очистить случайное проклятие" },
		{ 4100071, "При получении урона ты получишь полёт, а твоя Скорость Передвижения увеличится на +int1%\\Эффект длится до входа в следующую комнату" },
		{
			4100072,
			"Увеличивает весь наносимый игроком урон на +int2% когда " + Colorize("ОЗ", "") + " меньше int1%"
		},
		{ 4100073, "Уменьшает Время Восстановления навыка на int1%" },
		{ 4100901, "Количество заклинаний на выбор +int1" },
		{ 4100902, "У тебя есть несколько перебросов (int1), при получении заклинания" },
		{ 4100931, "Постоянный полёт\\Лимит Жезлов +int1\\Все жезлы всегда будут иметь Дух Жезла+" },
		{
			4100932,
			"\\Время Восстановления: float1&CD сек.\\Стоимость " + Colorize("Маны", "") + " Меча-Светозара ×int1%\\Рывок делает бесплатный каст из текущего выбранного жезла (но только если Макс. " + Colorize("Маны", "") + " жезла хватает на каст)\\Во время рывка ты неуязвим"
		},
		{ 4100933, "\\Время Восстановления: float1&CD сек.\\Возврат всех летающих мечей Би Ань наносит урон врагам на их пути" },
		{ 4100934, "Количество стаков отравления накладываемых заклинаниями ×float1\\Заклинания находящиеся в инвентаре будут автоматически синтезироваться при входе в комнату (если они могут быть синтезированы)" },
		{
			4100935,
			"\\Время Восстановления: float2&CD сек.\\При приземлении наносит урон равный int1% Макс. " + Colorize("ОЗ", "") + " цели (int2% для боссов) в " + Colorize("Радиусе Эффекта", "#FFD700") + " float1&range метра\\Даёт неуязвимость на небольшое время после приземления\\Если Жопный Удар убивает врага, Время Восстановления сбрасывается"
		},
		{
			4100999,
			"Поздравляем! Ты получил ультимативный артефакт! Увеличивает Макс. " + Colorize("ОЗ", "") + " на int1!"
		}
	};

	public static readonly IReadOnlyDictionary<int, string> Wand = new Dictionary<int, string>
	{
		{ 5000001, "Жезл из Светодрева" },
		{ 5000011, "Повреждённый Жезл из Светодрева" },
		{ 5000012, "Повреждённый Жезл из Светодрева" },
		{ 5000013, "Повреждённый Жезл из Светодрева" },
		{ 5000014, "Повреждённый Жезл из Светодрева" },
		{ 5000021, "Мистический Посох" },
		{ 5000031, "Колдовской Посох" },
		{ 5000041, "Жезл Скорострела" },
		{ 5000042, "Жезл Скорострела" },
		{ 5000043, "Жезл Скорострела" },
		{ 5000044, "Жезл Скорострела" },
		{ 5000051, "Эфирный Жезл" },
		{ 5000061, "Прямой Меч" },
		{ 5000071, "Неизвестный" },
		{ 5000081, "Серп Жнеца" },
		{ 5000091, "Лук" },
		{ 5000101, "Набор Жезлов" },
		{ 5000111, "Набор Жезлов" },
		{ 5000201, "Sprint Guide Flag" },
		{ 5000202, "Explosive Guide Flag" },
		{ 5000203, "Laser Guide Flag" },
		{ 5000204, "Magic Guide Flag" },
		{ 5000205, "Thunder Guide Flag" },
		{ 5000206, "Blue Snake Guide Flag" },
		{ 5000207, "Ice Stone Guide Flag" },
		{ 5000208, "Butterfly guide flag" },
		{ 5000209, "Tentacle guide flag" },
		{ 5000210, "Rainbow Guide Flag" },
		{ 5000301, "Заграждение Утренней Звезды" },
		{ 5000302, "Лишённый Источника" },
		{ 5000303, "Безупречный" },
		{ 5000304, "Жезл Фокуса" },
		{ 5000305, "Калейдоскоп" },
		{ 5001001, "Трость Древня" },
		{ 5001002, "Игрушечный Клинок" },
		{ 5001003, "Объятия Микромира" },
		{ 5001004, "Непоколебимая Воля" },
		{ 5001005, "Легковесный Жезл" },
		{ 5001006, "Гармонический Резонанс" },
		{ 5001007, "Источник Слияния" },
		{ 5001008, "Деревянная Палка" },
		{ 5001009, "Камертон" },
		{ 5001010, "Гримуар Новичка" },
		{ 5001011, "Направляющая Притча" },
		{ 5001012, "Старый Жезл" },
		{ 5001013, "777" },
		{ 5001014, "Стазис Времени" },
		{ 5001015, "Сверхновый Жезл" },
		{ 5001016, "Хватка Старейшины" },
		{ 5001017, "Безумный Заклинатель" },
		{ 5001018, "Вязкий Клык" },
		{ 5001019, "Ядовитый Укус" },
		{ 5001020, "Дуга Правосудия" },
		{ 5001021, "Триколор" },
		{ 5001022, "Непокорная Натура" },
		{ 5001023, "Шаманский Кинжал" },
		{ 5001024, "Разбитый Скипетр" },
		{ 5001025, "Ржавый Бластер" },
		{ 5001026, "Резервуар Энергии" },
		{ 5001027, "Трезубец" },
		{ 5001028, "Душепоглощающая Сфера" },
		{ 5001029, "Наследие Предков" },
		{ 5001030, "Клятва Рыцаря" },
		{ 5001031, "Фальшивый Кристалл" },
		{ 5001032, "Зонтик" },
		{ 5001033, "Золотой Скипетр" },
		{ 5002001, "Сияющий Букет" },
		{ 5002002, "Свисток из Раковины" },
		{ 5002003, "Жертвенный Кинжал" },
		{ 5002004, "Энергичный Жезл" },
		{ 5002005, "Свидетель Подвигов" },
		{ 5002006, "Посох Скорострела" },
		{ 5002007, "Знамя Легиона" },
		{ 5002008, "Расширяющийся Контейнер" },
		{ 5002009, "Двойная Флейта" },
		{ 5002010, "Лютня Трёх Аккордов" },
		{ 5002011, "Присяга Колдуна" },
		{ 5002012, "Беспокойное Сердце" },
		{ 5002013, "Метла Ведьмочки" },
		{ 5002014, "Бескрайний Том" },
		{ 5002015, "Тяжёлый Удар" },
		{ 5002016, "Сигил Воздержания" },
		{ 5002017, "Двуглавый Жезл" },
		{ 5002018, "Быстрый Заклимеч" },
		{ 5002019, "Книга Спокойствия" },
		{ 5002020, "Удобный Жезл" },
		{ 5002021, "Пульсирующий Жезл" },
		{ 5002022, "Портативная Библиотека" },
		{ 5002023, "Жезл Сближения" },
		{ 5002024, "Мешочек Чародея" },
		{ 5002025, "Посох Течения" },
		{ 5002026, "Межзвёздный Бродяга" },
		{ 5002027, "Праздничный Жезл" },
		{ 5002028, "Бабулина Игла" },
		{ 5002029, "Высоковольтный Камень" },
		{ 5002030, "Волшебный Проводник" },
		{ 5002031, "Кристалл Жизни" },
		{ 5002032, "Линейка" },
		{ 5004001, "Звёздный Горн" },
		{ 5004002, "Змеиный Вальс" },
		{ 5004003, "Астероид" },
		{ 5004004, "Заряженная Сфера" },
		{ 5004005, "Беспокойная Фея" },
		{ 5004006, "Клинок Разума" },
		{ 5004007, "Разносчик Чумы" },
		{ 5004008, "Спящая Тентакля" },
		{ 5004009, "Осадец" },
		{ 5004010, "Ледяное Касание" },
		{ 5004011, "Хранитель Королевства" },
		{ 5004012, "Старый Малый" },
		{ 5004013, "Жезл Архимага" },
		{ 5004014, "Оборотень" },
		{ 5004015, "Радужная Электросеть" },
		{ 5004016, "Посох Коллекционера" },
		{ 5004017, "Меч с Камнем" },
		{ 5006001, "Лишённый Наследства" },
		{ 5006002, "Лишённый Тени" },
		{ 5006003, "Лишённый Света" },
		{ 5006004, "Бесформенный" },
		{ 5006005, "Безликий" },
		{ 5006006, "Безупречный" },
		{ 5006007, "Безграничный" },
		{ 5006008, "Лишённый Источника" },
		{ 5006009, "Бессловесный" },
		{ 5006010, "Безымянный" },
		{ 5006011, "Тотем Варвара" },
		{ 5008001, "Жезл Фокуса" },
		{ 5008002, "Предзнаменование Гибели" },
		{ 5008003, "Чистейший Резонанс" },
		{ 5008004, "Осколок Времени" },
		{ 5008005, "Звёздный Дрейф" },
		{ 5008006, "Табельный Посох" },
		{ 5008007, "Калейдоскоп" },
		{ 5008008, "Благословение Изобилия" },
		{ 5100001, "" },
		{ 5100011, "" },
		{ 5100012, "" },
		{ 5100013, "" },
		{ 5100014, "" },
		{ 5100021, "" },
		{ 5100031, "" },
		{ 5100041, "" },
		{ 5100042, "" },
		{ 5100043, "" },
		{ 5100044, "" },
		{ 5100051, "" },
		{ 5100061, "" },
		{ 5100071, "" },
		{ 5100081, "" },
		{ 5100091, "" },
		{ 5100101, "" },
		{ 5100111, "" },
		{ 5100201, "" },
		{ 5100202, "" },
		{ 5100203, "" },
		{ 5100204, "" },
		{ 5100205, "" },
		{ 5100206, "" },
		{ 5100207, "" },
		{ 5100208, "" },
		{ 5100209, "" },
		{ 5100210, "" },
		{ 5100301, "" },
		{ 5100302, "" },
		{ 5100303, "" },
		{
			5100304,
			"Пока ты держишь этот жезл в руке, его Реген. " + Colorize("Маны", "") + " ×float1% иначе ×float2%"
		},
		{ 5100305, "На заклинания, выпущенные этим жезлом, добавляется случайный элементальный эффект" },
		{ 5100401, "" },
		{ 5100402, "" },
		{ 5101001, "" },
		{ 5101002, "" },
		{
			5101003,
			"Стоимость " + Colorize("Маны", "") + " на всех жезлах ×float1%"
		},
		{ 5101004, "" },
		{ 5101005, "" },
		{ 5101006, "" },
		{
			5101007,
			"Реген. " + Colorize("Маны", "") + " на всех жезлах +float1/s"
		},
		{ 5101008, "" },
		{ 5101009, "" },
		{
			5101010,
			"Стоимость " + Colorize("Маны", "") + " Заклинаний Призыва ×float1%"
		},
		{ 5101011, "" },
		{ 5101012, "" },
		{ 5101013, "" },
		{ 5101014, "" },
		{ 5101015, "" },
		{ 5101016, "" },
		{ 5101017, "" },
		{ 5101018, "" },
		{ 5101019, "" },
		{
			5101020,
			"Случайный " + Colorize("Радиус Эффекта", "#FFD700") + " орбиты"
		},
		{ 5101021, "На заклинания, выпущенные этим жезлом, добавляется случайный элементальный эффект" },
		{ 5101022, "Заклинания выпускаются в обратном направлении" },
		{ 5101023, "" },
		{ 5101024, "" },
		{ 5101025, "" },
		{ 5101026, "" },
		{ 5101027, "" },
		{ 5101028, "" },
		{ 5101029, "" },
		{ 5101030, "" },
		{ 5101031, "Враги, убитые этим жезлом, имеют float1% шанс уронить Магический Кристалл" },
		{ 5101032, "Этот жезл имеет длину float1m и может отражать большинство вражеских снарядов" },
		{ 5101033, "Враги, убитые этим жезлом, имеют float1% шанс уронить Монетку" },
		{ 5102001, "На заклинания, выпущенные этим жезлом, добавляется случайный элементальный эффект" },
		{ 5102002, "Пока ты держишь этот жезл в руке, твоя Скорость Передвижения увеличена на +float1%" },
		{ 5102003, "Уменьшает Неразборчивый Урон от этого жезла по игроку до float1%" },
		{
			5102004,
			"Добавляет заклинаниям +float1% Урона, если их Стоимость " + Colorize("Маны", "") + " меньше int1 (работает на каждое заклинание в жезле по отдельности)"
		},
		{
			5102005,
			"Увеличивает " + Colorize("Радиус Эффектов", "#FFD700") + " заклинаний на всех жезлах на +float1%"
		},
		{
			5102006,
			"Пока ты держишь этот жезл в руке, его Реген. " + Colorize("Маны", "") + " ×float1% иначе ×float2%"
		},
		{ 5102007, "" },
		{
			5102008,
			"Макс. " + Colorize("Маны", "") + " на всех жезлах ×float1%"
		},
		{ 5102009, "" },
		{ 5102010, "" },
		{
			5102011,
			"Реген. " + Colorize("Маны", "") + " на всех жезлах +float1/s"
		},
		{ 5102012, "Этот жезл имеет инверсивную отдачу" },
		{ 5102013, "Пока ты держишь этот жезл в руке, ты можешь левитировать" },
		{ 5102014, "" },
		{ 5102015, "" },
		{ 5102016, "" },
		{ 5102017, "" },
		{ 5102018, "Пока ты держишь этот жезл в руке, твоя Скорость Передвижения увеличена на +float1%" },
		{ 5102019, "Пока ты стоишь на месте, этот жезл не имеет отдачи" },
		{ 5102020, "" },
		{
			5102021,
			"Заклинания имеют шанс float1% мгновенно восстановить всю " + Colorize("Ману", "") + " жезла при касте\\Также есть float2% шанс проигнорировать задержку"
		},
		{ 5102022, "" },
		{ 5102023, "" },
		{ 5102024, "" },
		{ 5102025, "" },
		{ 5102026, "" },
		{ 5102027, "" },
		{ 5102028, "" },
		{ 5102029, "" },
		{ 5102030, "" },
		{
			5102031,
			"Пока ты держишь этот жезл в руке, призванные существа в " + Colorize("Радиусе Эффекта", "#FFD700") + " float2m будут лечиться на int1 " + Colorize("ОЗ", "") + " в сек."
		},
		{ 5102032, "Этот посох имеет длину float1m" },
		{ 5104001, "" },
		{ 5104002, "" },
		{ 5104003, "" },
		{
			5104004,
			"Когда на других жезлах не хватает " + Colorize("Маны", "") + ", они могут использовать " + Colorize("Ману", "") + " этого жезла"
		},
		{
			5104005,
			"Пока ты держишь этот жезл в руке, его Реген. " + Colorize("Маны", "") + " ×float1% иначе ×float2%"
		},
		{ 5104006, "" },
		{ 5104007, "" },
		{ 5104008, "" },
		{ 5104009, "" },
		{ 5104010, "" },
		{ 5104011, "" },
		{ 5104012, "" },
		{ 5104013, "" },
		{ 5104014, "" },
		{ 5104015, "" },
		{ 5104016, "" },
		{ 5104017, "Этот жезл имеет длину float1m и может отражать большинство вражеских снарядов" },
		{
			5106001,
			"Пока ты держишь этот жезл в руке, призванные существа в " + Colorize("Радиусе Эффекта", "#FFD700") + " float2m будут лечиться на float1% " + Colorize("ОЗ", "") + " в сек."
		},
		{ 5106002, "" },
		{ 5106003, "" },
		{ 5106004, "" },
		{ 5106005, "" },
		{ 5106006, "" },
		{ 5106007, "" },
		{ 5106008, "" },
		{ 5106009, "" },
		{ 5106010, "" },
		{ 5106011, "" },
		{
			5108001,
			"Пока ты держишь этот жезл в руке, его Реген. " + Colorize("Маны", "") + " ×float1% иначе ×float2%"
		},
		{ 5108002, "Уменьшает Неразборчивый Урон от этого жезла по игроку до float1%" },
		{ 5108003, "" },
		{
			5108004,
			"Реген. " + Colorize("Маны", "") + " всех жезлов +float1/s"
		},
		{ 5108005, "" },
		{ 5108006, "" },
		{ 5108007, "На заклинания, выпущенные этим жезлом, добавляется случайный элементальный эффект" },
		{
			5108008,
			"Пока ты держишь этот жезл в руке, призванные существа в " + Colorize("Радиусе Эффекта", "#FFD700") + " float2m будут лечиться на float1% " + Colorize("ОЗ", "") + " в сек."
		}
	};

	public static readonly IReadOnlyDictionary<int, string> Base = new Dictionary<int, string>
	{
		{ 1000001, "Начать Игру" },
		{ 1000002, "Настройки" },
		{ 1000003, "Титры" },
		{ 1000004, "Выход" },
		{ 1000005, "Добавить в Вишлист" },
		{ 1000006, "Сообщить об ошибке" },
		{ 1000007, "Ты уверен, что хочешь удалить сохранённые данные?" },
		{ 1000008, "Пусто" },
		{ 1000009, "Локация" },
		{ 1000010, "Кристаллов" },
		{ 1000011, "Древней Крови" },
		{ 1000012, "Время Игры" },
		{ 1000013, "ч" },
		{ 1000014, "м" },
		{ 1000015, "Пропустить начало истории?" },
		{ 1000016, "Награда за 60К предзаказов на Bilibili" },
		{ 1000017, "Награда за 100К предзаказов на Bilibili" },
		{ 1000018, "По умолчанию" },
		{ 1000019, "с" },
		{ 1000020, "Ядер Хаоса" },
		{ 1000021, "Выйти из Игры" },
		{ 1000022, "Макс. Сложность" },
		{ 1000023, "Маленький ТВ" },
		{ 1000024, "Кроссовер с блогером\nна Bilibili — 女流66" },
		{ 1000025, "Ничего" },
		{ 1000026, "Кроссовер с блогером\nна Bilibili — 老番茄" },
		{ 1000027, "Небесный Деятель" },
		{ 1000101, "Об