Decompiled source of CreatureLevelAndLootControl PTBR v0.1.0
CreaturePTBR.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using Splatform; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: Guid("6363d416-d2b3-437d-8f72-ed0069245f86")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyCompany("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyProduct("CreatureLevelControl")] [assembly: AssemblyTitle("CreatureLevelControl")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyDescription("https://valheim.thunderstore.io/package/Smoothbrain/CreatureLevelAndLootControl")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: <6c79ef52-1d18-4a52-b86b-be9360ea1262>RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<97c74bb4-9272-4b0e-a1bd-099c0a59de49>Embedded] internal sealed class <97c74bb4-9272-4b0e-a1bd-099c0a59de49>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [<97c74bb4-9272-4b0e-a1bd-099c0a59de49>Embedded] [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class <75b8e597-2006-46dc-8007-b4ba3b036dbf>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <75b8e597-2006-46dc-8007-b4ba3b036dbf>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <75b8e597-2006-46dc-8007-b4ba3b036dbf>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<97c74bb4-9272-4b0e-a1bd-099c0a59de49>Embedded] [CompilerGenerated] internal sealed class <a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContextAttribute : Attribute { public readonly byte Flag; public <a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [<97c74bb4-9272-4b0e-a1bd-099c0a59de49>Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class <6c79ef52-1d18-4a52-b86b-be9360ea1262>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <6c79ef52-1d18-4a52-b86b-be9360ea1262>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CreatureLevelControl { public enum CreatureExtraEffect { None, Aggressive, Quick, Regenerating, Curious, Splitting, Armored } public enum CreatureInfusion { None, Lightning, Fire, Frost, Poison, Chaos, Spirit } public enum BossAffix { None, Reflective, Shielded, Mending, Summoner, Elementalist, Enraged, Twin } [PublicAPI] [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)] public static class API { public static bool IsEnabled() { return true; } public static bool IsInfusionEnabled() { return CreatureLevelControl.creatureInfusionEffects.GetToggle(); } public static bool IsExtraEffectEnabled() { return CreatureLevelControl.creatureSpecialEffects.GetToggle(); } public static bool IsAffixEnabled() { return CreatureLevelControl.bossSpecialEffects.GetToggle(); } public static int GetWorldLevel() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZoneSystem.instance) || !Object.op_Implicit((Object)(object)Game.instance)) { return 0; } int result = CreatureLevelControl.worldLevels.Count; if (CreatureLevelControl.difficultySecondFactor.Value == CreatureLevelControl.DifficultySecondFactor.Distance) { Vector3 val = default(Vector3); ZoneSystem.instance.GetLocationIcon(Game.instance.m_StartLocation, ref val); Player localPlayer = Player.m_localPlayer; Vector3 val2 = (Vector3)((localPlayer != null) ? ((Component)localPlayer).transform.localPosition : default(Vector3)) - val; float num = Mathf.Sqrt(Mathf.Pow(val2.x, 2f) + Mathf.Pow(val2.z, 2f)); foreach (ConfigEntry<int> key in CreatureLevelControl.spawnDistance.Keys) { if (num < (float)key.Value) { result = CreatureLevelControl.spawnDistance[key]; break; } } } else if (CreatureLevelControl.difficultySecondFactor.Value != CreatureLevelControl.DifficultySecondFactor.Age_of_world) { result = ((CreatureLevelControl.difficultySecondFactor.Value != CreatureLevelControl.DifficultySecondFactor.BossesKilled) ? 3 : new string[6] { "eikthyr", "gdking", "bonemass", "dragon", "goblinking", "queen" }.Count([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string boss) => ZoneSystem.instance.GetGlobalKey("defeated_" + boss))); } else { int day = EnvMan.instance.GetDay(ZNet.instance.GetTimeSeconds()); foreach (ConfigEntry<int> key2 in CreatureLevelControl.worldLevels.Keys) { if (day < key2.Value) { result = CreatureLevelControl.worldLevels[key2]; break; } } } return result; } internal static float[] zeroProbabilities(float[] p, int shift = 0) { float num = 100f; for (int i = 0; i < p.Length; i++) { num -= p[i]; if (num < 0f) { p[i] += num; num = 0f; } } float[] array = new float[shift + 1].Concat(p).ToArray(); array[shift] = num; return array; } public static float[] LevelProbabilities([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] Character character, int worldLevel, bool includeZoneBonusLevel) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) int num; if (!includeZoneBonusLevel) { num = 0; } else { object obj; if (character == null) { obj = null; } else { ZNetView component = ((Component)character).GetComponent<ZNetView>(); obj = ((component != null) ? component.GetZDO() : null); } num = ((obj == null) ? CreatureSector.sectorBonusLevel(((Component)Player.m_localPlayer).GetComponent<ZNetView>().GetZDO().GetSector()) : CreatureSector.sectorBonusLevel(character)); } int num2 = num; if ((Object)(object)character != (Object)null) { float[] array = Utils.ReadWithWorldLevelFromConfig(character, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToStars); if (array != null) { return zeroProbabilities(array, (!character.IsBoss()) ? num2 : 0); } } if (character != null && character.IsBoss() && !CreatureLevelControl.bossLevelUseCreatureLevel.GetToggle()) { return zeroProbabilities(Utils.ParseStringProbabilities(CreatureLevelControl.customBossLevelChances.Value)); } if (CreatureLevelControl.difficulty.Value == CreatureLevelControl.Difficulty.Custom) { return zeroProbabilities(Utils.ParseStringProbabilities(CreatureLevelControl.customLevelChances[worldLevel].Value), num2); } if (!CreatureLevelControl.levelConfig.TryGetValue(CreatureLevelControl.difficulty.Value, out var value)) { value = CreatureLevelControl.levelConfig[CreatureLevelControl.Difficulty.Medium]; } float[] source = zeroProbabilities(value[worldLevel], num2); int value2 = (int)CreatureLevelControl.minimumLevel.Value; int num3 = Math.Max(value2, (int)CreatureLevelControl.maximumLevel.Value); float num4 = source.Take(value2).Sum(); float num5 = source.Skip(1 + num3).Sum(); source = new float[value2].Concat(source.Skip(value2).Take(1 + num3 - value2)).ToArray(); source[value2] += num4; if (num5 > 0f) { source = source.Concat(new float[Mathf.Max(0, 1 + num3 - source.Length)]).ToArray(); source[num3] += num5; } return source; } public static int LevelRand(Character character) { return Utils.LevelFromProbabilities(LevelProbabilities(character, GetWorldLevel(), includeZoneBonusLevel: true)); } public static bool HasAffixBoss(Character character) { return HasExtraEffectCreature(character); } public static BossAffix GetAffixBoss(Character character) { ZNetView component = ((Component)character).GetComponent<ZNetView>(); if (!CreatureLevelControl.bossSpecialEffects.GetToggle() || ((component != null) ? component.GetZDO() : null) == null) { return BossAffix.None; } return (BossAffix)component.GetZDO().GetInt("CL&LC effect", 0); } public static void SetAffixBoss(Character character, BossAffix affix) { //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_023c: 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_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) string[] source = new string[7] { "Eikthyr", "gd_king", "Bonemass", "Dragon", "GoblinKing", "SeekerQueen", "Fader" }; if (affix == BossAffix.Summoner && !source.Contains(((Object)character).name.Replace("(Clone)", ""))) { affix = BossAffix.None; } if (GetAffixBoss(character) == BossAffix.Twin) { if (affix != BossAffix.Twin) { Character twinBoss = GetTwinBoss(character); GameObject val = ((twinBoss != null) ? ((Component)twinBoss).gameObject : null); if (val != null) { ZNetScene.instance.Destroy(val); } } float num = Utils.ReadValueFromEnumWithWorldLevelAndStarsFromConfig(character, BossAffix.Twin, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 2 })] (CreatureConfig c) => c.worldLevelToBossAffixFactor) ?? (CreatureLevelControl.bossAffixPowerTwin.Value / 100f); character.m_health /= num; character.SetupMaxHealth(); } else if (affix == BossAffix.Twin) { if (CreatureLevelControl.bossSpecialEffects.GetToggle()) { float num2 = Utils.ReadValueFromEnumWithWorldLevelAndStarsFromConfig(character, BossAffix.Twin, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 2 })] (CreatureConfig c) => c.worldLevelToBossAffixFactor) ?? (CreatureLevelControl.bossAffixPowerTwin.Value / 100f); character.m_health *= num2; character.SetupMaxHealth(); setAffixBossZDO(character, affix); ZPackage val2 = new ZPackage(); character.m_nview.GetZDO().Serialize(val2); val2.SetPos(0); ZDO val3 = new ZDO(); val3.Init(); val3.m_uid = Utils.GenerateNewZDOID(); val3.Deserialize(val2); val3.SetRotation(Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)); val3.SetPosition(((Component)character).transform.localPosition + Random.insideUnitSphere * 0.5f); val3.SetOwnerInternal(ZDOMan.GetSessionID()); ZDOMan.instance.m_objectsByID.Add(val3.m_uid, val3); Character component = ZNetScene.instance.CreateObject(val3).GetComponent<Character>(); Vector3 insideUnitSphere = Random.insideUnitSphere; if (insideUnitSphere.y < 0f) { insideUnitSphere.y = 0f - insideUnitSphere.y; } ((Component)component).GetComponent<Rigidbody>().AddForce(insideUnitSphere * 5f, (ForceMode)2); CreatureLevelControl.SetTwinBoss(character, component); } else { affix = BossAffix.None; } } setAffixBossZDO(character, affix); OriginalCharacterData component2 = ((Component)character).GetComponent<OriginalCharacterData>(); if (component2 != null) { component2.Awake(); } else { ((Component)character).gameObject.AddComponent<OriginalCharacterData>(); } CreatureLevelControl.ShowStar.NeedsUpdate.Remove(character); } private static void setAffixBossZDO(Character character, BossAffix affix) { ((Component)character).GetComponent<ZNetView>().GetZDO().Set("CL&LC effect", (int)affix); } public static bool HasExtraEffectCreature(Character character) { return ((Component)character).GetComponent<ZNetView>().GetZDO().GetInt("CL&LC effect", -1) != -1; } public static CreatureExtraEffect GetExtraEffectCreature(Character character) { ZNetView component = ((Component)character).GetComponent<ZNetView>(); if (!CreatureLevelControl.creatureSpecialEffects.GetToggle() || ((component != null) ? component.GetZDO() : null) == null || character.GetLevel() <= 1) { return CreatureExtraEffect.None; } return (CreatureExtraEffect)component.GetZDO().GetInt("CL&LC effect", 0); } public static void SetExtraEffectCreature(Character character) { float rand; HashSet<CreatureExtraEffect> processedProbabilities; CreatureExtraEffect? creatureExtraEffect = Utils.RandomWithProbabilityFromConfig(character, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToCreatureEffect, out rand, out processedProbabilities); if (!creatureExtraEffect.HasValue) { creatureExtraEffect = CreatureExtraEffect.None; foreach (CreatureExtraEffect key in CreatureLevelControl.customCreatureAffixChances.Keys) { if (!processedProbabilities.Contains(key)) { rand -= CreatureLevelControl.customCreatureAffixChances[key].Value; if (rand < 0f) { creatureExtraEffect = key; break; } } } } SetExtraEffectCreature(character, creatureExtraEffect.Value); } public static void SetExtraEffectCreature(Character character, CreatureExtraEffect effect) { ((Component)character).GetComponent<ZNetView>().GetZDO().Set("CL&LC effect", (int)effect); CreatureLevelControl.SetPersistedCharacterAttributes(character); CreatureLevelControl.ShowStar.NeedsUpdate.Remove(character); } public static bool HasInfusionCreature(Character character) { return ((Component)character).GetComponent<ZNetView>().GetZDO().GetInt("CL&LC infusion", -1) != -1; } public static CreatureInfusion GetInfusionCreature(Character character) { ZNetView component = ((Component)character).GetComponent<ZNetView>(); if (!CreatureLevelControl.creatureInfusionEffects.GetToggle() || ((component != null) ? component.GetZDO() : null) == null) { return CreatureInfusion.None; } return (CreatureInfusion)component.GetZDO().GetInt("CL&LC infusion", 0); } public static void SetInfusionCreature(Character character) { float rand; HashSet<CreatureInfusion> processedProbabilities; CreatureInfusion? creatureInfusion = Utils.RandomWithProbabilityFromConfig(character, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })] (CreatureConfig c) => c.worldLevelToInfusion, out rand, out processedProbabilities); CreatureInfusion infusion; if (creatureInfusion.HasValue) { infusion = creatureInfusion.GetValueOrDefault(); } else { infusion = CreatureInfusion.None; if (!CreatureLevelControl.infusionProbabilityModifiersByLevel.TryGetValue(character.GetLevel(), out var value)) { value = 1f; } if (Random.Range(0f, 1f) <= value) { foreach (CreatureInfusion key in CreatureLevelControl.customCreatureInfusionChances.Keys) { if (!processedProbabilities.Contains(key)) { rand -= CreatureLevelControl.customCreatureInfusionChances[key].Value; if (rand < 0f) { infusion = key; break; } } } } } SetInfusionCreature(character, infusion); } public static void SetInfusionCreature(Character character, CreatureInfusion infusion) { ((Component)character).GetComponent<ZNetView>().GetZDO().Set("CL&LC infusion", (int)infusion); OriginalCharacterData component = ((Component)character).GetComponent<OriginalCharacterData>(); if (component != null) { component.immutableExtra = true; } CreatureLevelControl.AttachInfusionFlames(character); CreatureLevelControl.ShowStar.NeedsUpdate.Remove(character); } [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] public static Character GetTwinBoss(Character boss) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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) ZDOID zDOID = ((Component)boss).GetComponent<ZNetView>().GetZDO().GetZDOID("CL&LC twin boss"); if (ZDOMan.instance.m_objectsByID.TryGetValue(zDOID, out var value) && ZNetScene.s_instance.m_instances.TryGetValue(value, out var value2)) { return ((Component)value2).GetComponent<Character>(); } return null; } public static bool DropItemOnDeath(ItemData item) { bool? flag = Utils.ReadWithWorldLevelFromConfig(item, [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] (ItemConfig c) => c.worldLevelToItemLoss); if (!flag.HasValue) { if (!item.m_shared.m_questItem) { return !item.m_equipped; } return false; } return flag.GetValueOrDefault(); } } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)] [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] public class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1 })] public Action<ConfigEntryBase> CustomDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 1 })] public Func<object, string> ObjToStr; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 1 })] public Func<string, object> StrToObj; } [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)] public abstract class ConfigFile { public interface Loader { [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] ConfigFile ConfigFile { [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)] get; [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)] set; } string FilePattern { get; } string EditButtonName { get; } CustomSyncedValue<List<string>> FileData { get; } bool Enabled { get; } ConfigFile InstantiateConfig(); void ProcessConfig(); } [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] protected class Section : IDisposable { [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] private readonly Section lastSection; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] private readonly Dictionary<string, object> dict; public readonly string dictKey; private readonly HashSet<string> knownKeys = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase); private readonly ConfigFile configFile; public string Path => ((lastSection == null || lastSection.dictKey == "") ? "" : (lastSection.Path + ".")) + dictKey; public Section([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] Dictionary<string, object> dict, string key, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] Section lastSection, ConfigFile file) { this.dict = dict; dictKey = key; this.lastSection = lastSection; configFile = file; } [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] public object Get(string key) { knownKeys.Add(key); if (dict.TryGetValue(key, out var value) && value == null) { configFile.configErrors.Add(Path + "." + key + " cannot be empty"); } return value; } public IEnumerable<string> KeysWithPrefix(string prefix) { return dict.Keys.Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string k) => k.StartsWith(prefix)); } public void Dispose() { IEnumerable<string> enumerable = dict.Keys.Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string key) => !knownKeys.Contains(key)).ToArray(); if (enumerable.Any()) { configFile.configWarnings.Add(Path + " contains unknown keys " + string.Join(", ", enumerable)); } } } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] protected delegate bool ParserDelegate<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] ref T target, Section sect, string key); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)] private struct ParseResult<T> { [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] public T value; public string error; } public static readonly Loader[] loaders = new Loader[2] { new CreatureConfig.Loader(), new ItemConfig.Loader() }; public readonly List<string> configErrors = new List<string>(); public readonly List<string> configWarnings = new List<string>(); protected readonly Dictionary<string, List<string>> groups = new Dictionary<string, List<string>>(); public void DumpWarnings(string prefix) { if (configWarnings.Count > 0) { Debug.LogWarning((object)(prefix + ((configErrors.Count > 0) ? "" : " The config file was loaded, but may not yield expected results due to warnings:") + "\n" + string.Join("\n", configWarnings))); configWarnings.Clear(); } } protected void AssignConfig<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] T>(ref T newConfig, T inConfig) where T : class { if (newConfig == null) { newConfig = inConfig; } } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] protected void AssignConfig<T>(ref T? newConfig, T? inConfig) where T : struct { T? val = newConfig; if (!val.HasValue) { newConfig = inConfig; } } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)] protected void AssignEnumConfig<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 1, 2 })] ref Dictionary<int, Dictionary<T, float[]>> newConfig, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 1, 2 })] Dictionary<int, Dictionary<T, float[]>> inConfig) { if (inConfig == null) { return; } if (newConfig == null) { newConfig = inConfig.ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<int, Dictionary<T, float[]>> kv) => kv.Key, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<int, Dictionary<T, float[]>> kv) => kv.Value.ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<T, float[]> k) => k.Key, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<T, float[]> k) => k.Value)); } foreach (KeyValuePair<int, Dictionary<T, float[]>> item in inConfig) { if (!newConfig.ContainsKey(item.Key)) { newConfig[item.Key] = item.Value; continue; } foreach (KeyValuePair<T, float[]> item2 in item.Value) { if (!newConfig[item.Key].ContainsKey(item2.Key)) { newConfig[item.Key][item2.Key] = item2.Value; } } } } protected void resolveGroupsForName(List<string> groupNames, string name) { foreach (KeyValuePair<string, List<string>> group in groups) { if (!groupNames.Contains(group.Key) && group.Value.Contains(name)) { groupNames.Add(group.Key); resolveGroupsForName(groupNames, group.Key); } } } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)] protected void fillWorldLevels<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1 })] Dictionary<int, T> config) { if (config == null) { return; } T value = default(T); int num = -1; for (int i = 0; i <= CreatureLevelControl.defaultWorldLevelDays.Length; i++) { if (config.TryGetValue(i, out var value2)) { value = value2; if (num == -1) { num = i; } } else if (num != -1) { config[i] = value; } } for (int j = 0; j < num; j++) { config[j] = config[num]; } } [PublicAPI] [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] protected static Dictionary<string, object> castDictToStringDict([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] Dictionary<object, object> dict) { return new Dictionary<string, object>(dict.ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<object, object> kv) => kv.Key.ToString(), [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<object, object> kv) => kv.Value), StringComparer.CurrentCultureIgnoreCase); } [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] protected Section section(Section parent, string key) { object obj = parent.Get(key); if (obj is Dictionary<object, object> dict) { return new Section(castDictToStringDict(dict), key, parent, this); } if (obj != null) { configWarnings.Add($"Expected a section containing further configuration values, got {obj.GetType()} for {parent.Path}.{key}"); } return null; } public void Parse(object configObj) { if (configObj is Dictionary<object, object> dict) { Dictionary<string, object> dictionary = castDictToStringDict(dict); foreach (KeyValuePair<string, object> item2 in dictionary) { if (item2.Key == "groups") { if (item2.Value is Dictionary<object, object> dictionary2) { foreach (KeyValuePair<object, object> item3 in dictionary2) { string text = item3.Key.ToString(); List<string> source; if (item3.Value is string item) { source = new List<string> { item }; } else { if (!(item3.Value is List<object> source2)) { configErrors.Add("groups." + text + " contains an invalid value (" + (item3.Value?.GetType().Name ?? "null") + ")"); continue; } source = source2.Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (object s) => s != null).Cast<string>().ToList(); } groups[text.ToLower()] = source.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string s) => s.ToLower()).ToList(); } } else { configErrors.Add("groups must contain a mapping from group to a list of group or creature names"); } } else { Section section = this.section(new Section(dictionary, "", null, this), item2.Key); if (section != null) { ParsePrimarySection(section); section.Dispose(); continue; } configErrors.Add("All top-level keys must be a mapping. Got unexpected " + (item2.Value?.GetType().ToString() ?? "null") + " for key '" + item2.Key + "'."); } } } Verify(); } protected virtual void Verify() { } protected abstract void ParsePrimarySection(Section primarySection); [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] private bool parseScalar<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string input, out T output) where T : struct { if (typeof(int) == typeof(T)) { if (int.TryParse(input, out var result)) { output = (T)(object)result; return true; } } else if (typeof(float) == typeof(T)) { if (float.TryParse(input, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { output = (T)(object)result2; return true; } } else if (typeof(bool) == typeof(T) || typeof(T) == typeof(ItemConfig.Teleportable)) { string[] source = new string[12] { "0", "false", "off", "no", "nope", "nah", "-", "hell no", "pls dont", "lol no", "certainly not", "absolutely not" }; string[] source2 = new string[14] { "1", "true", "on", "yes", "yep", "yeah", "+", "hell yeah", "ok", "okay", "k", "yaaas", "certainly", "absolutely" }; if (source.Contains(input.ToLower())) { output = ((typeof(ItemConfig.Teleportable) == typeof(T)) ? ((T)(object)default(ItemConfig.Teleportable)) : ((T)(object)false)); return true; } if (source2.Contains(input.ToLower())) { output = ((typeof(ItemConfig.Teleportable) == typeof(T)) ? ((T)(object)new ItemConfig.Teleportable { amount = int.MaxValue }) : ((T)(object)true)); return true; } } output = default(T); return false; } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] protected bool ParseScalarFromObject<T>(ref T target, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] Section sect, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string key) where T : struct { T? target2 = null; if (ParseScalarFromObject(ref target2, sect, key)) { target = target2.Value; return true; } return false; } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] protected bool ParseScalarFromObject<T>(ref T? target, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] Section sect, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string key) where T : struct { object obj = sect.Get(key); if (obj != null) { if (obj is string input && parseScalar<T>(input, out var output)) { target = output; return true; } configErrors.Add(sect.Path + "." + key + " is not a " + typeof(T).Name + " describing a " + key + " multiplier"); } return false; } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] private bool parseStructFromDict<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] Dictionary<object, object> input, out T output, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string path) where T : struct { output = default(T); if (!typeof(T).IsPrimitive && !typeof(T).IsEnum) { HashSet<string> hashSet = new HashSet<string>(); FieldInfo[] fields = typeof(T).GetFields(); foreach (FieldInfo fieldInfo in fields) { if (!input.TryGetValue(fieldInfo.Name, out var value)) { continue; } hashSet.Add(fieldInfo.Name); object[] array; if (fieldInfo.FieldType.IsPrimitive || fieldInfo.FieldType.IsEnum) { array = new object[2] { value, null }; if (!(bool)typeof(ConfigFile).GetMethod("parseScalar", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(fieldInfo.FieldType).Invoke(this, array)) { configErrors.Add(path + "." + fieldInfo.Name + " is not " + fieldInfo.FieldType.Name); continue; } } else { array = new object[3] { value, null, path + "." + fieldInfo.FieldType.Name }; typeof(ConfigFile).GetMethod("parseStructFromDict", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(fieldInfo.FieldType).Invoke(this, array); } fieldInfo.SetValue(output, array[1]); } foreach (object key in input.Keys) { if (!hashSet.Contains(key)) { configErrors.Add(string.Format("{0} contains invalid key '{1}'. Allowed keys are {2}.", path, key, string.Join(", ", from f in typeof(T).GetFields() select f.Name))); } } return true; } return false; } [PublicAPI] [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)] protected float[] ParseProbabilityMap([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string path, object value) { if (value is List<object> list) { float[] array = new float[list.Count]; for (int i = 0; i < list.Count; i++) { if (list[i] is string s && float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { array[i] = result; } else { configErrors.Add($"{path}[{i}] is not a float denoting a probability"); } } return array; } return null; } protected bool ParseWorldlevelToSingleScalar<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 0 })] ref Dictionary<int, T?> target, Section sect, string key) where T : struct { string name = typeof(T).Name; object obj = sect.Get(key); if (obj != null) { T output; if (obj.ToString().ToLower() == "default") { target = Enumerable.Repeat<T?>(null, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T? v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); } else if (obj is string input && parseScalar<T>(input, out output)) { target = Enumerable.Repeat((T?)output, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T? v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); } else if (obj is Dictionary<object, object> dictionary) { target = new Dictionary<int, T?>(); bool flag = true; foreach (KeyValuePair<object, object> item in dictionary) { if (int.TryParse(item.Key.ToString(), out var result)) { if (item.Value?.ToString().ToLower() == "default") { target[result] = null; } else if (item.Value is string input2 && parseScalar<T>(input2, out output)) { target[result] = output; } else if (item.Value is Dictionary<object, object> input3 && parseStructFromDict<T>(input3, out output, $"{sect.Path}.{key}.{result}")) { target[result] = output; } else { configErrors.Add($"{sect.Path}.{key}.{result} is not 'default' nor {name}"); } } else { if (!flag && !typeof(T).IsPrimitive && !typeof(T).IsEnum && parseStructFromDict<T>(dictionary, out output, sect.Path + "." + key)) { target = Enumerable.Repeat((T?)output, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T? v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); break; } configErrors.Add($"{sect.Path}.{key} contains a non-integer key {item.Key}"); } flag = false; } } else { configErrors.Add(sect.Path + "." + key + " is not 'default', " + name + " nor Map"); } } return target != null; } protected bool ParseWorldlevelToFloatMap([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] ref Dictionary<int, float[]> target, Section sect, string key) { object obj = sect.Get(key); if (obj != null) { int result; float result2; if (obj.ToString().ToLower() == "default") { target = Enumerable.Repeat<float[]>(null, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); } else if (key == "stars" && obj is string s && int.TryParse(s, out result)) { float[] element = ((!(sect.dictKey != "sector")) ? ((result < 0) ? Array.Empty<float>() : new float[1] { -result }) : ((result <= 0) ? Array.Empty<float>() : Enumerable.Repeat(0f, result - 1).Concat(new float[1] { 100f }).ToArray())); target = Enumerable.Repeat(element, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); } else if (key != "stars" && obj is string s2 && float.TryParse(s2, NumberStyles.Float, CultureInfo.InvariantCulture, out result2)) { target = Enumerable.Repeat(new float[1] { result2 }, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); } else { float[] array = ParseProbabilityMap(sect.Path + "." + key, obj); if (array != null) { target = Enumerable.Repeat(array, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float[] v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); } else if (obj is Dictionary<object, object> dictionary) { target = new Dictionary<int, float[]>(); foreach (KeyValuePair<object, object> item in dictionary) { if (int.TryParse(item.Key.ToString(), out var result3)) { if (item.Value?.ToString().ToLower() == "default") { target[result3] = null; continue; } if (key == "stars" && item.Value is string s3 && int.TryParse(s3, out result)) { if (sect.dictKey != "sector") { target[result3] = ((result <= 0) ? Array.Empty<float>() : Enumerable.Repeat(0f, result - 1).Concat(new float[1] { 100f }).ToArray()); } else { target[result3] = ((result < 0) ? Array.Empty<float>() : new float[1] { -result }); } continue; } if (key != "stars" && item.Value is string s4 && float.TryParse(s4, NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)) { target[result3] = new float[1] { result4 }; continue; } float[] array2 = ParseProbabilityMap($"{sect.Path}.{key}.{result3}", item.Value); if (array2 != null) { target[result3] = array2; continue; } configErrors.Add(string.Format("{0}.{1}.{2} is not 'default', {3} nor List", sect.Path, key, result3, (key == "stars") ? "integer" : "float")); } else { configErrors.Add($"{sect.Path}.{key} contains a non-integer key {item.Key}"); } } } else { configErrors.Add(sect.Path + "." + key + " is not 'default', " + ((key == "stars") ? "integer" : "float") + " nor List nor Map"); } } } return target != null; } protected bool ParseEnumConfig<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 0, 2 })] ref Dictionary<int, Dictionary<T, float[]>> target, Section sect, string key) where T : struct, IConvertible { List<T> allEnumValues = ((T[])Enum.GetValues(typeof(T))).Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T t) => t.ToInt32(CultureInfo.InvariantCulture) != 0).ToList(); object obj = sect.Get(key); if (obj != null) { if (obj.ToString().ToLower() == "default") { target = Enumerable.Repeat(((IEnumerable<T>)allEnumValues).ToDictionary((Func<T, T>)([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T k) => k), (Func<T, float[]>)([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T _) => null)), CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); } else if (obj is string text) { if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { target = Enumerable.Repeat(defaultEntryFromProbability(result), CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); } else if (typeof(T) != typeof(CreatureLevelControl.ModifyDamage)) { ParseResult<T> parseResult = ParseEnum(text); if (parseResult.error == null) { target = Enumerable.Repeat(new Dictionary<T, float[]> { { parseResult.value, new float[1] { 100f } } }, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); } else { configErrors.Add(sect.Path + "." + key + " contains invalid value " + text + ", expecting default, float, " + parseResult.error + " or dictionary"); } } } else { if (typeof(T) == typeof(CreatureLevelControl.ModifyDamage)) { float[] array = ParseProbabilityMap(sect.Path + "." + key, obj); if (array != null) { target = Enumerable.Repeat(new Dictionary<T, float[]> { { (T)(object)CreatureLevelControl.ModifyDamage.All, array } }, CreatureLevelControl.defaultWorldLevelDays.Length + 1).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Dictionary<T, float[]> v, int i) => new { v, i }).ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.i, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] k => k.v); goto IL_0653; } } if (obj is Dictionary<object, object> dictionary) { target = new Dictionary<int, Dictionary<T, float[]>>(); if (dictionary.Count > 0) { if (int.TryParse(dictionary.Keys.First().ToString(), out var _)) { foreach (KeyValuePair<object, object> item in dictionary) { if (int.TryParse(item.Key.ToString(), out var result3)) { float result4; if (item.Value?.ToString().ToLower() == "default") { target[result3] = ((IEnumerable<T>)allEnumValues).ToDictionary((Func<T, T>)([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T k) => k), (Func<T, float[]>)([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T _) => null)); } else if (item.Value is string s && float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out result4)) { target[result3] = defaultEntryFromProbability(result4); } else if (item.Value is Dictionary<object, object> affixes2) { target[result3] = ParseAffixProbabilities($"{sect.Path}.{key}[{result3}]", affixes2); } else { configErrors.Add($"{sect.Path}.{key}[{result3}] is not a mapping from affix names to probabilities"); } } else { configErrors.Add(sect.Path + "." + key + " contains mixed world levels and affix names"); } } } else { Dictionary<T, float[]> value = ParseAffixProbabilities(sect.Path + "." + key, dictionary); for (int j = 0; j <= CreatureLevelControl.defaultWorldLevelDays.Length; j++) { target[j] = value; } } } } else { configErrors.Add(sect.Path + "." + key + " is not integer" + ((typeof(T) == typeof(CreatureLevelControl.ModifyDamage)) ? ", List" : "") + ", 'default' nor Map"); } } } goto IL_0653; IL_0653: return target != null; [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0, 2 })] Dictionary<T, float[]> ParseAffixProbabilities([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string path, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] Dictionary<object, object> affixes) { Dictionary<T, float[]> affixProbabilities = new Dictionary<T, float[]>(); bool hasOther = false; float[] otherValue = null; foreach (KeyValuePair<object, object> affix in affixes) { bool isOther = affix.Key.ToString().ToLower() == "other"; ParseResult<T> result5 = ParseEnum(affix.Key.ToString()); if (isOther || result5.error == null) { float result6; if (affix.Value?.ToString().ToLower() == "default") { assign(null); } else if (affix.Value is string s2 && float.TryParse(s2, NumberStyles.Float, CultureInfo.InvariantCulture, out result6)) { assign(new float[1] { result6 }); } else { float[] array2 = ParseProbabilityMap($"{path}.{affix.Key}", affix.Value); if (array2 != null) { assign(array2); } else { configErrors.Add(string.Format("{0}.{1} (value '{2}') is not a float or list of floats denoting probabilities", path, affix.Key, (affix.Value is string) ? affix.Value : (affix.Value?.GetType().Name ?? "null"))); } } } else { configErrors.Add($"{path} contains unexpected affix key {affix.Key}, expecting either other, {result5.error}"); } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] void assign([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] float[] probabilityArray) { if (isOther) { hasOther = true; otherValue = probabilityArray; } else { affixProbabilities[result5.value] = probabilityArray; } } } if (hasOther) { int undefinedValueCount = allEnumValues.Count - affixProbabilities.Count; if (otherValue != null && undefinedValueCount > 0) { otherValue = otherValue.Select((float p) => p / (float)undefinedValueCount).ToArray(); } foreach (T item2 in allEnumValues) { if (!affixProbabilities.ContainsKey(item2)) { affixProbabilities[item2] = otherValue; } } } return affixProbabilities; } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] ParseResult<T> ParseEnum([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(1)] string name) { ParseResult<T> result8; if (!Enum.TryParse<T>(name, ignoreCase: true, out var result7)) { result8 = default(ParseResult<T>); result8.error = string.Join(", ", allEnumValues.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T t) => t.ToString())); return result8; } result8 = default(ParseResult<T>); result8.value = result7; return result8; } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0, 2 })] Dictionary<T, float[]> defaultEntryFromProbability(float probability) { if (!(typeof(T) == typeof(CreatureLevelControl.ModifyDamage))) { return allEnumValues.ToDictionary([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T k) => k, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T _) => new float[1] { probability }); } return new Dictionary<T, float[]> { { (T)(object)CreatureLevelControl.ModifyDamage.All, new float[1] { probability } } }; } } } [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)] public class CreatureConfig { [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] [Flags] public enum CreatureMode { Default = 0, Tamed = 1, Day = 2, Night = 4, Dungeon = 8, Override = 0x10 } [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] public struct CreatureFilter : IComparable { public CreatureMode Mode; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1 })] public Dictionary<string, bool> GlobalKeys; private string globalKeys() { return "Globalkeys " + string.Join(", ", GlobalKeys.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<string, bool> kv) => (kv.Value ? "" : "!") + kv.Key)); } public override string ToString() { if (Mode == CreatureMode.Default) { return globalKeys(); } if (GlobalKeys != null) { return $"{Mode}, {globalKeys()}"; } return Mode.ToString(); } public int CompareTo(object obj) { if (obj is CreatureFilter creatureFilter) { int num = 0; if ((Mode & CreatureMode.Override) == 0 == ((creatureFilter.Mode & CreatureMode.Override) == 0)) { if (GlobalKeys == null != (creatureFilter.GlobalKeys == null)) { if (GlobalKeys != null) { return -1; } return 1; } if (GlobalKeys != null && GlobalKeys.Count != creatureFilter.GlobalKeys.Count) { if (GlobalKeys.Count <= creatureFilter.GlobalKeys.Count) { return 1; } return -1; } } CreatureMode[] modePriorities = CreatureConfig.modePriorities; foreach (CreatureMode creatureMode in modePriorities) { if ((Mode & creatureMode) == 0 != ((creatureFilter.Mode & creatureMode) == 0)) { if ((Mode & creatureMode) != 0) { return -1; } return 1; } if (num == 0 && (Mode & creatureMode) != (creatureFilter.Mode & creatureMode)) { num = ((Mode >= creatureFilter.Mode) ? 1 : (-1)); } } if (num == 0 && GlobalKeys != null && creatureFilter.GlobalKeys != null) { List<KeyValuePair<string, bool>> list = GlobalKeys.OrderBy([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<string, bool> kv) => kv.Key).ToList(); List<KeyValuePair<string, bool>> list2 = creatureFilter.GlobalKeys.OrderBy([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<string, bool> kv) => kv.Key).ToList(); for (int j = 0; j < list.Count; j++) { int num2 = string.Compare(list[j].Key, list2[j].Key, StringComparison.Ordinal); if (num2 != 0) { return num2; } if (list[j].Value != list2[j].Value) { if (!list[j].Value) { return 1; } return -1; } } } return num; } return 1; } } [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] public class ConfigFile : global::CreatureLevelControl.ConfigFile { [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] private delegate void Assigner<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] T>(ref T current, T input); private readonly Dictionary<string, CreatureConfig> configs = new Dictionary<string, CreatureConfig>(); private static List<string> prefabLocalizations(Character prefab) { return new List<string> { ((Object)prefab).name.ToLower(), prefab.m_name.ToLower(), Localization.instance.Localize(prefab.m_name).ToLower(), CreatureLevelControl.englishLocalization.Localize(prefab.m_name).ToLower() }; } private static List<string> biomeLocalizations(Biome biome) { return new string[3] { ((object)(Biome)(ref biome)).ToString().ToLower(), Localization.instance.Localize("$biome_" + ((object)(Biome)(ref biome)).ToString().ToLower()).ToLower(), CreatureLevelControl.englishLocalization.Localize("$biome_" + ((object)(Biome)(ref biome)).ToString().ToLower()).ToLower() }.Distinct().ToList(); } public Dictionary<string, CreatureConfig> Process() { //IL_00cf: 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_00e8: 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) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, CreatureConfig> dictionary = new Dictionary<string, CreatureConfig>(); Biome[] array = new Biome[9]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Biome[] biomeOrder = (Biome[])(object)array; biomeOrder = biomeOrder.Concat(knownBiomes.Where((Biome b) => !biomeOrder.Contains(b))).ToArray(); Dictionary<Biome, List<GameObject>> dictionary2 = new Dictionary<Biome, List<GameObject>>(); foreach (IGrouping<string, SpawnData> item in ZNetScene.instance.GetPrefab("_ZoneCtrl").GetComponent<SpawnSystem>().m_spawnLists.SelectMany([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (SpawnSystemList s) => from p in s.m_spawners where p.m_requiredGlobalKey == "" && Object.op_Implicit((Object)(object)p.m_prefab.gameObject.GetComponent<Character>()) group p by ((Object)p.m_prefab).name)) { Biome val = item.Aggregate((Biome)0, [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Biome a, SpawnData p) => (Biome)(a | p.m_biome)); Biome[] array2 = biomeOrder; foreach (Biome val2 in array2) { if (((Enum)val).HasFlag((Enum)(object)val2)) { if (!dictionary2.TryGetValue(val2, out var value)) { List<GameObject> list2 = (dictionary2[val2] = new List<GameObject>()); value = list2; } value.Add(item.First().m_prefab); break; } } } foreach (KeyValuePair<Biome, List<GameObject>> item2 in dictionary2) { List<string> value2 = item2.Value.SelectMany([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (GameObject prefab) => prefabLocalizations(prefab.GetComponent<Character>())).ToList(); foreach (string item3 in from biomeName in biomeLocalizations(item2.Key) where !groups.ContainsKey(biomeName) select biomeName) { groups[item3] = value2; } } foreach (Character item4 in from p in ZNetScene.instance.m_prefabs select p.GetComponent<Character>() into c where Object.op_Implicit((Object)(object)c) && !c.IsPlayer() select c) { List<string> list3 = prefabLocalizations(item4); string[] array3 = list3.ToArray(); foreach (string name in array3) { resolveGroupsForName(list3, name); } list3.Add(item4.IsBoss() ? "boss" : "creature"); list3.Add("all"); foreach (string item5 in list3) { if (configs.TryGetValue(item5, out var value3)) { if (!dictionary.TryGetValue(item4.m_name, out var value4)) { CreatureConfig creatureConfig2 = (dictionary[item4.m_name] = new CreatureConfig()); value4 = creatureConfig2; } AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.worldLevelToStars, value3.worldLevelToStars); AssignCreatureModeConfigStruct<float>(value4.sizeScalingFactor, value3.sizeScalingFactor); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.baseHealth, value3.baseHealth); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.healthGainPerStar, value3.healthGainPerStar); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(base.AssignConfig, value4.baseDamage, value3.baseDamage); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.damageGainPerStar, value3.damageGainPerStar); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.attackSpeedGainPerStar, value3.attackSpeedGainPerStar); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.movementSpeedGainPerStar, value3.movementSpeedGainPerStar); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.baseMovementSpeed, value3.baseMovementSpeed); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.baseAttackSpeed, value3.baseAttackSpeed); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.spawnAmount, value3.spawnAmount); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.sectorCount, value3.sectorCount); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.sectorStars, value3.sectorStars); AssignCreatureModeConfig<Dictionary<int, float[]>>(base.AssignConfig, value4.worldLevelToLootAmount, value3.worldLevelToLootAmount); AssignCreatureModeConfig<Dictionary<int, float?>>(base.AssignConfig, value4.worldLevelToLootPerStar, value3.worldLevelToLootPerStar); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(base.AssignEnumConfig, value4.worldLevelToCreatureEffect, value3.worldLevelToCreatureEffect); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(base.AssignEnumConfig, value4.worldLevelToCreatureEffectFactor, value3.worldLevelToCreatureEffectFactor); AssignEnumConfig(ref value4.worldLevelToBoss, value3.worldLevelToBoss); AssignEnumConfig(ref value4.worldLevelToBossAffixFactor, value3.worldLevelToBossAffixFactor); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureInfusion, float[]>>>(base.AssignEnumConfig, value4.worldLevelToInfusion, value3.worldLevelToInfusion); AssignCreatureModeConfig<Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(base.AssignEnumConfig, value4.worldLevelToDamageTakenModifier, value3.worldLevelToDamageTakenModifier); } } if (dictionary.TryGetValue(item4.m_name, out var value5)) { fillModeWorldLevels<float[]>(value5.worldLevelToStars); fillModeWorldLevels<Dictionary<CreatureExtraEffect, float[]>>(value5.worldLevelToCreatureEffect); fillModeWorldLevels<Dictionary<CreatureExtraEffect, float[]>>(value5.worldLevelToCreatureEffectFactor); fillWorldLevels(value5.worldLevelToBoss); fillWorldLevels(value5.worldLevelToBossAffixFactor); fillModeWorldLevels<Dictionary<CreatureInfusion, float[]>>(value5.worldLevelToInfusion); fillModeWorldLevels<Dictionary<CreatureLevelControl.ModifyDamage, float[]>>(value5.worldLevelToDamageTakenModifier); fillModeWorldLevels<float[]>(value5.baseHealth); fillModeWorldLevels<float?>(value5.healthGainPerStar); fillModeWorldLevels<Dictionary<CreatureLevelControl.ModifyDamage, float[]>>(value5.baseDamage); fillModeWorldLevels<float?>(value5.damageGainPerStar); fillModeWorldLevels<float[]>(value5.baseMovementSpeed); fillModeWorldLevels<float?>(value5.movementSpeedGainPerStar); fillModeWorldLevels<float[]>(value5.baseAttackSpeed); fillModeWorldLevels<float?>(value5.attackSpeedGainPerStar); fillModeWorldLevels<float[]>(value5.spawnAmount); fillModeWorldLevels<float[]>(value5.sectorCount); fillModeWorldLevels<float[]>(value5.sectorStars); fillModeWorldLevels<float[]>(value5.worldLevelToLootAmount); fillModeWorldLevels<float?>(value5.worldLevelToLootPerStar); } } return dictionary; static void AssignCreatureModeConfig<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] Assigner<T> assigner, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> newConfig, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> inConfig) where T : class { foreach (CreatureFilter item6 in newConfig.Keys.Concat(inConfig.Keys).ToList()) { T value9; if (!newConfig.TryGetValue(item6, out var value7)) { if (inConfig.TryGetValue(item6, out var value8)) { newConfig[item6] = value8; } } else if (inConfig.TryGetValue(item6, out value9)) { assigner(ref value7, value9); newConfig[item6] = value7; } } } static void AssignCreatureModeConfigStruct<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> newConfig, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] SortedDictionary<CreatureFilter, T> inConfig) where T : struct { foreach (CreatureFilter item7 in newConfig.Keys.Concat(inConfig.Keys).ToList()) { if (!newConfig.ContainsKey(item7) && inConfig.TryGetValue(item7, out var value6)) { newConfig[item7] = value6; } } } void fillModeWorldLevels<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 0 })] SortedDictionary<CreatureFilter, Dictionary<int, T>> config) { config.Values.ToList().ForEach(base.fillWorldLevels); } } private SortedDictionary<CreatureFilter, Section> getSections(Section parentSection) { //IL_00c2: 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_00cc: Unknown result type (might be due to invalid IL or missing references) SortedDictionary<CreatureFilter, Section> sections = new SortedDictionary<CreatureFilter, Section> { { default(CreatureFilter), parentSection } }; foreach (CreatureMode item in ((CreatureMode[])Enum.GetValues(typeof(CreatureMode))).Where((CreatureMode v) => v != CreatureMode.Default)) { creatureModeSection(item, new string[1] { item.ToString().ToLower() }); } Biome[] knownBiomes = CreatureConfig.knownBiomes; foreach (Biome biome in knownBiomes) { creatureModeSection(biomeToCreatureMode(biome), biomeLocalizations(biome)); } readGlobalkeys("key_", present: true); readGlobalkeys("nokey_", present: false); return sections; void creatureModeSection(CreatureMode mode, IEnumerable<string> localizations) { Section section3 = localizations.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (string localizedKey) => section(parentSection, localizedKey)).FirstOrDefault([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (Section section) => section != null); if (section3 != null) { foreach (KeyValuePair<CreatureFilter, Section> section4 in getSections(section3)) { CreatureFilter key2 = section4.Key; key2.Mode |= mode; sections[key2] = section4.Value; } } } void readGlobalkeys(string prefix, bool present) { foreach (string item2 in parentSection.KeysWithPrefix(prefix)) { Section section2 = section(parentSection, item2); if (section2 != null) { foreach (KeyValuePair<CreatureFilter, Section> section5 in getSections(section2)) { CreatureFilter key = section5.Key; key.GlobalKeys = ((key.GlobalKeys != null) ? new Dictionary<string, bool>(key.GlobalKeys) : new Dictionary<string, bool>()); key.GlobalKeys[item2.Substring(prefix.Length)] = present; sections[key] = section5.Value; } } } } } protected override void ParsePrimarySection(Section creatureSection) { string key = creatureSection.dictKey.ToLower(); if (!configs.TryGetValue(key, out var value)) { value = (configs[key] = new CreatureConfig()); } SortedDictionary<CreatureFilter, Section> sections = getSections(creatureSection); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.worldLevelToStars, sections, "stars"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.worldLevelToLootAmount, sections, "loot"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.worldLevelToLootPerStar, sections, "loot per star"); AssignCreatureMode(base.ParseScalarFromObject, value.sizeScalingFactor, sections, "size"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.baseHealth, sections, "health"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.healthGainPerStar, sections, "health per star"); AssignCreatureMode(base.ParseEnumConfig, value.baseDamage, sections, "damage"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.damageGainPerStar, sections, "damage per star"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.baseAttackSpeed, sections, "attack speed"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.attackSpeedGainPerStar, sections, "attack speed per star"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.baseMovementSpeed, sections, "movement speed"); AssignCreatureMode(base.ParseWorldlevelToSingleScalar, value.movementSpeedGainPerStar, sections, "movement speed per star"); AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToDamageTakenModifier, sections, "damage taken"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.spawnAmount, sections, "amount"); AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToCreatureEffect, sections, "effect"); AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToCreatureEffectFactor, sections, "effect power"); ParseEnumConfig(ref value.worldLevelToBoss, creatureSection, "affix"); ParseEnumConfig(ref value.worldLevelToBossAffixFactor, creatureSection, "affix power"); AssignCreatureMode(base.ParseEnumConfig, value.worldLevelToInfusion, sections, "infusion"); using Section section = base.section(creatureSection, "sector"); if (section != null) { SortedDictionary<CreatureFilter, Section> sections2 = getSections(section); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.sectorCount, sections2, "count"); AssignCreatureMode(base.ParseWorldlevelToFloatMap, value.sectorStars, sections2, "stars"); } sections.Remove(default(CreatureFilter)); foreach (Section value2 in sections.Values) { value2.Dispose(); } } private static void AssignCreatureMode<[<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] T>(ParserDelegate<T> parser, SortedDictionary<CreatureFilter, T> target, SortedDictionary<CreatureFilter, Section> sections, string key) { foreach (KeyValuePair<CreatureFilter, Section> section in sections) { target.TryGetValue(default(CreatureFilter), out var value); if (parser(ref value, section.Value, key)) { target[section.Key] = value; } } } protected override void Verify() { foreach (KeyValuePair<string, CreatureConfig> config in configs) { KeyValuePair<string, CreatureConfig> configKv = config; foreach (KeyValuePair<CreatureFilter, Dictionary<int, float[]>> worldLevelToStar in configKv.Value.worldLevelToStars) { float[] array = null; foreach (KeyValuePair<int, float[]> item in worldLevelToStar.Value) { float[] value = item.Value; if (value != null && value.Sum() > 100.0001f && (array == null || !array.SequenceEqual(item.Value))) { array = item.Value; configWarnings.Add(string.Format("{0}{1} has a sum of probabilities greater than 100% for its 'stars' setting at world level {2}. Note that the sum of probabilites for individual star levels MUST be equal or lower than 100%, otherwise probabilities exceeding 100% will be ignored.\nWith the current configuration this group would have the following base probabilities: {3}.", configKv.Key, worldLevelToStar.Key.Equals(default(CreatureFilter)) ? "" : $" in {worldLevelToStar.Key} mode", item.Key, string.Join(", ", API.zeroProbabilities(item.Value).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (float p, int i) => $"{i} stars: {p}%")))); } } } checkEffectProbabilities<CreatureExtraEffect>(configKv.Value.worldLevelToCreatureEffect, CreatureLevelControl.customCreatureAffixChances, "creature special effect"); checkEffectProbabilities<CreatureInfusion>(configKv.Value.worldLevelToInfusion, CreatureLevelControl.customCreatureInfusionChances, "creature infusion"); SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<BossAffix, float[]>>> sortedDictionary = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<BossAffix, float[]>>>(); if (configKv.Value.worldLevelToBoss != null) { sortedDictionary[default(CreatureFilter)] = configKv.Value.worldLevelToBoss; } checkEffectProbabilities<BossAffix>(sortedDictionary, CreatureLevelControl.customBossAffixChances, "boss affix"); void checkEffectProbabilities<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 0, 2 })] SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<T, float[]>>> dict, [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0, 1 })] Dictionary<T, ConfigEntry<float>> defaultsDict, string nameString) where T : struct, IConvertible { foreach (KeyValuePair<CreatureFilter, Dictionary<int, Dictionary<T, float[]>>> item2 in dict) { Dictionary<T, float> dictionary = null; foreach (KeyValuePair<int, Dictionary<T, float[]>> item3 in item2.Value) { int num = item3.Value.Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<T, float[]> v) => (v.Value ?? new float[1]).Length).DefaultIfEmpty(1).Max(); for (int j = 0; j < num; j++) { bool flag = false; Dictionary<T, float> dictionary2 = new Dictionary<T, float>(); Dictionary<T, float> dictionary3 = new Dictionary<T, float>(); foreach (T item4 in ((T[])Enum.GetValues(typeof(T))).Where([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (T e) => e.ToInt32(CultureInfo.InvariantCulture) != 0)) { float num3; if (item3.Value.TryGetValue(item4, out var value2) && value2 != null && value2.Length != 0) { num3 = (dictionary3[item4] = value2[(j < value2.Length) ? j : (value2.Length - 1)]); } else { num3 = defaultsDict[item4].Value; if (num3 > 0f) { flag = true; } } dictionary2[item4] = num3; } if (dictionary2.Values.Sum() > 101.1f && Mathf.Abs(dictionary3.Values.Sum() - 100f) > 1.1f && (dictionary == null || !dictionary.SequenceEqual(dictionary2))) { bool flag2 = dictionary3.Values.Sum() < 100f; dictionary = dictionary2; configWarnings.Add(string.Format("{0}{1} has a sum of {2} chances greater than 100% for {3} stars at world level {4}{5}. Some effects may not happen at all with the current configuration. Specified chances are: {6}.", configKv.Key, item2.Key.Equals(default(CreatureFilter)) ? "" : $" in configuration {item2.Key}", nameString, j, item3.Key, (flag && flag2) ? " (including default probabilities from config)" : "", string.Join(", ", (flag2 ? dictionary2 : dictionary3).Select([<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] (KeyValuePair<T, float> kv) => $"{kv.Key}: {kv.Value}%")))); } } } } } } } } [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] public class Loader : global::CreatureLevelControl.ConfigFile.Loader { [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(2)] public global::CreatureLevelControl.ConfigFile ConfigFile { [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)] get { return CreatureLevelControl.creatureConfigFile; } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(2)] set { CreatureLevelControl.creatureConfigFile = (ConfigFile)value; } } public string FilePattern => "CreatureConfig*.yml"; public string EditButtonName => LocalizationWrapper.getTranslation("Edit Creature YAML config"); public CustomSyncedValue<List<string>> FileData => CreatureLevelControl.creatureConfigFileData; public bool Enabled => CreatureLevelControl.creatureConfigFileActive.GetToggle(); public global::CreatureLevelControl.ConfigFile InstantiateConfig() { return new ConfigFile(); } public void ProcessConfig() { CreatureLevelControl.PrefabConfig = CreatureLevelControl.creatureConfigFile.Process(); } } private const int BiomeOffset = 5; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> worldLevelToStars = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>> worldLevelToCreatureEffect = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>> worldLevelToCreatureEffectFactor = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureExtraEffect, float[]>>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureInfusion, float[]>>> worldLevelToInfusion = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureInfusion, float[]>>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 2 })] public Dictionary<int, Dictionary<BossAffix, float[]>> worldLevelToBoss; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 2, 1, 2 })] public Dictionary<int, Dictionary<BossAffix, float[]>> worldLevelToBossAffixFactor; public readonly SortedDictionary<CreatureFilter, float> sizeScalingFactor = new SortedDictionary<CreatureFilter, float>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> baseHealth = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> healthGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>> baseDamage = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> damageGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> baseMovementSpeed = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> movementSpeedGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> baseAttackSpeed = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> attackSpeedGainPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> spawnAmount = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> sectorCount = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> sectorStars = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>> worldLevelToDamageTakenModifier = new SortedDictionary<CreatureFilter, Dictionary<int, Dictionary<CreatureLevelControl.ModifyDamage, float[]>>>(); [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 1, 2 })] public readonly SortedDictionary<CreatureFilter, Dictionary<int, float[]>> worldLevelToLootAmount = new SortedDictionary<CreatureFilter, Dictionary<int, float[]>>(); public readonly SortedDictionary<CreatureFilter, Dictionary<int, float?>> worldLevelToLootPerStar = new SortedDictionary<CreatureFilter, Dictionary<int, float?>>(); private static Biome[] knownBiomes => ((Biome[])Enum.GetValues(typeof(Biome))).Where((Biome b) => (int)b > 0).ToArray(); private static CreatureMode[] modePriorities { get { CreatureMode[] obj = new CreatureMode[5] { CreatureMode.Override, CreatureMode.Tamed, CreatureMode.Dungeon, CreatureMode.Default, CreatureMode.Day | CreatureMode.Night }; obj[3] = knownBiomes.Aggregate(CreatureMode.Default, (CreatureMode a, Biome m) => a | biomeToCreatureMode(m)); return obj; } } public static CreatureMode biomeToCreatureMode(Biome biome) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Expected I4, but got Unknown return (CreatureMode)(biome << 5); } } [BepInPlugin("org.bepinex.plugins.creaturelevelcontrol", "Creature Level & Loot Control", "4.6.4")] [BepInIncompatibility("org.bepinex.plugins.valheim_plus")] [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)] [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class CreatureLevelControl : BaseUnityPlugin { [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] public enum Difficulty { [LocalizationWrapper.Localized(Difficulty.Custom)] Custom, [LocalizationWrapper.Localized(Difficulty.Very_easy)] Very_easy, [LocalizationWrapper.Localized(Difficulty.Easy)] Easy, [LocalizationWrapper.Localized(Difficulty.Medium)] Medium, [LocalizationWrapper.Localized(Difficulty.Hard)] Hard, [LocalizationWrapper.Localized(Difficulty.Very_hard)] Very_hard, [LocalizationWrapper.Localized(Difficulty.Insane)] Insane } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] public enum CreatureSectorAnnouncementScope { [LocalizationWrapper.Localized(CreatureSectorAnnouncementScope.Local)] Local, [LocalizationWrapper.Localized(CreatureSectorAnnouncementScope.Global)] Global, [LocalizationWrapper.Localized(CreatureSectorAnnouncementScope.Off)] Off } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] public enum LootSystem { [LocalizationWrapper.Localized(LootSystem.Vanilla)] Vanilla, [LocalizationWrapper.Localized(LootSystem.Linear)] Linear, [LocalizationWrapper.Localized(LootSystem.CalculateChance)] CalculateChance, [LocalizationWrapper.Localized(LootSystem.CalculateAmount)] CalculateAmount } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] private enum VisualLevelIndicator { [LocalizationWrapper.Localized(VisualLevelIndicator.Off)] Off, [LocalizationWrapper.Localized(VisualLevelIndicator.On)] On, [LocalizationWrapper.Localized(VisualLevelIndicator.BossesOff)] BossesOff, [LocalizationWrapper.Localized(VisualLevelIndicator.CreaturesOff)] CreaturesOff } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] private enum AllowedConsoleCommands { [LocalizationWrapper.Localized(AllowedConsoleCommands.CreatureCommands)] CreatureCommands, [LocalizationWrapper.Localized(AllowedConsoleCommands.InformationCommands)] InformationCommands, [LocalizationWrapper.Localized(AllowedConsoleCommands.None)] None } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] private enum VisualExtraEffectIndicator { [LocalizationWrapper.Localized(VisualExtraEffectIndicator.Color)] Color, [LocalizationWrapper.Localized(VisualExtraEffectIndicator.Text)] Text, [LocalizationWrapper.Localized(VisualExtraEffectIndicator.Both)] Both } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] public enum DifficultySecondFactor { [LocalizationWrapper.Localized(DifficultySecondFactor.None)] None, [LocalizationWrapper.Localized(DifficultySecondFactor.Age_of_world)] Age_of_world, [LocalizationWrapper.Localized(DifficultySecondFactor.Distance)] Distance, [LocalizationWrapper.Localized(DifficultySecondFactor.BossesKilled)] BossesKilled } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] public enum SpawnLevel { [LocalizationWrapper.Localized(SpawnLevel.None)] None, [LocalizationWrapper.Localized(SpawnLevel.One)] One, [LocalizationWrapper.Localized(SpawnLevel.Two)] Two, [LocalizationWrapper.Localized(SpawnLevel.Three)] Three, [LocalizationWrapper.Localized(SpawnLevel.Four)] Four, [LocalizationWrapper.Localized(SpawnLevel.Five)] Five } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] public enum CreatureSectorWorldLevel { [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Disabled)] Disabled = -1, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.None)] None, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.One)] One, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Two)] Two, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Three)] Three, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Four)] Four, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Five)] Five, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Six)] Six, [LocalizationWrapper.Localized(CreatureSectorWorldLevel.Seven)] Seven } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] public enum ModifyDamage { All, Fire, Frost, Poison, Lightning, Spirit, Elemental, Blunt, Slash, Pierce, Chop, Physical, Knives, Bows, Crossbows, ElementalMagic, BloodMagic, Swords, Spears, Pickaxes, Axes, Clubs, Polearms, Weapons, Unarmed } [HarmonyPatch(typeof(Game), "GetPlayerDifficulty")] [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] private class PatchPlayerCount { [UsedImplicitly] private static void Postfix(ref int __result) { __result = Mathf.Min(maximumMultiplayerPlayerCount.Value, Mathf.Max(minimumMultiplayerPlayerCount.Value, additionalMultiplayerPlayerCount.Value + __result)); } } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] [HarmonyPatch(typeof(Terminal), "TryRunCommand")] private class PatchTerminal { [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)] [UsedImplicitly] private static bool Prefix(Terminal __instance, string text) { //IL_04a1: Unknown result type (might be due to invalid IL or missing references) //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) if (!text.ToLower().StartsWith("cllc")) { return true; } bool flag = true; string[] array = text.ToLower().Split(new char[1] { ' ' }); bool flag2 = !configSync.IsLocked; bool flag3 = false; if (array.Length > 1 && array[1] == "killhighstars") { flag = false; if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands) { if (array.Length <= 2 || !int.TryParse(array[2], out var result)) { result = 6; } Character[] array2 = Object.FindObjectsOfType<Character>(); foreach (Character val in array2) { if (val.IsPlayer() || val.GetLevel() - 1 < result) { continue; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if (component != null) { ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.SetOwner(ZDOMan.instance.m_sessionID); } } Object.Destroy((Object)(object)((Component)val).GetComponent<CharacterDrop>()); ZNetScene.instance.Destroy(((Component)val).gameObject); } __instance.AddString("Removed all nearby creatures with at least " + result + " stars"); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "killall") { flag = false; if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands) { Character[] array2 = Object.FindObjectsOfType<Character>(); foreach (Character val2 in array2) { if (val2.IsPlayer()) { continue; } ZNetView component2 = ((Component)val2).GetComponent<ZNetView>(); if (component2 != null) { ZDO zDO2 = component2.GetZDO(); if (zDO2 != null) { zDO2.SetOwner(ZDOMan.instance.m_sessionID); } } Object.Destroy((Object)(object)((Component)val2).GetComponent<CharacterDrop>()); ZNetScene.instance.Destroy(((Component)val2).gameObject); } __instance.AddString("Removed all nearby creatures"); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "worldlevel") { flag = false; if (flag2 || allowedConsoleCommands.Value != AllowedConsoleCommands.None) { __instance.AddString("Current world level: " + API.GetWorldLevel()); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "sectorkills") { flag = false; if (flag2 || allowedConsoleCommands.Value != AllowedConsoleCommands.None) { __instance.AddString("Kills in the current sector: " + (CreatureSector.currentSector(((Component)Player.m_localPlayer).GetComponent<ZNetView>())?.sectorKills ?? 0f)); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "resetsector") { flag = false; if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands) { CreatureSector.resetSectorKills(((Component)Player.m_localPlayer).GetComponent<ZNetView>()); __instance.AddString("Reset all nearby creature sectors"); } else { flag3 = true; } } else if (array.Length > 1 && array[1] == "starchance") { flag = false; if (flag2 || allowedConsoleCommands.Value != AllowedConsoleCommands.None) { object obj; if (array.Length <= 2) { obj = null; } else { GameObject prefab = ZNetScene.instance.GetPrefab(text.Split(new char[1] { ' ' })[2]); obj = ((prefab != null) ? prefab.GetComponent<Character>() : null); } Character val3 = (Character)obj; int num = 0; __instance.AddString("Current star chances" + ((val3 == null) ? "" : (" for " + Localization.instance.Localize(val3.m_name))) + ":"); float[] array3 = API.LevelProbabilities(val3, API.GetWorldLevel(), includeZoneBonusLevel: true); foreach (float num2 in array3) { __instance.AddString(num++ + " star: " + num2.ToString(CultureInfo.InvariantCulture) + "%"); } } else { flag3 = true; } } else if (array.Length > 2 && array[1] == "spawn") { flag = false; if (flag2 || allowedConsoleCommands.Value == AllowedConsoleCommands.CreatureCommands) { string text2 = text.Split(new char[1] { ' ' })[2]; GameObject prefab2 = ZNetScene.instance.GetPrefab(text2); if ((Object)(object)prefab2 == (Object)null || !Object.op_Implicit((Object)(object)prefab2.GetComponent<Character>())) { __instance.AddString(text2 + " is not a creature"); return false; } ((Character)Player.m_localPlayer).Message((MessageType)1, "Spawning object " + ((Object)prefab2).name, 0, (Sprite)null); Transform transform = ((Component)Player.m_localPlayer).transform; Character character = Object.Instantiate<GameObject>(prefab2, transform.position + transform.forward * 2f + Vector3.up, Quaternion.identity).GetComponent<Character>(); foreach (string item in array.Skip(3)) { string effectName = item; if (int.TryParse(effectName, out var result2)) { character.SetLevel(result2); continue; } bool matched = false; if (character.IsBoss()) { loop<BossAffix>(delegate(BossAffix affix) { API.SetAffixBoss(character, affix); }); } else { loop<CreatureInfusion>(delegate(CreatureInfusion infusion) { API.SetInfusionCreature(character, infusion); }); loop<CreatureExtraEffect>(delegate(CreatureExtraEffect effect) { API.SetExtraEffectCreature(character, effect); }); } if (!matched) { __instance.AddString("Unknown effect " + effectName); } void loop<T>([<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 1, 0 })] Action<T> apply) { T[] array4 = (T[])Enum.GetValues(typeof(T)); for (int j = 0; j < array4.Length; j++) { T obj2 = array4[j]; if (string.Equals(obj2.ToString(), effectName, StringComparison.CurrentCultureIgnoreCase)) { apply(obj2); matched = true; } } } } } else { flag3 = true; } } if (flag) { __instance.AddString("CLLC console commands - use 'cllc' followed by one of the following options"); __instance.AddString("killhighstars [stars] - removes all nearby creatures with at least stars. Default stars is 6."); __instance.AddString("killall - removes all nearby creatures"); __instance.AddString("worldlevel - displays the current world level"); __instance.AddString("sectorkills - displays the creatures killed in the current sector"); __instance.AddString("resetsector - resets all nearby creature sectors"); __instance.AddString("starchance [creature] - displays the current star chances. Optionally for a specific creature."); __instance.AddString("spawn [creature] [level] [affix] [extraeffect] [infusion] - spawns a creature with the provided properties."); } if (flag3) { __instance.AddString("You are not allowed to use this command on this server."); } return false; } } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] [HarmonyPatch(typeof(Game), "GetDifficultyDamageScalePlayer")] private class PatchDamageFactor { [UsedImplicitly] private static void Postfix(ref float __result) { __result = (float)((double)(__result - 1f) / 0.04 * (double)multiplayerDMGfactor.Value / 100.0) + 1f; } } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] [HarmonyPatch(typeof(Game), "GetDifficultyDamageScaleEnemy")] private class PatchHealthFactor { [UsedImplicitly] private static void Postfix(ref float __result) { __result = 1f / ((float)((double)(1f / __result - 1f) / 0.4 * (double)multiplayerHPfactor.Value / 100.0) + 1f); } } [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(0)] [HarmonyPatch(typeof(Attack), "GetLevelDamageFactor")] private class PatchDamageStarFactor { [UsedImplicitly] [<a56b5d22-7ddd-46b2-a7eb-83a6facc76b7>NullableContext(1)] private static void Postfix(Attack __instance, ref float __result) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!((Character)(Humanoid)AccessTools.DeclaredField(typeof(Attack), "m_character").GetValue(__instance)).IsPlayer()) { __result = 1f; } } } [HarmonyPatch(typeof(Character), "SetupMaxHealth")] [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] private class PatchHealthStarFactor { [CompilerGenerated] private sealed class <Transpiler>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 0, 1 })] private IEnumerable<CodeInstruction> instructions; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 0, 1 })] public IEnumerable<CodeInstruction> <>3__instructions; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(new byte[] { 0, 1 })] private IEnumerator<CodeInstruction> <>7__wrap1; [<75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] private CodeInstruction <instruction>5__3; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 2u) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <instruction>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; if (<instruction>5__3.opcode == OpCodes.Conv_R4) { <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 2; return true; } goto IL_00df; case 2: <>1__state = -3; <>2__current = new CodeInstruction(OpCodes.Call, (object)HealthFactorApplier); <>1__state = 3; return true; case 3: { <>1__state = -3; goto IL_00df; } IL_00df: <instruction>5__3 = null; break; } if (<>7__wrap1.MoveNext()) { <instruction>5__3 = <>7__wrap1.Current; <>2__current = <instruction>5__3; <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 != null) { <>7__wrap1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__2 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__2(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] [return: <75b8e597-2006-46dc-8007-b4ba3b036dbf>Nullable(0)] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private static readonly MethodInfo HealthFactorApplier = AccessTools.DeclaredMethod(typeof(PatchHealthStarFactor), "applyHealthFactor", (Type[])null, (Type[])null); private static float applyHealthFactor(float level, Character character) { int usedStars; float num = Utils.ReadWithWorldLevelAndStarsFromConfig