Decompiled source of GeneticArtifact v4.5.3

GeneticsArtifact.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using On.RoR2;
using R2API;
using R2API.ScriptableObjects;
using R2API.Utils;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

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

public class ArtifactOfGenetics
{
	public static ArtifactDef artifactDef;

	public static ArtifactCode artifactCode;

	public static ArtifactCompoundDef geneArtifactCompoundDef;

	internal static void Init()
	{
		//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)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		LanguageAPI.Add("GENETIC_ARTIFACT_NAME_TOKEN", "Artifact of Genetics");
		LanguageAPI.Add("GENETIC_ARTIFACT_DESCRIPTION_TOKEN", "Monsters will spawn with adjusted stats. Adjustments are determined by a genetic algorithm.");
		artifactDef = ScriptableObject.CreateInstance<ArtifactDef>();
		artifactDef.nameToken = "GENETIC_ARTIFACT_NAME_TOKEN";
		artifactDef.descriptionToken = "GENETIC_ARTIFACT_DESCRIPTION_TOKEN";
		artifactDef.smallIconSelectedSprite = GeneticsArtifactPlugin.geneticAssetBundle.LoadAsset<Sprite>("Assets/Genetics/Selected.png");
		artifactDef.smallIconDeselectedSprite = GeneticsArtifactPlugin.geneticAssetBundle.LoadAsset<Sprite>("Assets/Genetics/Unselected.png");
		artifactDef.pickupModelPrefab = GeneticsArtifactPlugin.geneticAssetBundle.LoadAsset<GameObject>("Assets/Genetics/PickupGene.prefab");
		ContentAddition.AddArtifactDef(artifactDef);
		geneArtifactCompoundDef = ScriptableObject.CreateInstance<ArtifactCompoundDef>();
		geneArtifactCompoundDef.modelPrefab = GeneticsArtifactPlugin.geneticAssetBundle.LoadAsset<GameObject>("Assets/Genetics/CompoundGene.prefab");
		geneArtifactCompoundDef.value = 15;
		ArtifactCodeAPI.AddCompound(geneArtifactCompoundDef);
		artifactCode = ScriptableObject.CreateInstance<ArtifactCode>();
		artifactCode.topRow = new Vector3Int(3, 5, 3);
		artifactCode.middleRow = new Vector3Int(1, geneArtifactCompoundDef.value, 1);
		artifactCode.bottomRow = new Vector3Int(3, 5, 3);
		ArtifactCodeAPI.AddCode(artifactDef, artifactCode);
	}
}
public class ConfigManager
{
	public static ConfigEntry<int> timeLimit;

	public static ConfigEntry<int> deathLimit;

	public static ConfigEntry<int> governorType;

	public static ConfigEntry<float> geneVarianceLimit;

	public static ConfigEntry<float> geneCap;

	public static ConfigEntry<float> geneFloor;

	public static ConfigEntry<float> geneProductLimit;

	public static ConfigEntry<bool> maintainIfDisabled;

	public static ConfigEntry<bool> enableGeneLimitOverrides;

	public static ConfigEntry<string> geneLimitOverrides;

	public static void Init(ConfigFile configFile)
	{
		//IL_000b: 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_002c: Expected O, but got Unknown
		//IL_002c: Expected O, but got Unknown
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Expected O, but got Unknown
		//IL_0062: Expected O, but got Unknown
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Expected O, but got Unknown
		//IL_0096: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Expected O, but got Unknown
		//IL_00cf: Expected O, but got Unknown
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Expected O, but got Unknown
		//IL_010c: Expected O, but got Unknown
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Expected O, but got Unknown
		//IL_0149: Expected O, but got Unknown
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Expected O, but got Unknown
		//IL_0186: Expected O, but got Unknown
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Expected O, but got Unknown
		//IL_01c3: Expected O, but got Unknown
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Expected O, but got Unknown
		//IL_01fc: Expected O, but got Unknown
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Expected O, but got Unknown
		//IL_022b: Expected O, but got Unknown
		governorType = configFile.Bind<int>(new ConfigDefinition("GeneEngineDriver Variables", "Learning Governor Type"), 0, new ConfigDescription("How the algorithm decides when to learn: 0 - Default, 1 - Time Only, 2 - Death Count Only", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
		timeLimit = configFile.Bind<int>(new ConfigDefinition("GeneEngineDriver Variables", "Time Limit"), 60, new ConfigDescription("How many seconds between learnings:", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 300), Array.Empty<object>()));
		deathLimit = configFile.Bind<int>(new ConfigDefinition("GeneEngineDriver Variables", "Death Limit"), 40, new ConfigDescription("How many monster deaths between learnings:", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 100), Array.Empty<object>()));
		maintainIfDisabled = configFile.Bind<bool>(new ConfigDefinition("GeneEngineDriver Variables", "Keep Mutations While Disabled"), false, new ConfigDescription("Should the stat mods still be applied if the artifact is disabled mid-run:", (AcceptableValueBase)(object)new AcceptableValueList<bool>(new bool[2] { true, false }), Array.Empty<object>()));
		geneCap = configFile.Bind<float>(new ConfigDefinition("Mutation Variables", "Gene Value Cap"), 10f, new ConfigDescription("Maximum multiplier for any stat:", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
		geneFloor = configFile.Bind<float>(new ConfigDefinition("Mutation Variables", "Gene Value Floor"), 0.01f, new ConfigDescription("Minimum multiplier for any stat:", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
		geneProductLimit = configFile.Bind<float>(new ConfigDefinition("Mutation Variables", "Gene Product Cap"), 1.5f, new ConfigDescription("Maximum product of all stat multipliers:", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
		geneVarianceLimit = configFile.Bind<float>(new ConfigDefinition("Mutation Variables", "Gene Variation Limit"), 0.1f, new ConfigDescription("How much a monster can differ from it`s master as a percent: 0.1 is 10% (Bulwark will be 5x this)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
		enableGeneLimitOverrides = configFile.Bind<bool>(new ConfigDefinition("Mutation Override Variables", "Enable Mutation Overrides"), false, new ConfigDescription("Should the mutation overrides be applied, use with caution", (AcceptableValueBase)(object)new AcceptableValueList<bool>(new bool[2] { true, false }), Array.Empty<object>()));
		geneLimitOverrides = configFile.Bind<string>(new ConfigDefinition("Mutation Override Variables", "Gene Limit Overrides"), "MoveSpeed,0.5,2|InvalidName,0.8,NaN", new ConfigDescription("Format is as follows: GeneName1,Floor1,Cap1|GeneName2,Floor2,Cap2 where GeneName is in (MaxHealth,MoveSpeed,AttackSpeed,AttackDamage) and Floor and Cap are parseable numerics", (AcceptableValueBase)null, Array.Empty<object>()));
	}
}
public enum GovernorType
{
	Default,
	TimeOnly,
	DeathsOnly
}
public class RiskOfOptionsCompat
{
	public static void Init()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Expected O, but got Unknown
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Expected O, but got Unknown
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Expected O, but got Unknown
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Expected O, but got Unknown
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: 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_00ef: Expected O, but got Unknown
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Expected O, but got Unknown
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Expected O, but got Unknown
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Expected O, but got Unknown
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Expected O, but got Unknown
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Expected O, but got Unknown
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Expected O, but got Unknown
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Expected O, but got Unknown
		ModSettingsManager.SetModIcon(ArtifactOfGenetics.artifactDef.smallIconSelectedSprite);
		ModSettingsManager.AddOption((BaseOption)new IntSliderOption(ConfigManager.governorType, new IntSliderConfig
		{
			min = 0,
			max = 2
		}));
		ModSettingsManager.AddOption((BaseOption)new IntSliderOption(ConfigManager.timeLimit, new IntSliderConfig
		{
			min = 5,
			max = 300
		}));
		ModSettingsManager.AddOption((BaseOption)new IntSliderOption(ConfigManager.deathLimit, new IntSliderConfig
		{
			min = 10,
			max = 100
		}));
		ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(ConfigManager.maintainIfDisabled));
		ModSettingsManager.AddOption((BaseOption)new SliderOption(ConfigManager.geneCap, new SliderConfig
		{
			min = 1f,
			max = 50f,
			formatString = "{0:#0.##}x"
		}));
		ModSettingsManager.AddOption((BaseOption)new SliderOption(ConfigManager.geneFloor, new SliderConfig
		{
			min = 0.01f,
			max = 1f,
			formatString = "{0:0.##}x"
		}));
		ModSettingsManager.AddOption((BaseOption)new SliderOption(ConfigManager.geneProductLimit, new SliderConfig
		{
			min = 1f,
			max = 10f,
			formatString = "{0:#0.##}x"
		}));
		ModSettingsManager.AddOption((BaseOption)new SliderOption(ConfigManager.geneVarianceLimit, new SliderConfig
		{
			min = 0.01f,
			max = 1f,
			formatString = "{0:#0.##%}"
		}));
		ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(ConfigManager.enableGeneLimitOverrides));
		ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(ConfigManager.geneLimitOverrides));
	}
}
public class GeneEngineDriver : NetworkBehaviour
{
	public static GeneEngineDriver instance;

	public static List<MasterGeneBehaviour> masterGenes;

	public static List<MonsterGeneBehaviour> livingGenes;

	public static List<MonsterGeneBehaviour> deadGenes;

	public static float timeSinceLastLearning;

	public static Dictionary<GeneStat, (float, float)> geneLimitOverrides;

	public event EventHandler GEDPostLearningEvent;

	public static void RegisterHooks()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		Run.Start += new hook_Start(Run_Start);
		CharacterBody.Start += new hook_Start(CharacterBody_Start);
		HealthComponent.TakeDamage += new hook_TakeDamage(HealthComponent_TakeDamage);
	}

	private static void Run_Start(orig_Start orig, Run self)
	{
		orig.Invoke(self);
		if (NetworkServer.active && RunArtifactManager.instance.IsArtifactEnabled(ArtifactOfGenetics.artifactDef))
		{
			((Component)self).gameObject.AddComponent<GeneEngineDriver>();
		}
	}

	private static void CharacterBody_Start(orig_Start orig, CharacterBody self)
	{
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Invalid comparison between Unknown and I4
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		orig.Invoke(self);
		if (!NetworkServer.active || (!RunArtifactManager.instance.IsArtifactEnabled(ArtifactOfGenetics.artifactDef) && !ConfigManager.maintainIfDisabled.Value))
		{
			return;
		}
		if ((Object)(object)instance == (Object)null)
		{
			((Component)Run.instance).gameObject.AddComponent<GeneEngineDriver>();
			GeneticsArtifactPlugin.geneticLogSource.LogWarning((object)"GeneEngineDriver Emergency Activation! Wasn't ready for a body yet.");
		}
		if ((int)self.teamComponent.teamIndex == 2 && Object.op_Implicit((Object)(object)self.inventory))
		{
			if (!masterGenes.Exists((MasterGeneBehaviour x) => x.bodyIndex == self.bodyIndex))
			{
				MasterGeneBehaviour masterGeneBehaviour = new MasterGeneBehaviour();
				masterGeneBehaviour.Init();
				masterGeneBehaviour.bodyIndex = self.bodyIndex;
				masterGenes.Add(masterGeneBehaviour);
				GeneticsArtifactPlugin.geneticLogSource.LogInfo((object)("Generated a Master Template for: " + BodyCatalog.GetBodyName(self.bodyIndex)));
			}
			MonsterGeneBehaviour monsterGeneBehaviour = ((Component)self).gameObject.AddComponent<MonsterGeneBehaviour>();
			if (RunArtifactManager.instance.IsArtifactEnabled(ArtifactOfGenetics.artifactDef))
			{
				monsterGeneBehaviour.MutateFromMaster();
				monsterGeneBehaviour.characterBody.RecalculateStats();
			}
			else
			{
				monsterGeneBehaviour.CopyFromMaster();
			}
		}
	}

	private static void HealthComponent_TakeDamage(orig_TakeDamage orig, HealthComponent self, DamageInfo damageInfo)
	{
		orig.Invoke(self, damageInfo);
		if (!NetworkServer.active || !RunArtifactManager.instance.IsArtifactEnabled(ArtifactOfGenetics.artifactDef))
		{
			return;
		}
		GameObject attacker = damageInfo.attacker;
		if (attacker != null)
		{
			if (!((Object)(object)attacker != (Object)null))
			{
				return;
			}
			CharacterBody attackerBody = attacker.GetComponent<CharacterBody>();
			if (attackerBody == null || !((Object)(object)attackerBody != (Object)null))
			{
				return;
			}
			Inventory inventory = attackerBody.inventory;
			if (inventory != null && inventory.GetItemCount(GeneTokens.blockerDef) == 0)
			{
				MonsterGeneBehaviour monsterGeneBehaviour = livingGenes.Find((MonsterGeneBehaviour x) => (Object)(object)x.characterBody == (Object)(object)attackerBody);
				if ((Object)(object)monsterGeneBehaviour != (Object)null)
				{
					monsterGeneBehaviour.damageDealt += damageInfo.damage;
				}
			}
			return;
		}
		GameObject inflictor = damageInfo.inflictor;
		if (inflictor == null)
		{
			return;
		}
		if (!((Object)(object)inflictor != (Object)null))
		{
			return;
		}
		CharacterBody inflictorBody = inflictor.GetComponent<CharacterBody>();
		if (inflictorBody == null || !((Object)(object)inflictorBody != (Object)null))
		{
			return;
		}
		Inventory inventory2 = inflictorBody.inventory;
		if (inventory2 != null && inventory2.GetItemCount(GeneTokens.blockerDef) == 0)
		{
			MonsterGeneBehaviour monsterGeneBehaviour2 = livingGenes.Find((MonsterGeneBehaviour x) => (Object)(object)x.characterBody == (Object)(object)inflictorBody);
			if ((Object)(object)monsterGeneBehaviour2 != (Object)null)
			{
				monsterGeneBehaviour2.damageDealt += damageInfo.damage;
			}
		}
	}

	public void Awake()
	{
		if ((Object)(object)instance == (Object)null)
		{
			instance = this;
		}
		if (NetworkServer.active)
		{
			masterGenes = new List<MasterGeneBehaviour>();
			livingGenes = new List<MonsterGeneBehaviour>();
			deadGenes = new List<MonsterGeneBehaviour>();
			RegenerateGeneLimitOverrides();
		}
	}

	public void Update()
	{
		if (!NetworkServer.active)
		{
			return;
		}
		timeSinceLastLearning += Time.deltaTime;
		switch (ConfigManager.governorType.Value)
		{
		case 1:
			if (timeSinceLastLearning >= (float)ConfigManager.timeLimit.Value)
			{
				Learn();
			}
			break;
		case 2:
			if (deadGenes.Count >= ConfigManager.deathLimit.Value)
			{
				Learn();
			}
			break;
		default:
			if (timeSinceLastLearning >= (float)ConfigManager.timeLimit.Value || deadGenes.Count >= ConfigManager.deathLimit.Value)
			{
				Learn();
			}
			break;
		}
	}

	public void Learn()
	{
		foreach (MasterGeneBehaviour masterGene in masterGenes)
		{
			masterGene.MutateFromChildren();
		}
		deadGenes.Clear();
		timeSinceLastLearning = 0f;
		this.GEDPostLearningEvent?.Invoke(this, new EventArgs());
	}

	public void RegenerateGeneLimitOverrides()
	{
		geneLimitOverrides = new Dictionary<GeneStat, (float, float)>();
		if (!ConfigManager.enableGeneLimitOverrides.Value || string.IsNullOrEmpty(ConfigManager.geneLimitOverrides.Value))
		{
			return;
		}
		string[] array = ConfigManager.geneLimitOverrides.Value.Trim().Split(new char[1] { '|' });
		foreach (string text in array)
		{
			string[] array2 = text.Split(new char[1] { ',' });
			if (Enum.TryParse<GeneStat>(array2[0], ignoreCase: true, out var result) && float.TryParse(array2[1], out var result2) && result2 <= 1f && float.TryParse(array2[2], out var result3) && result3 >= 1f)
			{
				try
				{
					geneLimitOverrides.Add(result, (result2, result3));
					GeneticsArtifactPlugin.geneticLogSource.LogInfo((object)("Adding Valid GeneOverride: " + text));
				}
				catch
				{
					goto IL_00ce;
				}
				continue;
			}
			goto IL_00ce;
			IL_00ce:
			GeneticsArtifactPlugin.geneticLogSource.LogWarning((object)("Skipping Invalid GeneOverride: " + text));
		}
	}
}
public class GeneTokenCalc
{
	public static void RegisterHooks()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(RecalculateStatsAPI_GetStatCoefficients);
	}

	private static void RecalculateStatsAPI_GetStatCoefficients(CharacterBody sender, StatHookEventArgs args)
	{
		Inventory inventory = sender.inventory;
		if (inventory != null && inventory.GetItemCount(GeneTokens.blockerDef) == 0)
		{
			args.baseHealthAdd += GetStatValueToAdd(sender, GeneStat.MaxHealth);
			args.baseMoveSpeedAdd += GetStatValueToAdd(sender, GeneStat.MoveSpeed);
			args.baseAttackSpeedAdd += GetStatValueToAdd(sender, GeneStat.AttackSpeed);
			args.baseDamageAdd += GetStatValueToAdd(sender, GeneStat.AttackDamage);
		}
	}

	public static float GetGeneMultiplier(CharacterBody body, GeneStat statType)
	{
		float num = 0.01f;
		Inventory inventory = body.inventory;
		float num2 = 1f + (num * (float?)((inventory != null) ? new int?(inventory.GetItemCount(GeneTokens.tokenDict[statType][GeneMod.Plus1])) : null)).GetValueOrDefault();
		num = 0.01f;
		Inventory inventory2 = body.inventory;
		return num2 - (num * (float?)((inventory2 != null) ? new int?(inventory2.GetItemCount(GeneTokens.tokenDict[statType][GeneMod.Minus1])) : null)).GetValueOrDefault();
	}

	public static float GetStatValueToAdd(CharacterBody body, GeneStat statType)
	{
		float num = 0f;
		switch (statType)
		{
		case GeneStat.MaxHealth:
			num = body.baseMaxHealth + body.levelMaxHealth * body.level;
			break;
		case GeneStat.MoveSpeed:
			num = body.baseMoveSpeed + body.levelMoveSpeed * body.level;
			break;
		case GeneStat.AttackSpeed:
			num = body.baseAttackSpeed + body.levelAttackSpeed * body.level;
			break;
		case GeneStat.AttackDamage:
			num = body.baseDamage + body.levelDamage * body.level;
			break;
		}
		return num * GetGeneMultiplier(body, statType) - num;
	}

	public static Dictionary<ItemDef, int> GetTokensToAdd(Dictionary<GeneStat, float> oldValues, Dictionary<GeneStat, float> newValues)
	{
		Dictionary<ItemDef, int> dictionary = new Dictionary<ItemDef, int>();
		Dictionary<GeneStat, float> dictionary2 = new Dictionary<GeneStat, float>();
		foreach (GeneStat value in Enum.GetValues(typeof(GeneStat)))
		{
			dictionary2.Add(value, newValues[value] - oldValues[value]);
		}
		foreach (GeneStat value2 in Enum.GetValues(typeof(GeneStat)))
		{
			if (dictionary2[value2] > 0f)
			{
				dictionary.Add(GeneTokens.tokenDict[value2][GeneMod.Plus1], (int)(dictionary2[value2] * 100f));
			}
			else
			{
				dictionary.Add(GeneTokens.tokenDict[value2][GeneMod.Minus1], (int)(dictionary2[value2] * -100f));
			}
		}
		return dictionary;
	}
}
public class GeneTokens
{
	public static Dictionary<GeneStat, Dictionary<GeneMod, ItemDef>> tokenDict;

	public static ItemDef blockerDef;

	public static void Init()
	{
		LanguageAPI.Add("GENETIC_EMPTY_TOKEN", "This is better than null I guess");
		tokenDict = new Dictionary<GeneStat, Dictionary<GeneMod, ItemDef>>();
		foreach (GeneStat value in Enum.GetValues(typeof(GeneStat)))
		{
			tokenDict.Add(value, new Dictionary<GeneMod, ItemDef>());
			foreach (GeneMod value2 in Enum.GetValues(typeof(GeneMod)))
			{
				ItemDef val = ScriptableObject.CreateInstance<ItemDef>();
				((Object)val).name = "GENETOKEN_" + value.ToString().ToUpper() + "_" + value2.ToString().ToUpper();
				val.nameToken = "GENETIC_EMPTY_TOKEN";
				val.pickupToken = "GENETIC_EMPTY_TOKEN";
				val.descriptionToken = "GENETIC_EMPTY_TOKEN";
				val.loreToken = "GENETIC_EMPTY_TOKEN";
				val.pickupIconSprite = null;
				val.pickupModelPrefab = null;
				val.tags = (ItemTag[])(object)new ItemTag[2]
				{
					(ItemTag)13,
					(ItemTag)12
				};
				Reflection.SetFieldValue<ItemTier>((object)val, "deprecatedTier", (ItemTier)5);
				val.hidden = true;
				val.canRemove = false;
				ContentAddition.AddItemDef(val);
				tokenDict[value].Add(value2, val);
			}
		}
		blockerDef = ScriptableObject.CreateInstance<ItemDef>();
		((Object)blockerDef).name = "GENETOKEN_BLOCKER";
		blockerDef.nameToken = "GENETIC_EMPTY_TOKEN";
		blockerDef.pickupToken = "GENETIC_EMPTY_TOKEN";
		blockerDef.descriptionToken = "GENETIC_EMPTY_TOKEN";
		blockerDef.loreToken = "GENETIC_EMPTY_TOKEN";
		blockerDef.pickupIconSprite = null;
		blockerDef.pickupModelPrefab = null;
		blockerDef.tags = (ItemTag[])(object)new ItemTag[2]
		{
			(ItemTag)13,
			(ItemTag)12
		};
		Reflection.SetFieldValue<ItemTier>((object)blockerDef, "deprecatedTier", (ItemTier)5);
		blockerDef.hidden = true;
		blockerDef.canRemove = false;
		ContentAddition.AddItemDef(blockerDef);
	}
}
public enum GeneStat
{
	MaxHealth,
	MoveSpeed,
	AttackSpeed,
	AttackDamage
}
public enum GeneMod
{
	Plus1,
	Minus1
}
public class MasterGeneBehaviour
{
	public BodyIndex bodyIndex;

	public Dictionary<GeneStat, float> templateGenes;

	public event EventHandler MaGBPostCreationEvent;

	public event EventHandler MaGBPostMutationEvent;

	public void Init()
	{
		templateGenes = new Dictionary<GeneStat, float>();
		foreach (GeneStat value in Enum.GetValues(typeof(GeneStat)))
		{
			templateGenes.Add(value, 1f);
		}
		this.MaGBPostCreationEvent?.Invoke(this, new EventArgs());
	}

	public void MutateFromChildren()
	{
		List<MonsterGeneBehaviour> list = GeneEngineDriver.deadGenes.Where((MonsterGeneBehaviour x) => x.bodyIndex == bodyIndex && x.score > 0f).ToList();
		foreach (GeneStat value in Enum.GetValues(typeof(GeneStat)))
		{
			float num = 0f;
			float num2 = 0f;
			foreach (MonsterGeneBehaviour item in list)
			{
				num2 += item.currentGenes[value] * item.score;
				num += item.score;
			}
			if (num > 0f)
			{
				templateGenes[value] = (float)decimal.Round((decimal)(num2 / num), 2);
			}
		}
		this.MaGBPostMutationEvent?.Invoke(this, new EventArgs());
	}
}
public class MonsterGeneBehaviour : MonoBehaviour
{
	public BodyIndex bodyIndex;

	public Dictionary<GeneStat, float> currentGenes;

	public CharacterBody characterBody;

	public float timeAlive;

	public float timeEngaged;

	public float damageDealt;

	public float score;

	public event EventHandler MoGBPostMutationEvent;

	public event EventHandler MoGBPostScoringEvent;

	public void Awake()
	{
		//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)
		characterBody = ((Component)this).gameObject.GetComponent<CharacterBody>();
		bodyIndex = characterBody.bodyIndex;
		InitializeCurrentGenes();
		GeneEngineDriver.livingGenes.Add(this);
	}

	public void Update()
	{
		timeAlive += Time.deltaTime;
		if (!characterBody.outOfCombat)
		{
			timeEngaged += Time.deltaTime;
		}
	}

	public void MutateFromMaster()
	{
		CopyFromMaster();
		MutateSelf();
	}

	public void CopyFromMaster()
	{
		MasterGeneBehaviour masterGeneBehaviour = GeneEngineDriver.masterGenes.Find((MasterGeneBehaviour x) => x.bodyIndex == bodyIndex);
		AdaptToNewGenes(masterGeneBehaviour.templateGenes);
	}

	public void MutateSelf()
	{
		Dictionary<GeneStat, float> attempt = GenerateMutationAttempt();
		attempt = CorrectOvermutation(attempt);
		AdaptToNewGenes(attempt);
		this.MoGBPostMutationEvent?.Invoke(this, new EventArgs());
	}

	private Dictionary<GeneStat, float> CorrectOvermutation(Dictionary<GeneStat, float> attempt)
	{
		while (CalculateGeneProduct(attempt) > ConfigManager.geneProductLimit.Value)
		{
			attempt[attempt.Aggregate((KeyValuePair<GeneStat, float> x, KeyValuePair<GeneStat, float> y) => (!(x.Value > y.Value)) ? y : x).Key] -= 0.05f;
		}
		return attempt;
	}

	private float CalculateGeneProduct(Dictionary<GeneStat, float> testValues)
	{
		float num = 1f;
		foreach (float value in testValues.Values)
		{
			num *= value;
		}
		return num;
	}

	public void LogDebugInfo()
	{
		GeneticsArtifactPlugin.geneticLogSource.LogInfo((object)(Stage.instance.sceneDef.baseSceneName + " " + ((Object)characterBody).name + " " + currentGenes[GeneStat.MaxHealth] + " " + currentGenes[GeneStat.MoveSpeed] + " " + currentGenes[GeneStat.AttackSpeed] + " " + currentGenes[GeneStat.AttackDamage]));
	}

	private void InitializeCurrentGenes()
	{
		currentGenes = new Dictionary<GeneStat, float>();
		foreach (GeneStat value in Enum.GetValues(typeof(GeneStat)))
		{
			currentGenes.Add(value, 1f);
		}
	}

	public void AdaptToNewGenes(Dictionary<GeneStat, float> newGenes)
	{
		foreach (KeyValuePair<ItemDef, int> item in GeneTokenCalc.GetTokensToAdd(currentGenes, newGenes))
		{
			characterBody.inventory.GiveItem(item.Key, item.Value);
		}
		currentGenes = newGenes;
	}

	private Dictionary<GeneStat, float> GenerateMutationAttempt()
	{
		Dictionary<GeneStat, float> dictionary = new Dictionary<GeneStat, float>();
		float num = ConfigManager.geneVarianceLimit.Value * (float)((!(Stage.instance.sceneDef.baseSceneName == "artifactworld")) ? 1 : 5);
		foreach (GeneStat key in currentGenes.Keys)
		{
			float num2 = currentGenes[key];
			if (ConfigManager.enableGeneLimitOverrides.Value && GeneEngineDriver.geneLimitOverrides.ContainsKey(key))
			{
				dictionary.Add(key, (float)decimal.Round((decimal)Mathf.Clamp(Random.Range(num2 * (1f - num), num2 * (1f + num)), GeneEngineDriver.geneLimitOverrides[key].Item1, GeneEngineDriver.geneLimitOverrides[key].Item2), 2));
			}
			else
			{
				dictionary.Add(key, (float)decimal.Round((decimal)Mathf.Clamp(Random.Range(num2 * (1f - num), num2 * (1f + num)), ConfigManager.geneFloor.Value, ConfigManager.geneCap.Value), 2));
			}
		}
		return dictionary;
	}

	private void OnDestroy()
	{
		ScoreMe();
		GeneEngineDriver.livingGenes.Remove(this);
		GeneEngineDriver.deadGenes.Add(this);
	}

	public float ScoreMe()
	{
		score = 0f;
		if (timeAlive > 0f && timeEngaged > 0f)
		{
			float num = timeEngaged / timeAlive;
			score = damageDealt * num;
		}
		this.MoGBPostScoringEvent?.Invoke(this, new EventArgs());
		return score;
	}
}
[BepInPlugin("com.RicoValdezio.ArtifactOfGenetics", "Genetics", "4.5.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class GeneticsArtifactPlugin : BaseUnityPlugin
{
	public const string ModVer = "4.5.3";

	public const string ModName = "Genetics";

	public const string ModGuid = "com.RicoValdezio.ArtifactOfGenetics";

	public static GeneticsArtifactPlugin Instance;

	public static ManualLogSource geneticLogSource;

	public static AssetBundle geneticAssetBundle;

	private void Awake()
	{
		if ((Object)(object)Instance == (Object)null)
		{
			Instance = this;
		}
		geneticLogSource = ((BaseUnityPlugin)Instance).Logger;
		geneticAssetBundle = AssetBundle.LoadFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("GeneticsArtifact.ArtifactResources.genetics"));
		ConfigManager.Init(((BaseUnityPlugin)this).Config);
		ArtifactOfGenetics.Init();
		GeneTokens.Init();
		GeneTokenCalc.RegisterHooks();
		GeneEngineDriver.RegisterHooks();
		foreach (PluginInfo value in Chainloader.PluginInfos.Values)
		{
			if (value.Metadata.GUID.Equals("com.rune580.riskofoptions"))
			{
				RiskOfOptionsCompat.Init();
				break;
			}
		}
	}
}