Decompiled source of Coeur v1.0.1

CoeurSixVikings.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using SixVikings;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("CoeurSixVikings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+647996836758923c0de9c8ad4e96c94fa372f426")]
[assembly: AssemblyProduct("CoeurSixVikings")]
[assembly: AssemblyTitle("CoeurSixVikings")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 SixVikings
{
	internal static class Langue
	{
		internal static bool Francais
		{
			get
			{
				try
				{
					return Localization.instance.GetSelectedLanguage() == "French";
				}
				catch (Exception)
				{
					return false;
				}
			}
		}

		internal static string T(string francais, string anglais)
		{
			if (!Francais)
			{
				return anglais;
			}
			return francais;
		}

		internal static string Reglage(string anglais, string francais)
		{
			return anglais + "\nFR : " + francais;
		}
	}
}
namespace CoeurSixVikings
{
	[BepInPlugin("sixvikings.coeur", "SixVikings Coeur", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private class CommandeCoeur : ConsoleCommand
		{
			public override string Name => "coeur";

			public override string Help => Langue.T("coeur : état du correctif de BlightedWorldHeart. coeur on / coeur off : l'activer ou le couper sans relancer le jeu.", "coeur: status of the BlightedWorldHeart fix. coeur on / coeur off: turn it on or off without restarting the game.");

			public override void Run(string[] args, Terminal context)
			{
				try
				{
					bool francais = Langue.Francais;
					string text = ((args.Length != 0) ? args[0].ToLowerInvariant() : "");
					if (text == "on" || text == "off")
					{
						Instance.reglageActif.Value = text == "on";
					}
					else if (text != "")
					{
						Instance.Repondre(context, francais ? ("coeur : « " + text + " » n'existe pas. Écris coeur, coeur on ou coeur off.") : ("coeur: \"" + text + "\" does not exist. Type coeur, coeur on or coeur off."));
						return;
					}
					if (pourquoiRien != null)
					{
						Instance.Repondre(context, francais ? ("SixVikings Coeur 1.0.1 NE FAIT RIEN : " + pourquoiRien + ". BlightedWorldHeart tourne sans correctif.") : ("SixVikings Coeur 1.0.1 DOES NOTHING: " + pourquoiRienAnglais + ". BlightedWorldHeart runs without the fix."));
						return;
					}
					Instance.Repondre(context, francais ? ("SixVikings Coeur 1.0.1 : " + (actif ? "actif" : "coupé") + ", " + greffesPosees + " greffe(s) posée(s) sur " + 7 + ((gestesEnErreur.Count > 0) ? (", en erreur pour : " + string.Join(", ", gestesEnErreur)) : "") + ".") : ("SixVikings Coeur 1.0.1: " + (actif ? "on" : "off") + ", " + greffesPosees + " of " + 7 + " patch(es) applied" + ((gestesEnErreur.Count > 0) ? (", errors in: " + string.Join(", ", gestesEnErreur)) : "") + "."));
					Instance.Repondre(context, EtatDesCoeurs(francais));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)Instance).Logger.LogError((object)ex);
				}
			}
		}

		public const string ModGuid = "sixvikings.coeur";

		public const string ModNom = "SixVikings Coeur";

		public const string ModVersion = "1.0.1";

		public const string GuidDuCoeur = "wubarrk.blightedworldheart";

		private const int GreffesAttendues = 7;

		private const string MessageEveil = "SixVikingsCoeur_Eveil";

		internal static Plugin Instance;

		private static bool actif;

		private static int greffesPosees;

		private static string pourquoiRien;

		private static string pourquoiRienAnglais;

		private static readonly HashSet<string> gestesEnErreur = new HashSet<string>();

		private ConfigEntry<bool> reglageActif;

		internal static Type TypeCoeur;

		internal static Type TypeSousBoss;

		internal static Type TypeEveil;

		internal static Type TypeReglages;

		private static FieldInfo champBiome;

		private static FieldInfo champVagueAvant;

		private static FieldInfo champSousBoss1Fait;

		private static FieldInfo champSousBoss2Fait;

		private static FieldInfo champEnnemis;

		private static FieldInfo champSousBoss1;

		private static FieldInfo champSousBoss2;

		private static FieldInfo champVue;

		private static FieldInfo champReglagesParBiome;

		private static MethodInfo methodeCouleurs;

		internal static int HashVie;

		internal static int HashVieMax;

		internal static KeyValuePair<int, int> HashSousBoss1;

		internal static KeyValuePair<int, int> HashSousBoss2;

		private static readonly int HashBiome = StringExtensionMethods.GetStableHashCode("sixvikings_coeur_biome");

		private static readonly int HashRaid = StringExtensionMethods.GetStableHashCode("sixvikings_coeur_raid");

		internal static readonly int HashVague = StringExtensionMethods.GetStableHashCode("sixvikings_coeur_vague");

		internal static readonly int HashSousBoss = StringExtensionMethods.GetStableHashCode("sixvikings_coeur_sousboss");

		private static readonly int HashTaille = StringExtensionMethods.GetStableHashCode("sixvikings_coeur_taille");

		private static readonly int HashVieDuSousBoss = StringExtensionMethods.GetStableHashCode("sixvikings_coeur_vie");

		private static readonly List<KeyValuePair<Vector3, float>> eveils = new List<KeyValuePair<Vector3, float>>();

		private static ZRoutedRpc reseauEcoute;

		private static readonly Dictionary<int, float> prochainControle = new Dictionary<int, float>();

		private void Awake()
		{
			Instance = this;
			reglageActif = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Actif", true, Langue.Reglage("true: the fix works. false: BlightedWorldHeart behaves as without it (to compare). Can also be changed in game: coeur on, coeur off.", "true : le correctif agit. false : BlightedWorldHeart se comporte comme sans lui (pour comparer). Se change aussi en jeu : coeur on, coeur off."));
			actif = reglageActif.Value;
			reglageActif.SettingChanged += delegate
			{
				actif = reglageActif.Value;
			};
			Traduire();
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new CommandeCoeur());
			PluginInfo value;
			string text = (Chainloader.PluginInfos.TryGetValue("wubarrk.blightedworldheart", out value) ? value.Metadata.Version.ToString() : null);
			if (!Regles.VersionConnue(text))
			{
				pourquoiRien = "BlightedWorldHeart " + (text ?? "absent") + " : ce correctif ne connaît que la 1.1.2";
				pourquoiRienAnglais = "BlightedWorldHeart " + (text ?? "missing") + ": this fix only knows version 1.1.2";
				((BaseUnityPlugin)this).Logger.LogError((object)(pourquoiRien + ". Aucune greffe posée, il ne fait rien."));
				return;
			}
			string text2 = Trouver();
			if (text2 != null)
			{
				pourquoiRien = "introuvable dans BlightedWorldHeart " + text + " : " + text2;
				pourquoiRienAnglais = "not found in BlightedWorldHeart " + text + ": " + text2;
				((BaseUnityPlugin)this).Logger.LogError((object)(pourquoiRien + ". Aucune greffe posée, il ne fait rien."));
			}
			else
			{
				Greffer();
			}
		}

		private void Update()
		{
			if (greffesPosees == 0 || ZRoutedRpc.instance == null || ZRoutedRpc.instance == reseauEcoute)
			{
				return;
			}
			reseauEcoute = ZRoutedRpc.instance;
			try
			{
				reseauEcoute.Register<Vector3>("SixVikingsCoeur_Eveil", (Action<long, Vector3>)RecevoirUnEveil);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Annonce des éveils : écoute posée sur cette session réseau.");
			}
			catch (Exception e)
			{
				Erreur("écouter l'annonce des éveils", e);
			}
		}

		private static string Trouver()
		{
			List<string> list = new List<string>();
			TypeCoeur = Classe("BlightedHeart.BlightedWorldHeartAI", list);
			TypeSousBoss = Classe("BlightedHeart.BlightedSubBoss", list);
			TypeEveil = Classe("BlightedHeart.BlightedHeartSpawning", list);
			TypeReglages = Classe("BlightedHeart.BlightedConfigManager", list);
			if (list.Count > 0)
			{
				return string.Join(", ", list);
			}
			champBiome = Champ(TypeCoeur, "CurrentBiome", typeof(Biome), list);
			champVagueAvant = Champ(TypeCoeur, "_lastWaveTime", typeof(float), list);
			champSousBoss1Fait = Champ(TypeCoeur, "_subBoss1Spawned", typeof(bool), list);
			champSousBoss2Fait = Champ(TypeCoeur, "_subBoss2Spawned", typeof(bool), list);
			champEnnemis = Champ(TypeCoeur, "m_spawnedEnemies", typeof(List<GameObject>), list);
			champSousBoss1 = Champ(TypeCoeur, "m_subBoss1", typeof(Character), list);
			champSousBoss2 = Champ(TypeCoeur, "m_subBoss2", typeof(Character), list);
			champVue = Champ(TypeCoeur, "m_nview", typeof(ZNetView), list);
			champReglagesParBiome = AccessTools.Field(TypeReglages, "BiomeConfigs");
			if (champReglagesParBiome == null || !typeof(IDictionary).IsAssignableFrom(champReglagesParBiome.FieldType))
			{
				list.Add("BlightedConfigManager.BiomeConfigs");
			}
			methodeCouleurs = AccessTools.Method(TypeCoeur, "ApplyBiomeVisuals", new Type[1] { typeof(Biome) }, (Type[])null);
			if (methodeCouleurs == null)
			{
				list.Add("BlightedWorldHeartAI.ApplyBiomeVisuals");
			}
			object obj = Statique(TypeCoeur, "ZDO_Health", typeof(int), list);
			object obj2 = Statique(TypeCoeur, "ZDO_MaxHealth", typeof(int), list);
			object obj3 = Statique(TypeCoeur, "ZDO_SubBoss1", typeof(string), list);
			object obj4 = Statique(TypeCoeur, "ZDO_SubBoss2", typeof(string), list);
			if (list.Count > 0)
			{
				return string.Join(", ", list);
			}
			HashVie = (int)obj;
			HashVieMax = (int)obj2;
			HashSousBoss1 = ZDO.GetHashZDOID((string)obj3);
			HashSousBoss2 = ZDO.GetHashZDOID((string)obj4);
			return null;
		}

		private static object Statique(Type type, string nom, Type attendu, List<string> manques)
		{
			FieldInfo fieldInfo = AccessTools.Field(type, nom);
			object? obj = ((fieldInfo != null && fieldInfo.IsStatic && fieldInfo.FieldType == attendu) ? fieldInfo.GetValue(null) : null);
			if (obj == null)
			{
				manques.Add(type.Name + "." + nom);
			}
			return obj;
		}

		private static Type Classe(string nom, List<string> manques)
		{
			Type type = AccessTools.TypeByName(nom);
			if (type == null)
			{
				manques.Add(nom);
			}
			return type;
		}

		private static FieldInfo Champ(Type type, string nom, Type attendu, List<string> manques)
		{
			FieldInfo fieldInfo = AccessTools.Field(type, nom);
			if (fieldInfo == null || fieldInfo.FieldType != attendu)
			{
				manques.Add(type.Name + "." + nom);
			}
			return fieldInfo;
		}

		private void Greffer()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			Harmony harmony = new Harmony("sixvikings.coeur");
			greffesPosees = 0;
			Poser(harmony, AccessTools.Method(TypeCoeur, "Initialize", new Type[1] { typeof(Biome) }, (Type[])null), null, "ApresEveil");
			Poser(harmony, AccessTools.Method(TypeCoeur, "Update", (Type[])null, (Type[])null), "AvantChaqueImage");
			Poser(harmony, AccessTools.Method(TypeCoeur, "SpawnWave", (Type[])null, (Type[])null), null, "ApresVague");
			Poser(harmony, AccessTools.Method(TypeCoeur, "SpawnSubBoss", new Type[2]
			{
				typeof(int),
				typeof(float)
			}, (Type[])null), null, "ApresSousBoss");
			Poser(harmony, AccessTools.Method(TypeEveil, "UseItemPrefix", (Type[])null, (Type[])null), "AvantOffrande");
			Poser(harmony, AccessTools.Method(TypeEveil, "SpawnBlightedHeart", (Type[])null, (Type[])null), null, "ApresDebutDEveil");
			Poser(harmony, AccessTools.Method(typeof(Character), "Awake", (Type[])null, (Type[])null), null, "ApresNaissance");
			if (greffesPosees == 7)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Greffes : " + greffesPosees + " posée(s) sur " + 7 + ". Actif : " + (actif ? "oui" : "non") + "."));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Greffes : " + greffesPosees + " posée(s) sur " + 7 + " : le correctif est incomplet."));
			}
		}

		private void Poser(Harmony harmony, MethodInfo cible, string prefix = null, string postfix = null)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (cible == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Greffe NON posée : " + (prefix ?? postfix) + ", méthode visée introuvable."));
				return;
			}
			try
			{
				harmony.Patch((MethodBase)cible, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				greffesPosees++;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Greffe posée : " + cible.DeclaringType.Name + "." + cible.Name));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Greffe NON posée sur " + cible.DeclaringType.Name + "." + cible.Name + " : " + ex.Message));
			}
		}

		private static void ApresEveil(MonoBehaviour __instance, Biome biome)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected I4, but got Unknown
			if (!actif)
			{
				return;
			}
			try
			{
				ZNetView val = Vue(__instance);
				if (!((Object)(object)val == (Object)null) && val.IsValid() && val.IsOwner())
				{
					val.GetZDO().Set(HashBiome, (int)biome, false);
					Raid(val);
				}
			}
			catch (Exception e)
			{
				Erreur("noter le biome du Cœur", e);
			}
		}

		private static void AvantChaqueImage(MonoBehaviour __instance)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected I4, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			if (!actif)
			{
				return;
			}
			try
			{
				ZNetView val = Vue(__instance);
				if ((Object)(object)val == (Object)null || !val.IsValid())
				{
					return;
				}
				ZDO zDO = val.GetZDO();
				if (Regles.DoitReprendre(actif, (int)(Biome)champBiome.GetValue(__instance)))
				{
					Reprendre(__instance, zDO);
				}
				if (!val.IsOwner())
				{
					return;
				}
				int instanceID = ((Object)__instance).GetInstanceID();
				if (!prochainControle.TryGetValue(instanceID, out var value) || !(Time.time < value))
				{
					prochainControle[instanceID] = Time.time + 1f;
					if (!(bool)champSousBoss1Fait.GetValue(__instance) && zDO.GetZDOID(HashSousBoss1) != ZDOID.None)
					{
						champSousBoss1Fait.SetValue(__instance, true);
					}
					if (!(bool)champSousBoss2Fait.GetValue(__instance) && zDO.GetZDOID(HashSousBoss2) != ZDOID.None)
					{
						champSousBoss2Fait.SetValue(__instance, true);
					}
					RetrouverLaVague(__instance, Raid(val));
				}
			}
			catch (Exception e)
			{
				Erreur("reprendre le Cœur", e);
			}
		}

		private static void Reprendre(MonoBehaviour coeur, ZDO zdo)
		{
			//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_009d: Unknown result type (might be due to invalid IL or missing references)
			int num = zdo.GetInt(HashBiome, 0);
			int ici = ((WorldGenerator.instance != null) ? ((int)WorldGenerator.instance.GetBiome(((Component)coeur).transform.position)) : 0);
			int num2 = Regles.BiomeARendre(0, num, ici);
			if (num2 != 0)
			{
				champBiome.SetValue(coeur, (object)(Biome)num2);
				champVagueAvant.SetValue(coeur, Time.time);
				if (!GUIManager.IsHeadless())
				{
					methodeCouleurs.Invoke(coeur, new object[1] { (object)(Biome)num2 });
				}
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Cœur repris : biome " + ((object)(Biome)num2/*cast due to .constrained prefix*/).ToString() + ((num != 0) ? " (noté à son éveil)" : " (lu à l'endroit : éveillé avant ce correctif)") + ", vie " + Nombre(zdo.GetFloat(HashVie, 0f)) + " sur " + Nombre(zdo.GetFloat(HashVieMax, 0f)) + "."));
			}
		}

		private static int Raid(ZNetView vue)
		{
			ZDO zDO = vue.GetZDO();
			int num = zDO.GetInt(HashRaid, 0);
			if (num != 0 || !vue.IsOwner())
			{
				return num;
			}
			int num2 = Regles.NumeroDeRaid(num, Random.Range(int.MinValue, int.MaxValue));
			zDO.Set(HashRaid, num2, false);
			return num2;
		}

		private static void RetrouverLaVague(MonoBehaviour coeur, int raid)
		{
			if (raid == 0 || !(champEnnemis.GetValue(coeur) is List<GameObject> list))
			{
				return;
			}
			int num = 0;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsDead() && !list.Contains(((Component)allCharacter).gameObject))
				{
					ZNetView component = ((Component)allCharacter).GetComponent<ZNetView>();
					if (!((Object)(object)component == (Object)null) && component.IsValid() && component.GetZDO().GetInt(HashVague, 0) == raid)
					{
						list.Add(((Component)allCharacter).gameObject);
						num++;
					}
				}
			}
			if (num > 0)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Cœur pris en charge : " + num + " ennemi(s) de la vague en cours retrouvé(s)."));
			}
		}

		private static void ApresVague(MonoBehaviour __instance)
		{
			if (!actif)
			{
				return;
			}
			try
			{
				ZNetView val = Vue(__instance);
				if ((Object)(object)val == (Object)null || !val.IsValid() || !(champEnnemis.GetValue(__instance) is List<GameObject> list))
				{
					return;
				}
				int num = Raid(val);
				if (num == 0)
				{
					return;
				}
				foreach (GameObject item in list)
				{
					ZNetView val2 = Proprietaire(item);
					if ((Object)(object)val2 != (Object)null && val2.GetZDO().GetInt(HashVague, 0) != num)
					{
						val2.GetZDO().Set(HashVague, num, false);
					}
				}
			}
			catch (Exception e)
			{
				Erreur("marquer une vague", e);
			}
		}

		private static void ApresSousBoss(MonoBehaviour __instance, int index)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!actif)
			{
				return;
			}
			try
			{
				ZNetView val = Vue(__instance);
				object? value = ((index == 1) ? champSousBoss1 : champSousBoss2).GetValue(__instance);
				Character val2 = (Character)((value is Character) ? value : null);
				if (!((Object)(object)val == (Object)null) && val.IsValid() && !((Object)(object)val2 == (Object)null))
				{
					int num = Raid(val);
					ZNetView val3 = Proprietaire(((Component)val2).gameObject);
					if (num != 0 && !((Object)(object)val3 == (Object)null))
					{
						val3.GetZDO().Set(HashSousBoss, num, false);
						val3.GetZDO().Set(HashTaille, ((Component)val2).transform.localScale);
						val3.GetZDO().Set(HashVieDuSousBoss, val2.GetMaxHealth());
					}
				}
			}
			catch (Exception e)
			{
				Erreur("marquer un sous-boss", e);
			}
		}

		private static ZNetView Proprietaire(GameObject objet)
		{
			ZNetView val = (((Object)(object)objet != (Object)null) ? objet.GetComponent<ZNetView>() : null);
			if (!((Object)(object)val != (Object)null) || !val.IsValid() || !val.IsOwner())
			{
				return null;
			}
			return val;
		}

		private static void ApresNaissance(Character __instance)
		{
			if (!actif)
			{
				return;
			}
			try
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid())
				{
					ZDO zDO = component.GetZDO();
					if (zDO.GetInt(HashSousBoss, 0) != 0)
					{
						RefaireLeSousBoss(__instance, zDO);
					}
					else if (zDO.GetInt(HashVague, 0) != 0)
					{
						SansButin(((Component)__instance).gameObject);
					}
				}
			}
			catch (Exception e)
			{
				Erreur("refaire un sous-boss ou un ennemi de vague", e);
			}
		}

		private static void RefaireLeSousBoss(Character sousBoss, ZDO zdo)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((Component)sousBoss).GetComponent(TypeSousBoss) == (Object)null)
			{
				((Component)sousBoss).gameObject.AddComponent(TypeSousBoss);
			}
			SansButin(((Component)sousBoss).gameObject);
			Vector3 vec = zdo.GetVec3(HashTaille, Vector3.zero);
			if (vec != Vector3.zero)
			{
				((Component)sousBoss).transform.localScale = vec;
			}
			float num = zdo.GetFloat(HashVieDuSousBoss, 0f);
			ZNetView component = ((Component)sousBoss).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsOwner())
			{
				return;
			}
			Regles.Vie vie = Regles.VieDuSousBoss(num, sousBoss.GetMaxHealth(), sousBoss.GetMaxHealthBase() * (float)sousBoss.GetLevel(), sousBoss.GetHealth());
			if (vie != Regles.Vie.RienAFaire)
			{
				string text = ((Object)sousBoss).name.Replace("(Clone)", "");
				if (vie == Regles.Vie.Rendre)
				{
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Sous-boss " + text + " : vie rendue, " + Nombre(sousBoss.GetMaxHealth()) + " -> " + Nombre(num) + "."));
					sousBoss.SetMaxHealth(num);
					sousBoss.SetHealth(num);
				}
				else
				{
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Sous-boss " + text + " : vie NON rendue (vie " + Nombre(sousBoss.GetHealth()) + " sur " + Nombre(sousBoss.GetMaxHealth()) + ", notée " + Nombre(num) + ", de base " + Nombre(sousBoss.GetMaxHealthBase() * (float)sousBoss.GetLevel()) + ") : blessé, ou maximum posé par un autre mod."));
				}
			}
		}

		private static void SansButin(GameObject personnage)
		{
			CharacterDrop[] componentsInChildren = personnage.GetComponentsInChildren<CharacterDrop>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren[i]);
			}
			Component[] componentsInChildren2 = personnage.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren2)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string name = ((object)val).GetType().Name;
					if (name == "DropOnDestroy" || name == "SpawnOnDestroy")
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
		}

		private static bool AvantOffrande(OfferingBowl __0, Humanoid __1, ItemData __2, ref bool __3, ref bool __result)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!actif || (Object)(object)__0 == (Object)null || (Object)(object)__0.m_bossPrefab == (Object)null)
			{
				return true;
			}
			try
			{
				if (!EstUneOffrandeDuCoeur(__0, __2))
				{
					return true;
				}
				bool flag = CoeurPres(((Component)__0).transform.position, 60f);
				double num = DepuisLeDernierEveil(((Component)__0).transform.position);
				if (!Regles.AutelOccupe(flag, num))
				{
					return true;
				}
				if (__1 != null)
				{
					((Character)__1).Message((MessageType)2, flag ? "$sixvikings_coeur_deja_la" : "$sixvikings_coeur_eveil_en_cours", 0, (Sprite)null, false);
				}
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Offrande refusée à l'autel : " + (flag ? "un Cœur est déjà là" : ("éveil lancé il y a " + Nombre((float)num) + " s")) + "."));
				__3 = true;
				__result = false;
				return false;
			}
			catch (Exception e)
			{
				Erreur("contrôler une offrande", e);
				return true;
			}
		}

		private static void ApresDebutDEveil(OfferingBowl bowl)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!actif || (Object)(object)bowl == (Object)null)
			{
				return;
			}
			try
			{
				Vector3 position = ((Component)bowl).transform.position;
				if (reseauEcoute != null && reseauEcoute == ZRoutedRpc.instance)
				{
					reseauEcoute.InvokeRoutedRPC(0L, "SixVikingsCoeur_Eveil", new object[1] { position });
				}
				else
				{
					NoterUnEveil(position);
				}
			}
			catch (Exception e)
			{
				Erreur("annoncer un éveil", e);
			}
		}

		private static void RecevoirUnEveil(long expediteur, Vector3 autel)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!actif)
			{
				return;
			}
			try
			{
				NoterUnEveil(autel);
				bool flag = expediteur == ZNet.GetUID();
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Éveil annoncé à l'autel en " + Texte(autel) + " par " + (flag ? "ce jeu" : "un autre jeu") + "."));
			}
			catch (Exception e)
			{
				Erreur("noter un éveil annoncé", e);
			}
		}

		private static void NoterUnEveil(Vector3 autel)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			eveils.RemoveAll((KeyValuePair<Vector3, float> e) => Time.time - e.Value >= 15f);
			eveils.Add(new KeyValuePair<Vector3, float>(autel, Time.time));
		}

		private static double DepuisLeDernierEveil(Vector3 autel)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			double num = double.PositiveInfinity;
			foreach (KeyValuePair<Vector3, float> eveil in eveils)
			{
				if (Regles.MemeAutel(eveil.Key.x, eveil.Key.z, autel.x, autel.z))
				{
					num = Math.Min(num, Time.time - eveil.Value);
				}
			}
			return num;
		}

		private static bool EstUneOffrandeDuCoeur(OfferingBowl autel, ItemData objet)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			if (objet == null || (Object)(object)objet.m_dropPrefab == (Object)null)
			{
				return false;
			}
			if (!(champReglagesParBiome.GetValue(null) is IDictionary dictionary))
			{
				return false;
			}
			Biome val = Heightmap.FindBiome(((Component)autel).transform.position);
			if (!dictionary.Contains(val))
			{
				return false;
			}
			object obj = dictionary[val];
			if (AccessTools.Field(obj.GetType(), "AltarSummonItem")?.GetValue(obj) is ConfigEntry<string> val2)
			{
				return ((Object)objet.m_dropPrefab).name == val2.Value;
			}
			return false;
		}

		internal static bool CoeurPres(Vector3 ou, float rayon)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Object[] array = Object.FindObjectsByType(TypeCoeur, (FindObjectsSortMode)0);
			foreach (Object obj in array)
			{
				MonoBehaviour val = (MonoBehaviour)(object)((obj is MonoBehaviour) ? obj : null);
				if (val != null && (Object)(object)val != (Object)null && Vector3.Distance(((Component)val).transform.position, ou) <= rayon)
				{
					return true;
				}
			}
			return false;
		}

		internal static ZNetView Vue(MonoBehaviour coeur)
		{
			object? value = champVue.GetValue(coeur);
			return (ZNetView)((value is ZNetView) ? value : null);
		}

		private static string Nombre(float valeur)
		{
			return valeur.ToString("F0", CultureInfo.InvariantCulture);
		}

		private static void Erreur(string geste, Exception e)
		{
			if (gestesEnErreur.Add(geste))
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogError((object)("Erreur en voulant " + geste + " ; BlightedWorldHeart continue sans le correctif pour ce geste : " + e));
				}
			}
		}

		internal static string EtatDesCoeurs(bool francais = true)
		{
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			if (TypeCoeur == null)
			{
				if (!francais)
				{
					return "BlightedWorldHeart not found";
				}
				return "BlightedWorldHeart non trouvé";
			}
			List<string> list = new List<string>();
			Object[] array = Object.FindObjectsByType(TypeCoeur, (FindObjectsSortMode)0);
			foreach (Object obj in array)
			{
				MonoBehaviour val = (MonoBehaviour)(object)((obj is MonoBehaviour) ? obj : null);
				if (val != null && !((Object)(object)val == (Object)null))
				{
					ZNetView val2 = Vue(val);
					ZDO val3 = (((Object)(object)val2 != (Object)null && val2.IsValid()) ? val2.GetZDO() : null);
					int num = ((champEnnemis.GetValue(val) is List<GameObject> list2) ? list2.FindAll((GameObject e) => (Object)(object)e != (Object)null).Count : 0);
					bool flag = val3 != null && val3.GetInt(HashRaid, 0) != 0;
					bool flag2 = (Object)(object)val2 != (Object)null && val2.IsValid() && val2.IsOwner();
					string text = (((bool)champSousBoss1Fait.GetValue(val)) ? "1" : "-") + (((bool)champSousBoss2Fait.GetValue(val)) ? "2" : "-");
					if (francais)
					{
						list.Add("Cœur en " + Texte(((Component)val).transform.position) + " : biome " + champBiome.GetValue(val)?.ToString() + ((val3 != null) ? (" (noté : " + ((object)(Biome)val3.GetInt(HashBiome, 0)/*cast due to .constrained prefix*/).ToString() + ", raid " + (flag ? "numéroté" : "SANS numéro") + ")") : "") + ", vie " + Nombre((val3 != null) ? val3.GetFloat(HashVie, 0f) : 0f) + ", " + (flag2 ? "chez moi" : "chez un autre") + ", sous-boss appelés " + text + ", ennemis suivis " + num);
					}
					else
					{
						list.Add("Heart at " + Texte(((Component)val).transform.position) + ": biome " + champBiome.GetValue(val)?.ToString() + ((val3 != null) ? (" (stored: " + ((object)(Biome)val3.GetInt(HashBiome, 0)/*cast due to .constrained prefix*/).ToString() + ", raid " + (flag ? "numbered" : "WITHOUT number") + ")") : "") + ", health " + Nombre((val3 != null) ? val3.GetFloat(HashVie, 0f) : 0f) + ", " + (flag2 ? "owned by me" : "owned by another") + ", sub-bosses summoned " + text + ", tracked enemies " + num);
					}
				}
			}
			if (list.Count == 0)
			{
				if (!francais)
				{
					return "no Heart in range";
				}
				return "aucun Cœur à portée";
			}
			return string.Join(" | ", list);
		}

		internal static string Texte(Vector3 v)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			return "(" + Nombre(v.x) + ", " + Nombre(v.y) + ", " + Nombre(v.z) + ")";
		}

		internal void Repondre(Terminal terminal, string texte)
		{
			if ((Object)(object)terminal != (Object)null)
			{
				terminal.AddString(texte);
			}
			((BaseUnityPlugin)this).Logger.LogMessage((object)texte);
		}

		private void Traduire()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "French";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "sixvikings_coeur_deja_la", "Un Cœur maudit bat déjà près de cet autel" },
				{ "sixvikings_coeur_eveil_en_cours", "Le Cœur maudit s'éveille déjà" }
			});
			text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "sixvikings_coeur_deja_la", "A Blighted Heart already beats near this altar" },
				{ "sixvikings_coeur_eveil_en_cours", "The Blighted Heart is already awakening" }
			});
		}
	}
	public static class Regles
	{
		public enum Vie
		{
			RienAFaire,
			Rendre,
			NonRendue
		}

		public const string VersionVisee = "1.1.2";

		public const string CleBiome = "sixvikings_coeur_biome";

		public const string CleRaid = "sixvikings_coeur_raid";

		public const string CleVague = "sixvikings_coeur_vague";

		public const string CleSousBoss = "sixvikings_coeur_sousboss";

		public const string CleTaille = "sixvikings_coeur_taille";

		public const string CleVie = "sixvikings_coeur_vie";

		public const float RayonDeLAutel = 60f;

		public const float SecondesEntreDeuxEveils = 15f;

		public const float RayonDUnAutel = 3f;

		public static bool VersionConnue(string version)
		{
			return version == "1.1.2";
		}

		public static bool DoitReprendre(bool actif, int biomeCourant)
		{
			if (actif)
			{
				return biomeCourant == 0;
			}
			return false;
		}

		public static int NumeroDeRaid(int existant, int tirage)
		{
			if (existant != 0)
			{
				return existant;
			}
			if (tirage == 0)
			{
				return 1;
			}
			return tirage;
		}

		public static bool MemeAutel(float ax, float az, float bx, float bz)
		{
			float num = ax - bx;
			float num2 = az - bz;
			return num * num + num2 * num2 < 9f;
		}

		public static Vie VieDuSousBoss(float notee, float maxActuelle, float maxDeBase, float vie)
		{
			if (notee <= 0f || maxActuelle == notee)
			{
				return Vie.RienAFaire;
			}
			if (Math.Abs(maxActuelle - maxDeBase) < 0.01f && vie >= Math.Min(maxActuelle, notee))
			{
				return Vie.Rendre;
			}
			return Vie.NonRendue;
		}

		public static int BiomeARendre(int courant, int note, int ici)
		{
			if (courant != 0)
			{
				return courant;
			}
			if (note == 0)
			{
				return ici;
			}
			return note;
		}

		public static bool AutelOccupe(bool coeurProche, double secondesDepuisLeDernierEveil)
		{
			if (!coeurProche)
			{
				return secondesDepuisLeDernierEveil < 15.0;
			}
			return true;
		}
	}
}