using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using SimpleJson; using Splatform; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using ValheimFortress.Challenge; using ValheimFortress.Common; using ValheimFortress.Data; using ValheimFortress.Defenses; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ValheimFortress")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ValheimFortress")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.0")] namespace ValheimFortress { public static class API { private static readonly Type APIReceiver; private static readonly MethodInfo RunChallengeMethod; private static readonly MethodInfo GetSpawnableCreaturesMethod; private static readonly MethodInfo GetRewardItemsMethod; private static readonly MethodInfo GetWaveStylesMethod; private static readonly DataContractJsonSerializerSettings SerializerSettings; public static bool IsAvailable => APIReceiver != null; static API() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown SerializerSettings = new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true }; APIReceiver = Type.GetType("ValheimFortress.APIReceiver, ValheimFortress"); if (!(APIReceiver == null)) { RunChallengeMethod = APIReceiver.GetMethod("RunChallenge", BindingFlags.Static | BindingFlags.Public); GetSpawnableCreaturesMethod = APIReceiver.GetMethod("GetSpawnableCreatures", BindingFlags.Static | BindingFlags.Public); GetRewardItemsMethod = APIReceiver.GetMethod("GetRewardItems", BindingFlags.Static | BindingFlags.Public); GetWaveStylesMethod = APIReceiver.GetMethod("GetWaveStyles", BindingFlags.Static | BindingFlags.Public); } } public static bool RunChallenge(VFChallengeDefinition definition, Vector3[] spawnPoints, Vector3 rewardLocation) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (RunChallengeMethod == null || definition == null) { return false; } string text = Serialize(definition); if (text == null) { return false; } object obj = RunChallengeMethod.Invoke(null, new object[3] { text, spawnPoints, rewardLocation }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } public static bool RunChallenge(VFChallengeDefinition definition, List spawnPoints, Vector3 rewardLocation) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) return RunChallenge(definition, spawnPoints?.ToArray(), rewardLocation); } public static List GetSpawnableCreatures() { if (GetSpawnableCreaturesMethod == null) { return new List(); } return (List)GetSpawnableCreaturesMethod.Invoke(null, null); } public static List GetRewardItems() { if (GetRewardItemsMethod == null) { return new List(); } return (List)GetRewardItemsMethod.Invoke(null, null); } public static List GetWaveStyles() { if (GetWaveStylesMethod == null) { return new List(); } return (List)GetWaveStylesMethod.Invoke(null, null); } private static string Serialize(VFChallengeDefinition definition) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) try { using MemoryStream memoryStream = new MemoryStream(); ((XmlObjectSerializer)new DataContractJsonSerializer(typeof(VFChallengeDefinition), SerializerSettings)).WriteObject((Stream)memoryStream, (object)definition); return Encoding.UTF8.GetString(memoryStream.ToArray()); } catch { return null; } } } [DataContract] public class VFChallengeDefinition { public const int CurrentSchemaVersion = 1; [DataMember] public int SchemaVersion { get; set; } = 1; [DataMember(EmitDefaultValue = false, IsRequired = false)] public Biome Biome { get; set; } = (Biome)1; [DataMember(EmitDefaultValue = false, IsRequired = false)] public short Difficulty { get; set; } = 1; [DataMember(EmitDefaultValue = false, IsRequired = false)] public string WaveStyle { get; set; } = "Normal"; [DataMember(EmitDefaultValue = false, IsRequired = false)] public short NumPhases { get; set; } = 4; [DataMember(EmitDefaultValue = false, IsRequired = false)] public short MaxCreaturesPerPhase { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public List OnlySelectMonsters { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public List ExcludeSelectMonsters { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public bool HardMode { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public bool BossMode { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public bool SiegeMode { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public bool EnableCreatureDrops { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public Dictionary CreatureDropOverrides { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public List> ExplicitPhases { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public Dictionary ScaledRewards { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public Dictionary FixedRewards { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public string WaveStartMessage { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public string WaveEndMessage { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public List BetweenWavePhrases { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public bool OrderedPhrases { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public bool DrawMapOverlay { get; set; } } [DataContract] public class VFHoardEntry { [DataMember(EmitDefaultValue = false, IsRequired = false)] public string Creature { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public short Amount { get; set; } [DataMember(EmitDefaultValue = false, IsRequired = false)] public short Stars { get; set; } } public static class APIReceiver { private static readonly Biome[] supported_biomes; private static readonly DataContractJsonSerializerSettings SerializerSettings; public static bool RunChallenge(string definitionJson, Vector3[] spawnPoints, Vector3 rewardLocation) { //IL_0093: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNetScene.instance == (Object)null) { Logger.LogWarning((object)"VF-API: RunChallenge called with no world loaded (ZNetScene is null)."); return false; } if (spawnPoints == null || spawnPoints.Length == 0) { Logger.LogWarning((object)"VF-API: RunChallenge requires at least one spawn point."); return false; } VFChallengeDefinition vFChallengeDefinition = Deserialize(definitionJson); if (vFChallengeDefinition == null) { Logger.LogWarning((object)"VF-API: RunChallenge could not parse the supplied challenge definition."); return false; } PhasedWaveTemplate phasedWaveTemplate = BuildWaveTemplate(vFChallengeDefinition); if (phasedWaveTemplate == null || phasedWaveTemplate.hordePhases == null || phasedWaveTemplate.hordePhases.Count == 0) { Logger.LogWarning((object)"VF-API: RunChallenge produced an empty wave template; nothing to run."); return false; } GameObject prefab = PrefabManager.Instance.GetPrefab("VF_api_challenge_runner"); if ((Object)(object)prefab == (Object)null) { Logger.LogError((object)"VF-API: runner prefab 'VF_api_challenge_runner' was not found."); return false; } GameObject val = Object.Instantiate(prefab, rewardLocation, Quaternion.identity); ExternalShrine component = val.GetComponent(); if ((Object)(object)component == (Object)null) { Logger.LogError((object)"VF-API: runner prefab is missing its ExternalShrine component."); Object.Destroy((Object)(object)val); return false; } Dictionary creatureDropOverrides = BuildDropOverrides(vFChallengeDefinition.CreatureDropOverrides); component.BeginApiChallenge(phasedWaveTemplate, spawnPoints, rewardLocation, vFChallengeDefinition.ScaledRewards, vFChallengeDefinition.FixedRewards, vFChallengeDefinition.Difficulty, vFChallengeDefinition.HardMode, vFChallengeDefinition.BossMode, vFChallengeDefinition.SiegeMode, vFChallengeDefinition.EnableCreatureDrops, creatureDropOverrides, vFChallengeDefinition.WaveStartMessage, vFChallengeDefinition.WaveEndMessage, vFChallengeDefinition.DrawMapOverlay, vFChallengeDefinition.BetweenWavePhrases, vFChallengeDefinition.OrderedPhrases); Logger.LogInfo((object)$"VF-API: started challenge with {phasedWaveTemplate.hordePhases.Count} phases at {rewardLocation}."); return true; } public static List GetSpawnableCreatures() { return Monsters.SpawnableCreatures.Keys.ToList(); } public static List GetRewardItems() { return RewardsData.resourceRewards.Values.Select((RewardEntry entry) => entry.resourcePrefab).Distinct().ToList(); } public static List GetWaveStyles() { return Enum.GetNames(typeof(WaveStyles.WaveStyleName)).ToList(); } private static PhasedWaveTemplate BuildWaveTemplate(VFChallengeDefinition def) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) if (def.ExplicitPhases != null && def.ExplicitPhases.Count > 0) { return BuildExplicitTemplate(def.ExplicitPhases); } if (!supported_biomes.Contains(def.Biome)) { Logger.LogWarning((object)string.Format("VF-API: biome '{0}' is not supported for generated waves. Supported: {1}.", def.Biome, string.Join(", ", supported_biomes))); return null; } WaveStyles.WaveStyleName result = WaveStyles.WaveStyleName.Normal; if (!string.IsNullOrEmpty(def.WaveStyle) && !Enum.TryParse(def.WaveStyle, out result)) { Logger.LogWarning((object)("VF-API: unknown wave style '" + def.WaveStyle + "', defaulting to Normal.")); result = WaveStyles.WaveStyleName.Normal; } short override_max_creatures = ((def.MaxCreaturesPerPhase > 0) ? def.MaxCreaturesPerPhase : VFConfig.ChallengeShrineMaxCreaturesPerWave.Value); return Levels.generateRandomWaveWithOptions(new ChallengeLevelDefinition { levelName = "VF_API", levelIndex = def.Difficulty, numPhases = (short)((def.NumPhases > 0) ? def.NumPhases : 4), levelForShrineTypes = new Dictionary { { ShrineType.Wild, true } }, levelMenuLocalization = "", requiredGlobalKey = "NONE", biome = def.Biome, waveFormat = result, bossWaveFormat = result, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "", bossLevelWarningLocalization = "", onlySelectMonsters = def.OnlySelectMonsters, excludeSelectMonsters = def.ExcludeSelectMonsters, commonSpawnModifiers = new SpawnModifiers(), rareSpawnModifiers = new SpawnModifiers(), eliteSpawnModifiers = new SpawnModifiers(), uniqueSpawnModifiers = new SpawnModifiers() }, def.HardMode, def.BossMode, def.SiegeMode, override_max_creatures); } private static PhasedWaveTemplate BuildExplicitTemplate(List> phases) { List> list = new List>(); foreach (List phase in phases) { if (phase == null) { continue; } List list2 = new List(); foreach (VFHoardEntry item in phase) { if (item != null && !string.IsNullOrEmpty(item.Creature) && item.Amount > 0) { if (!Monsters.SpawnableCreatures.ContainsKey(item.Creature)) { Logger.LogWarning((object)("VF-API: explicit creature '" + item.Creature + "' is not a known VF creature, skipping. Use GetSpawnableCreatures() for valid names.")); continue; } list2.Add(new HoardConfig { creature = item.Creature, prefab = Monsters.SpawnableCreatures[item.Creature].prefabName, amount = item.Amount, stars = item.Stars }); } } if (list2.Count > 0) { list.Add(list2); } } if (list.Count == 0) { return null; } return new PhasedWaveTemplate { hordePhases = list }; } private static Dictionary BuildDropOverrides(Dictionary overrides) { Dictionary dictionary = new Dictionary(); if (overrides == null) { return dictionary; } foreach (KeyValuePair @override in overrides) { if (!string.IsNullOrEmpty(@override.Key)) { if (!Monsters.SpawnableCreatures.ContainsKey(@override.Key)) { Logger.LogWarning((object)("VF-API: creature drop override '" + @override.Key + "' is not a known VF creature, skipping. Use GetSpawnableCreatures() for valid names.")); } else { dictionary[@override.Key] = (@override.Value ? ((short)1) : ((short)0)); } } } return dictionary; } private static VFChallengeDefinition Deserialize(string json) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(json)) { return null; } try { using MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json)); if (!(((XmlObjectSerializer)new DataContractJsonSerializer(typeof(VFChallengeDefinition), SerializerSettings)).ReadObject((Stream)memoryStream) is VFChallengeDefinition vFChallengeDefinition)) { Logger.LogError((object)"VF-API: challenge definition deserialized to null / an unexpected type."); return null; } if (vFChallengeDefinition.SchemaVersion != 1) { Logger.LogWarning((object)($"VF-API: challenge definition schema version mismatch (received {vFChallengeDefinition.SchemaVersion}, expected {1}). " + "The calling mod's copy of API.cs is out of sync with this Valheim Fortress version; re-copy API.cs from the current release. Attempting to continue.")); } return vFChallengeDefinition; } catch (Exception arg) { Logger.LogError((object)$"VF-API: failed to deserialize challenge definition: {arg}"); return null; } } static APIReceiver() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown Biome[] array = new Biome[7]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); supported_biomes = (Biome[])(object)array; SerializerSettings = new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true }; } } internal static class Logger { public static LogLevel Level = (LogLevel)4; public static void enableDebugLogging() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (VFConfig.EnableDebugMode.Value) { Level = (LogLevel)32; } else { Level = (LogLevel)4; } } public static void toggleDebug(object s, EventArgs e) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (VFConfig.EnableDebugMode.Value) { Level = (LogLevel)32; } else { Level = (LogLevel)4; } } public static void LogDebug(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 32) { ValheimFortress.Log.LogInfo((object)message); } } public static void LogInfo(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 16) { ValheimFortress.Log.LogInfo((object)message); } } public static void LogWarning(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 4) { ValheimFortress.Log.LogWarning((object)message); } } public static void LogError(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 2) { ValheimFortress.Log.LogError((object)message); } } } internal class ValheimFortressPieces { private JotunnPieceLoader Loader = new JotunnPieceLoader(); public ValheimFortressPieces() { Logger.LogInfo("Loading Pieces."); LoadAlterOfChallenge(); LoadDefenses(); Loader.BatchSetup(ValheimFortress.EmbeddedResourceBundle); } private void LoadAlterOfChallenge() { PieceDefinition pieceDefinition = new PieceDefinition(); pieceDefinition.Name = "Alter of Challenge"; pieceDefinition.Category = PieceCategory.Misc; pieceDefinition.prefab = "VFshrine_of_challenge"; pieceDefinition.icon = "shrine_of_challenge"; pieceDefinition.enabled = true; pieceDefinition.requiredWorkstation = "piece_workbench"; pieceDefinition.recipe = new PieceCostDefinition { recipeItems = new List { new PieceIngredient { prefab = "Stone", amount = 34, refund = true }, new PieceIngredient { prefab = "Ruby", amount = 4, refund = true }, new PieceIngredient { prefab = "Coins", amount = 100, refund = false } } }; pieceDefinition.setupScripts = delegate(GameObject go) { go.AddComponent(); go.AddComponent(); go.AddComponent(); }; Loader.AddPiece(pieceDefinition); PieceDefinition pieceDefinition2 = new PieceDefinition(); pieceDefinition2.Name = "Alter of Arena"; pieceDefinition2.Category = PieceCategory.Misc; pieceDefinition2.prefab = "VFshine_of_gladiator"; pieceDefinition2.icon = "alter_of_arena"; pieceDefinition2.enabled = true; pieceDefinition2.requiredWorkstation = "piece_workbench"; pieceDefinition2.recipe = new PieceCostDefinition { recipeItems = new List { new PieceIngredient { prefab = "Stone", amount = 23, refund = true }, new PieceIngredient { prefab = "Coins", amount = 100, refund = false } } }; pieceDefinition2.setupScripts = delegate(GameObject go) { go.AddComponent(); go.AddComponent(); go.AddComponent(); }; Loader.AddPiece(pieceDefinition2); } private void LoadDefenses() { PieceDefinition pieceDefinition = new PieceDefinition(); pieceDefinition.Name = "Stone Spikes"; pieceDefinition.Category = PieceCategory.Misc; pieceDefinition.prefab = "VFstone_stakes"; pieceDefinition.icon = "stone_spikes"; pieceDefinition.enabled = true; pieceDefinition.requiredWorkstation = "piece_stonecutter"; pieceDefinition.recipe = new PieceCostDefinition { recipeItems = new List { new PieceIngredient { prefab = "Stone", amount = 30, refund = false }, new PieceIngredient { prefab = "Silver", amount = 2, refund = true } } }; Loader.AddPiece(pieceDefinition); PieceDefinition pieceDefinition2 = new PieceDefinition(); pieceDefinition2.Name = "Auto Ballista"; pieceDefinition2.Category = PieceCategory.Misc; pieceDefinition2.prefab = "VFpiece_turret"; pieceDefinition2.icon = "modified_turret"; pieceDefinition2.enabled = true; pieceDefinition2.requiredWorkstation = "piece_artisanstation"; pieceDefinition2.recipe = new PieceCostDefinition { recipeItems = new List { new PieceIngredient { prefab = "BlackMetal", amount = 20, refund = true }, new PieceIngredient { prefab = "YggdrasilWood", amount = 20, refund = true }, new PieceIngredient { prefab = "MechanicalSpring", amount = 5, refund = true }, new PieceIngredient { prefab = "DragonTear", amount = 2, refund = true } } }; pieceDefinition2.setupScripts = delegate(GameObject go) { go.AddComponent(); }; VFConfig.BallistaDamage.SettingChanged += BallistaOnChange.BallistaDamageChange; VFConfig.BallistaRange.SettingChanged += BallistaOnChange.BallistaRange_SettingChanged; VFConfig.BallistaAmmoAccuracyPenalty.SettingChanged += BallistaOnChange.BallistaAmmoAccuracyPenalty_SettingChanged; VFConfig.BallistaCooldownTime.SettingChanged += BallistaOnChange.BallistaCooldownTime_SettingChanged; Loader.AddPiece(pieceDefinition2); } } [BepInPlugin("MidnightsFX.ValheimFortress", "ValheimFortress", "0.36.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class ValheimFortress : BaseUnityPlugin { public const string PluginGUID = "MidnightsFX.ValheimFortress"; public const string PluginName = "ValheimFortress"; public const string PluginVersion = "0.36.2"; public const string ApiChallengeRunnerPrefab = "VF_api_challenge_runner"; internal static Harmony Harmony = new Harmony("MidnightsFX.ValheimFortress"); public static AssetBundle EmbeddedResourceBundle; public VFConfig cfg; internal static CustomLocalization LocalizationInstance; public static ManualLogSource Log; public static GameObject spawnPortal; public static GameObject creatureNotifier; public static GameObject portalDestroyVFX; private static readonly Regex sWhitespace = new Regex("\\s+"); public void Awake() { cfg = new VFConfig(((BaseUnityPlugin)this).Config); Log = ((BaseUnityPlugin)this).Logger; cfg.SetupConfigRPCs(); EmbeddedResourceBundle = AssetUtils.LoadAssetBundleFromResources("ValheimFortress.AssetsEmbedded.vfbundle", typeof(ValheimFortress).Assembly); AddLocalizations(); new ValheimFortressPieces(); SetupVFXObjects(EmbeddedResourceBundle); SetupAPIRunnerPrefab(); new VFLocations(EmbeddedResourceBundle, cfg); VFConfig.GetYamlConfigFiles(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim Fortress loaded."); Assembly executingAssembly = Assembly.GetExecutingAssembly(); Harmony.PatchAll(executingAssembly); } private void AddLocalizations() { LocalizationInstance = LocalizationManager.Instance.GetLocalization(); string text = Path.Combine(Paths.ConfigPath, "VFortress", "Localizations"); Directory.CreateDirectory(text); string[] manifestResourceNames = typeof(ValheimFortress).Assembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (!text2.Contains("Localizations")) { continue; } string text3 = Regex.Replace(ReadEmbeddedResourceFile(text2), "\\/\\/.*", ""); Dictionary internal_localization = SimpleJson.DeserializeObject>(text3); string[] array = text2.Split(new char[1] { '.' }); if (File.Exists(text + "/" + array[2] + ".json")) { string text4 = File.ReadAllText(text + "/" + array[2] + ".json"); try { Dictionary dictionary = SimpleJson.DeserializeObject>(text4); UpdateLocalizationWithMissingKeys(internal_localization, dictionary); ((BaseUnityPlugin)this).Logger.LogDebug((object)("Reading " + text + "/" + array[2] + ".json")); File.WriteAllText(text + "/" + array[2] + ".json", SimpleJson.SerializeObject((object)dictionary)); string text5 = File.ReadAllText(text + "/" + array[2] + ".json"); LocalizationInstance.AddJsonFile(array[2], text5); } catch { File.WriteAllText(text + "/" + array[2] + ".json", text3); ((BaseUnityPlugin)this).Logger.LogDebug((object)("Reading " + text2)); LocalizationInstance.AddJsonFile(array[2], text3); } } else { File.WriteAllText(text + "/" + array[2] + ".json", text3); ((BaseUnityPlugin)this).Logger.LogDebug((object)("Reading " + text2)); LocalizationInstance.AddJsonFile(array[2], text3); } ((BaseUnityPlugin)this).Logger.LogDebug((object)("Added localization: '" + array[2] + "'")); } } private void UpdateLocalizationWithMissingKeys(Dictionary internal_localization, Dictionary cached_localization) { if (internal_localization.Keys.Count == cached_localization.Keys.Count) { return; } ((BaseUnityPlugin)this).Logger.LogDebug((object)"Cached localization was missing some entries. They will be added."); foreach (KeyValuePair item in internal_localization) { if (!cached_localization.ContainsKey(item.Key)) { cached_localization.Add(item.Key, item.Value); } } } internal static GameObject getPortal() { return spawnPortal; } internal static GameObject getNotifier() { return creatureNotifier; } internal static GameObject getPortalDestroyVFX() { return portalDestroyVFX; } private static void SetupVFXObjects(AssetBundle EmbeddedResourceBundle) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown CustomPrefab val = new CustomPrefab(EmbeddedResourceBundle.LoadAsset("Assets/Custom/Pieces/VFortress/VF_portal.prefab"), false); PrefabManager.Instance.AddPrefab(val); spawnPortal = val.Prefab; CustomPrefab val2 = new CustomPrefab(EmbeddedResourceBundle.LoadAsset("Assets/Custom/Pieces/VFortress/VF_portal_destroy.prefab"), false); PrefabManager.Instance.AddPrefab(val2); portalDestroyVFX = val2.Prefab; CustomPrefab val3 = new CustomPrefab(EmbeddedResourceBundle.LoadAsset("Assets/Custom/Pieces/VFortress/VF_creature_notify.prefab"), false); PrefabManager.Instance.AddPrefab(val3); creatureNotifier = val3.Prefab; } private static void SetupAPIRunnerPrefab() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown GameObject val = PrefabManager.Instance.CreateEmptyPrefab("VF_api_challenge_runner", true); if (!((Object)(object)val == (Object)null)) { MeshRenderer[] componentsInChildren = val.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } MeshFilter[] componentsInChildren2 = val.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } Collider[] componentsInChildren3 = val.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } ZNetView component = val.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_persistent = true; } val.AddComponent(); val.AddComponent(); PrefabManager.Instance.AddPrefab(new CustomPrefab(val, false)); } } public static string LocalizeOrDefault(string str_to_localize, string default_string) { string text = LocalizationInstance.TryTranslate(str_to_localize); if (text == "[" + str_to_localize.Replace("$", "") + "]") { Logger.LogDebug((object)(str_to_localize + " was not localized, returning the default: " + default_string)); return default_string; } return text; } internal static string ReadEmbeddedResourceFile(string filename) { using Stream stream = typeof(ValheimFortress).Assembly.GetManifestResourceStream(filename); using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } public static List shuffleList(List inputList) { int i = 0; int count = inputList.Count; int num = 0; string text = null; List list = new List(); list.AddRange(inputList); for (; i < count; i++) { num = Random.Range(i, list.Count); text = list[i]; list[i] = list[num]; list[num] = text; } return list; } public static string FormatJson(string json, string indent = " ") { int indentation = 0; int quoteCount = 0; int escapeCount = 0; return string.Concat((from ch in json ?? string.Empty let escaped = ((ch == '\\') ? escapeCount++ : ((escapeCount > 0) ? escapeCount-- : escapeCount)) > 0 let quotes = (ch == '"' && !escaped) ? quoteCount++ : quoteCount let unquoted = quotes % 2 == 0 let colon = (ch == ':' && unquoted) ? ": " : null let nospace = (char.IsWhiteSpace(ch) && unquoted) ? string.Empty : null let lineBreak = (ch == ',' && unquoted) ? string.Concat(ch.ToString(), Environment.NewLine, string.Concat(Enumerable.Repeat(indent, indentation))) : null let openChar = ((ch == '{' || ch == '[') && unquoted) ? string.Concat(ch.ToString(), Environment.NewLine, string.Concat(Enumerable.Repeat(indent, ++indentation))) : ch.ToString() select new { <>h__TransparentIdentifier6 = <>h__TransparentIdentifier6, closeChar = (((ch == '}' || ch == ']') && unquoted) ? string.Concat(Environment.NewLine, string.Concat(Enumerable.Repeat(indent, --indentation)), ch.ToString()) : ch.ToString()) }).Select(<>h__TransparentIdentifier7 => { string text = <>h__TransparentIdentifier7.<>h__TransparentIdentifier6.<>h__TransparentIdentifier5.<>h__TransparentIdentifier4.<>h__TransparentIdentifier3.colon; if (text == null) { text = <>h__TransparentIdentifier7.<>h__TransparentIdentifier6.<>h__TransparentIdentifier5.<>h__TransparentIdentifier4.nospace; if (text == null) { text = <>h__TransparentIdentifier7.<>h__TransparentIdentifier6.<>h__TransparentIdentifier5.lineBreak; if (text == null) { if (<>h__TransparentIdentifier7.<>h__TransparentIdentifier6.openChar.Length <= 1) { return <>h__TransparentIdentifier7.closeChar; } text = <>h__TransparentIdentifier7.<>h__TransparentIdentifier6.openChar; } } } return text; })); } public static string ReplaceWhitespace(string input, string replacement) { return sWhitespace.Replace(input, replacement); } } internal class VFConfig { public static ConfigFile cfg; public static ConfigEntry EnableDebugMode; public static ConfigEntry EnableTurretDebugMode; public static ConfigEntry BallistaTargetsPassives; public static ConfigEntry BallistaDamage; public static ConfigEntry BallistaRange; public static ConfigEntry BallistaAmmoAccuracyPenalty; public static ConfigEntry BallistaTargetUpdateCacheInterval; public static ConfigEntry BallistaEnableShotSafetyCheck; public static ConfigEntry BallistaCooldownTime; public static ConfigEntry MaxSpawnRange; public static ConfigEntry NumberOfRemoteSpawnPoints; public static ConfigEntry rewardsMultiplier; public static ConfigEntry rewardsDifficultyScalar; public static ConfigEntry EnableBossModifier; public static ConfigEntry EnableHardModifier; public static ConfigEntry EnableSiegeModifer; public static ConfigEntry EnableRewardsEstimate; public static ConfigEntry EnableMapPings; public static ConfigEntry EnableShrineMapOverlay; public static ConfigEntry MaxRewardsPerSecond; public static ConfigEntry ScaleRewardsFromWorldSetting; public static ConfigEntry NotifyCreatureThreshold; public static ConfigEntry TeleportCreatureThreshold; public static ConfigEntry ShrineReconnectPauseBetweenAmount; public static ConfigEntry ShrineStallTimeout; public static ConfigEntry ShrineAnnouncementRange; public static ConfigEntry DistanceBetweenShrines; public static ConfigEntry ShrineReconnectRange; public static ConfigEntry NumberOfEachWildShrine; public static ConfigEntry ChallengeShrineMaxCreaturesPerWave; public static ConfigEntry ArenaShrineMaxCreaturesPerWave; public static ConfigEntry ShrineRewardPlayerBonus; public static ConfigEntry ServerConfigsLocked; public static ConfigEntry BaseChallengePoints; public static ConfigEntry MaxChallengePoints; public static ConfigEntry ChallengeSlope; public static ConfigEntry ChanceOfPreviousBiomeCreature; public static ConfigEntry MaxCreatureStars; private static CustomRPC monsterSyncRPC; private static CustomRPC rewardSyncRPC; private static CustomRPC WavesSyncRPC; private static CustomRPC LevelsSyncRPC; private static CustomRPC WildShrineSyncRPC; private static string rewardFilePath = Path.Combine(Paths.ConfigPath, "VFortress", "Rewards.yaml"); private static string creatureFilePath = Path.Combine(Paths.ConfigPath, "VFortress", "SpawnableCreatures.yaml"); private static string waveStylesFilePath = Path.Combine(Paths.ConfigPath, "VFortress", "WaveStyles.yaml"); private static string levelDefinitionsFilePath = Path.Combine(Paths.ConfigPath, "VFortress", "Levels.yaml"); private static string wildShrineConfigurationFilePath = Path.Combine(Paths.ConfigPath, "VFortress", "WildShrines.yaml"); public VFConfig(ConfigFile Config) { cfg = Config; cfg.SaveOnConfigSet = true; CreateConfigValues(Config); Logger.enableDebugLogging(); string configPath = Paths.ConfigPath; FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); fileSystemWatcher.Path = configPath; fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher.Filter = "MidnightsFX.ValheimFortress.cfg"; fileSystemWatcher.Changed += UpdateMainConfigFile; fileSystemWatcher.Created += UpdateMainConfigFile; fileSystemWatcher.Renamed += UpdateMainConfigFile; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; Logger.LogInfo((object)"Main config filewatcher initialized."); } public static void SaveOnSet(bool enabled) { cfg.SaveOnConfigSet = enabled; cfg.Save(); } public void SetupConfigRPCs() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0027: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0053: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_007f: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00ab: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_00d7: Expected O, but got Unknown monsterSyncRPC = NetworkManager.Instance.AddRPC("monsteryaml_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceiveCreatureConfigs)); rewardSyncRPC = NetworkManager.Instance.AddRPC("rewardsyaml_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceiveRewardsConfigs)); WavesSyncRPC = NetworkManager.Instance.AddRPC("wavestyleyaml_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceiveWaveConfigs)); LevelsSyncRPC = NetworkManager.Instance.AddRPC("levelsyaml_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceiveLevelConfigs)); WildShrineSyncRPC = NetworkManager.Instance.AddRPC("wildshrineyaml_rpc", new CoroutineHandler(OnServerRecieveConfigs), new CoroutineHandler(OnClientReceiveWildShrineConfigs)); SynchronizationManager.Instance.AddInitialSynchronization(monsterSyncRPC, (Func)SendCreatureConfigs); SynchronizationManager.Instance.AddInitialSynchronization(rewardSyncRPC, (Func)SendRewardsConfigs); SynchronizationManager.Instance.AddInitialSynchronization(WavesSyncRPC, (Func)SendWavesConfigs); SynchronizationManager.Instance.AddInitialSynchronization(LevelsSyncRPC, (Func)SendLevelsConfigs); SynchronizationManager.Instance.AddInitialSynchronization(WildShrineSyncRPC, (Func)SendWildShrineConfigs); } public static string GetSecondaryConfigDirectoryPath() { return Directory.CreateDirectory(Path.Combine(Paths.ConfigPath, "VFortress")).FullName; } public static void GetYamlConfigFiles() { string secondaryConfigDirectoryPath = GetSecondaryConfigDirectoryPath(); bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; bool flag5 = false; string[] files = Directory.GetFiles(secondaryConfigDirectoryPath); foreach (string text in files) { Logger.LogInfo((object)("Config file found: " + text)); if (text.Contains("Rewards.yaml")) { Logger.LogInfo((object)("Found rewards configuration: " + text)); rewardFilePath = text; flag = true; } if (text.Contains("SpawnableCreatures.yaml")) { Logger.LogInfo((object)("Found Creature configuration: " + text)); creatureFilePath = text; flag2 = true; } if (text.Contains("WaveStyles.yaml")) { Logger.LogInfo((object)("Found WaveStyles configuration: " + text)); waveStylesFilePath = text; flag3 = true; } if (text.Contains("Levels.yaml")) { Logger.LogInfo((object)("Found Levels configuration: " + text)); levelDefinitionsFilePath = text; flag4 = true; } if (text.Contains("WildShrines.yaml")) { Logger.LogInfo((object)("Found WildShrine configuration: " + text)); wildShrineConfigurationFilePath = text; flag5 = true; } } if (!flag) { Logger.LogInfo((object)"Rewards file missing, recreating."); using StreamWriter streamWriter = new StreamWriter(rewardFilePath); string value = "#################################################\n# Shrine of Challenge Rewards Configuration\n#################################################\n# Rewards configurations have a number of key values\n# Coin: |- The name of the reward, this will be the diplayed name if there is no localization for this reward, which is likely the case for any custom entries.\n# enabled: true |- Whether or not the reward is enabled, you can use this to disable any vanilla rewards you do not want. At least 1 reward must be available at ALL times.\n# resourceCost: 5 |- This is the cost to gain 1 of the particular reward. Points are generated based on how many monsters are spawned.\n# resourcePrefab: \"Coins\" |- This is the unity prefab name for a resource, you will often see mods list the prefabs they have added. Prefabs are also listed on the valheim wiki.\n# requiredBoss: \"None\" |- This must be one of the following values: \"None\" \"Eikythr\" \"TheElder\" \"BoneMass\" \"Moder\" \"Yagluth\" \"TheQueen\"\n"; streamWriter.WriteLine(value); streamWriter.WriteLine(RewardsData.YamlRewardsDefinition()); } if (!flag3) { Logger.LogInfo((object)"WaveStyles file missing, recreating."); using StreamWriter streamWriter2 = new StreamWriter(waveStylesFilePath); string value2 = "#################################################\n# Shrine of Challenge WaveStyles Configuration\n#################################################\n# WaveStyles configurations have a number of key values\n# Easy: |- This is the key used to lookup this wave definition\n# WaveConfig |- The wave configuration for each segment of the wave\n# - type: COMMON |- This is the catagory of creature that will be selected\n# percent: 30 |- This is the percentage of the waves total point pool that will be used for this spawn"; streamWriter2.WriteLine(value2); streamWriter2.WriteLine(WaveStyles.YamlWaveDefinition()); } if (!flag4) { Logger.LogInfo((object)"LevelsConfig file missing, recreating."); using StreamWriter streamWriter3 = new StreamWriter(levelDefinitionsFilePath); string value3 = "#################################################\n# Shrines of Challenge Levels Configuration\n#################################################\n# levels:\n# - levelIndex: 1 |- LevelIndex is the difficulty this wave is set at, valid values are 1+\n# numPhases: 4 |- The number of phases in this level, enemies will be distributed among the phases\n# levelForShrineTypes: |- What shrines will host this level, multiple definitions can be applied\n# challenge: true |- Shrine of challenge will host this level\n# arena: true |- Shrine of the arena will host this level\n# levelMenuLocalization: $shrine_menu_meadow |- This is the localization that will be displayed when selecting the level, if no key matches the $lookup the literal string will be used\n# requiredGlobalKey: NONE |- This is the global key required to unlock this level more available here (https://valheim.fandom.com/wiki/Global_Keys)\n# biome: Meadows |- This is the biome used for this level. This determines what creatures are considered\n# waveFormat: Tutorial |- This is the format of the wave, formates are defined in WaveStyles.yaml, it determines how many creatures, what catagory and percentage of total points they use\n# bossWaveFormat: TutorialBoss |- This is the format if the wave is modified to be a boss wave\n# maxCreatureFromPreviousBiomes: 0 |- This is the maximum number of creatures that can be selected from prior biomes\n# previousBiomeSearchRange: 1 |- How many previous biomes to look back for potential creatures\n# chancePreviousBiomeCreatureSelected: 0.05 |- Chance that a creature will be selected from a previous biome, if it can be\n# previousBiomeCreaturesAddedStarPerBiome: true |- Automatically upgrades creatures from a previous biome, one star per biome difference (up to max defined stars)\n# levelWarningLocalization: $shrine_warning_meadows |- This is the announcement text that plays when the challenge starts as a normal wave, uses literal value if the localization does not exist\n# bossLevelWarningLocalization: $shrine_warning_meadows_boss |- This is the announcement text that plays when the challenge starts as a boss wave, localizations are available here https://github.com/MidnightsFX/Valheim_Fortress/blob/master/JotunnModStub/Localizations/English.json\n# onlySelectMonsters: [] |- This is an array of monsters that are the only valid targets for this wave\n# excludeSelectMonsters: [] |- This is an array of monsters that are to be avoided for the wave\n# levelRewardOptionsLimitedTo: |- When set, only the available rewards can be selected for this level, rewards still have their normal global key requirements\n# - Coin |- The rewards entry name of rewards that should be available for this level\n# commonSpawnModifiers: |- Spawn modifiers are functions applied to each part of the wave, they can be different per catagory of monster\n# linearIncreaseRandomWaveAdjustment: true |- In general, it is best to only use one type of spawn modifier per creature type\n# linearDecreaseRandomWaveAdjustment: false |- Linear Decrease/Increase will frontload or backload this creature in the various phase of the wave, meaning more of it will appear earlier or later depending on the modifier\n# partialRandomWaveAdjustment: false |- Partial random adjustment will add more significant random variance to the number of creatures that will spawn\n# onlyGenerateInSecondHalf: false |- Only generate in second half will prevent this type of creature from spawning in the earlier waves, this is useful for Elites/Rares when LinearDecrease is set for commons\n# rareSpawnModifiers: |- The start of the wave will have many commons, and they will taper off till the end, while elites would come into play only on the second half of the wave\n# linearIncreaseRandomWaveAdjustment: true\n# linearDecreaseRandomWaveAdjustment: false\n# partialRandomWaveAdjustment: false\n# onlyGenerateInSecondHalf: false\n# eliteSpawnModifiers:\n# linearIncreaseRandomWaveAdjustment: true\n# linearDecreaseRandomWaveAdjustment: false\n# partialRandomWaveAdjustment: false\n# onlyGenerateInSecondHalf: false\n# uniqueSpawnModifiers: "; streamWriter3.WriteLine(value3); streamWriter3.WriteLine(ChallengeLevels.YamlLevelsDefinition()); } if (!flag2) { Logger.LogInfo((object)"CreatureConfig file missing, recreating."); using StreamWriter streamWriter4 = new StreamWriter(creatureFilePath); string value4 = "#################################################\n# Shrine of Challenge Creature Configuration\n#################################################\n# Creature configurations have a number of key values\n# Neck: |- This is the name of the creature being added, it is primarily used for display purposes and lookups\n# spawnCost: 5 |- This is how many points from the wave pool it costs to spawn one creature, smaller values allow many more spawns.\n# prefab: \"Neck\" |- This is the creatures prefab, which will be used to spawn it.\n# spawnType: \"common\" |- This can either be: \"common\" or \"rare\" or \"elite\" or \"unique\", uniques are \"bosses\", most of the wave will be made up of more common enemies\n# enabled: true |- This controls if this creature will be included in wave-generation.\n# dropsEnabled: false |- This controls if this particular monster should drop loot. Disabled by default for everything.\n# biome: \"Meadows\" |- This must be one of the following values: \"Meadows\", \"BlackForest\", \"Swamp\", \"Mountain\", \"Plains\", \"Mistlands\". The biome determines the levels that will recieve this spawn, and how the spawn might be adjusted to\n# fit higher difficulty waves. eg: a greydwarf spawning into a swamp level wave will recieve 1 bonus star, since it is from the black forest, which is 1 biome behind the swamp."; streamWriter4.WriteLine(value4); streamWriter4.WriteLine(Monsters.YamlCreatureDefinition()); } if (!flag5) { Logger.LogInfo((object)"WildShrineConfig file missing, recreating."); using StreamWriter streamWriter5 = new StreamWriter(wildShrineConfigurationFilePath); string value5 = "###################################################################################################################################################\n# Wild Shrine Configuration\n###################################################################################################################################################\n# wildShrines:\n# - definitionForWildShrine: VF_wild_shrine_green1 |- The prefab that this set of configuration will be applied to\n# wildShrineNameLocalization: $wild_shrine_green |- The localization for the prefabs name (when hovered over) this uses a lookup value but defaults to its literal value\n# wildShrineRequestLocalization: $wild_shrine_green_request |- What the shrine says when you interact with it\n# shrineUnacceptedTributeLocalization: $wild_shrine_not_interested |- What the shrine says when you offer an incorrect tribute\n# shrineLargerTributeRequiredLocalization: $wild_shrine_hungry |- What the shrine says when you do not offer enough tribute\n# wildShrineLevelsConfig: |- Level configurations related to this shrine\n# - tributeName: TrophyBoar |- The prefab name of the tribute required to activate this level\n# tributeAmount: 4 |- Amount of the tribute required to activate this level\n# rewards: |- Rewards for this level in the format of Prefab: cost eg: RawMeat: 14.\n# LeatherScraps: 14\n# RawMeat: 12\n# hardMode: false |- If hardmode should be enabled for this level (doubles the spawn point pool and gives 50% more rewards)\n# siegeMode: false |- If siege mode should be enabled for this level (double the number of waves 4->8 and gives 50% more rewards)\n# wildshrineWaveStartLocalization: $wild_boars_attack |- Localization text to display when this wave starts\n# wildshrineWaveEndLocalization: $wild_boars_defeated |- Localization text to display when this wave is finished\n# wildLevelDefinition:\n# levelIndex: 2 |- The difficulty level for this wave, valid values are 1+ (Refer to the readme for a breakdown of this equation)\n# biome: Meadows |- The biome this wave is for, this impacts creature selection\n# waveFormat: Tutorial |- The wavestyle this uses (from wavestyles.yml), this governs which catagories and the percentage makeup of the wave\n# levelWarningLocalization: $meadows_warning_wilderness |- Localization for a between phase warning (often not used)\n# maxCreaturesPerPhaseOverride: 15 |- Overrides the max creatures per wave to be this value (overrides the global config)\n# onlySelectMonsters: |- Set of monsters that can be selected (From monsters.yml)\n# - Boar\n# - Greyling\n# excludeSelectMonsters: |- Set of monsters that can't be selected (from monsters.yml) best used when OnlySelected is not set.\n# commonSpawnModifiers: |- Spawn modifiers for common creatures\n# linearIncreaseRandomWaveAdjustment: true\n# rareSpawnModifiers: |- Spawn modifiers for rare creatures\n# eliteSpawnModifiers: |- Spawn modifiers for elite creatures\n"; streamWriter5.WriteLine(value5); streamWriter5.WriteLine(WildShrineData.YamlWildShrineDefinition()); } string text2 = File.ReadAllText(creatureFilePath); string text3 = File.ReadAllText(rewardFilePath); string text4 = File.ReadAllText(waveStylesFilePath); string text5 = File.ReadAllText(levelDefinitionsFilePath); string text6 = File.ReadAllText(wildShrineConfigurationFilePath); try { WaveStyles.UpdateWaveDefinition(CONST.yamldeserializer.Deserialize(text4)); } catch (Exception arg) { Logger.LogWarning((object)$"There was an error updating the waveStyle values, defaults will be used. Exception: {arg}"); } try { Monsters.UpdateSpawnableCreatures(CONST.yamldeserializer.Deserialize(text2)); } catch (Exception arg2) { Logger.LogWarning((object)$"There was an error updating the creature values, defaults will be used. Exception: {arg2}"); } try { RewardsData.UpdateRewardsEntries(CONST.yamldeserializer.Deserialize(text3)); } catch (Exception arg3) { Logger.LogWarning((object)$"There was an error updating the rewards values, defaults will be used. Exception: {arg3}"); } try { ChallengeLevels.UpdateLevelsDefinition(CONST.yamldeserializer.Deserialize(text5)); } catch (Exception arg4) { Logger.LogWarning((object)$"There was an error updating the levelDefinitions values, defaults will be used. Exception: {arg4}"); } try { WildShrineData.UpdateWildShrineDefinition(CONST.yamldeserializer.Deserialize(text6)); } catch (Exception arg5) { Logger.LogWarning((object)$"There was an error updating the WildShrine values, defaults will be used. Exception: {arg5}"); } FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); fileSystemWatcher.Path = secondaryConfigDirectoryPath; fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher.Filter = "Levels.yaml"; fileSystemWatcher.Changed += UpdateLevelsConfigFileOnChange; fileSystemWatcher.Created += UpdateLevelsConfigFileOnChange; fileSystemWatcher.Renamed += UpdateLevelsConfigFileOnChange; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; FileSystemWatcher fileSystemWatcher2 = new FileSystemWatcher(); fileSystemWatcher2.Path = secondaryConfigDirectoryPath; fileSystemWatcher2.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher2.Filter = "WaveStyles.yaml"; fileSystemWatcher2.Changed += UpdateWavesConfigFileOnChange; fileSystemWatcher2.Created += UpdateWavesConfigFileOnChange; fileSystemWatcher2.Renamed += UpdateWavesConfigFileOnChange; fileSystemWatcher2.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher2.EnableRaisingEvents = true; FileSystemWatcher fileSystemWatcher3 = new FileSystemWatcher(); fileSystemWatcher3.Path = secondaryConfigDirectoryPath; fileSystemWatcher3.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher3.Filter = "SpawnableCreatures.yaml"; fileSystemWatcher3.Changed += UpdateCreatureConfigFileOnChange; fileSystemWatcher3.Created += UpdateCreatureConfigFileOnChange; fileSystemWatcher3.Renamed += UpdateCreatureConfigFileOnChange; fileSystemWatcher3.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher3.EnableRaisingEvents = true; FileSystemWatcher fileSystemWatcher4 = new FileSystemWatcher(); fileSystemWatcher4.Path = secondaryConfigDirectoryPath; fileSystemWatcher4.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher4.Filter = "Rewards.yaml"; fileSystemWatcher4.Changed += UpdateRewardsConfigFileOnChange; fileSystemWatcher4.Created += UpdateRewardsConfigFileOnChange; fileSystemWatcher4.Renamed += UpdateRewardsConfigFileOnChange; fileSystemWatcher4.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher4.EnableRaisingEvents = true; FileSystemWatcher fileSystemWatcher5 = new FileSystemWatcher(); fileSystemWatcher5.Path = secondaryConfigDirectoryPath; fileSystemWatcher5.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher5.Filter = "WildShrines.yaml"; fileSystemWatcher5.Changed += UpdateWildShrineConfigFileOnChange; fileSystemWatcher5.Created += UpdateWildShrineConfigFileOnChange; fileSystemWatcher5.Renamed += UpdateWildShrineConfigFileOnChange; fileSystemWatcher5.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher5.EnableRaisingEvents = true; } public static IEnumerator OnServerRecieveConfigs(long sender, ZPackage package) { Logger.LogInfo((object)"Server recieved config from client, rejecting due to being the server."); yield return null; } private static ZPackage SendCreatureConfigs() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown string text = File.ReadAllText(creatureFilePath); ZPackage val = new ZPackage(); val.Write(text); return val; } private static ZPackage SendWavesConfigs() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown string text = File.ReadAllText(waveStylesFilePath); ZPackage val = new ZPackage(); val.Write(text); return val; } private static ZPackage SendRewardsConfigs() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown string text = File.ReadAllText(rewardFilePath); ZPackage val = new ZPackage(); val.Write(text); return val; } private static ZPackage SendLevelsConfigs() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown string text = File.ReadAllText(levelDefinitionsFilePath); ZPackage val = new ZPackage(); val.Write(text); return val; } private static ZPackage SendWildShrineConfigs() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown string text = File.ReadAllText(wildShrineConfigurationFilePath); ZPackage val = new ZPackage(); val.Write(text); return val; } private static IEnumerator OnClientReceiveCreatureConfigs(long sender, ZPackage package) { string value = package.ReadString(); using (StreamWriter streamWriter = new StreamWriter(creatureFilePath)) { streamWriter.WriteLine(value); } yield return null; } private static IEnumerator OnClientReceiveRewardsConfigs(long sender, ZPackage package) { string value = package.ReadString(); using (StreamWriter streamWriter = new StreamWriter(rewardFilePath)) { streamWriter.WriteLine(value); } yield return null; } private static IEnumerator OnClientReceiveWaveConfigs(long sender, ZPackage package) { string value = package.ReadString(); using (StreamWriter streamWriter = new StreamWriter(waveStylesFilePath)) { streamWriter.WriteLine(value); } yield return null; } private static IEnumerator OnClientReceiveLevelConfigs(long sender, ZPackage package) { string text = package.ReadString(); if (UpdateLevelsInMemory(text) && !ServerConfigsLocked.Value) { using StreamWriter streamWriter = new StreamWriter(levelDefinitionsFilePath); streamWriter.WriteLine(text); } yield return null; } private static IEnumerator OnClientReceiveWildShrineConfigs(long sender, ZPackage package) { string value = package.ReadString(); using (StreamWriter streamWriter = new StreamWriter(wildShrineConfigurationFilePath)) { streamWriter.WriteLine(value); } yield return null; } private static void UpdateLevelsConfigFileOnChange(object sender, FileSystemEventArgs e) { if (!File.Exists(levelDefinitionsFilePath)) { return; } Logger.LogInfo((object)$"{e} Creature filewatcher called, updating creature values."); UpdateLevelsInMemory(File.ReadAllText(levelDefinitionsFilePath)); Logger.LogInfo((object)"Updated levels in-memory values."); try { LevelsSyncRPC.SendPackage(ZNet.instance.m_peers, SendLevelsConfigs()); Logger.LogInfo((object)"Sent levels configs to clients."); } catch { Logger.LogError((object)"Error while server syncing creature configs"); } } private static bool UpdateLevelsInMemory(string raw_levels_data) { ChallengeLevelDefinitionCollection levelDefinitions; try { levelDefinitions = CONST.yamldeserializer.Deserialize(raw_levels_data); } catch { return false; } ChallengeLevels.UpdateLevelsDefinition(levelDefinitions); return true; } private static void UpdateCreatureConfigFileOnChange(object sender, FileSystemEventArgs e) { if (!File.Exists(creatureFilePath)) { return; } Logger.LogInfo((object)$"{e} Creature filewatcher called, updating creature values."); string text = File.ReadAllText(creatureFilePath); SpawnableCreatureCollection spawnables; try { spawnables = CONST.yamldeserializer.Deserialize(text); } catch { Logger.LogWarning((object)"Creatures failed deserializing, skipping update."); return; } Monsters.UpdateSpawnableCreatures(spawnables); Logger.LogInfo((object)"Updated creature in-memory values."); try { monsterSyncRPC.SendPackage(ZNet.instance.m_peers, SendCreatureConfigs()); Logger.LogInfo((object)"Sent creature configs to clients."); } catch { Logger.LogError((object)"Error while server syncing creature configs"); } } private static void UpdateWavesConfigFileOnChange(object sender, FileSystemEventArgs e) { if (!File.Exists(waveStylesFilePath)) { return; } Logger.LogInfo((object)$"{e} Wavestyles filewatcher called, updating Wavestyles values."); string text = File.ReadAllText(waveStylesFilePath); WaveFormatCollection waveStyles; try { waveStyles = CONST.yamldeserializer.Deserialize(text); } catch { Logger.LogWarning((object)"Wavestyles failed deserializing, skipping update."); return; } WaveStyles.UpdateWaveDefinition(waveStyles); Logger.LogInfo((object)"Updated WaveDefinition in-memory values."); try { WavesSyncRPC.SendPackage(ZNet.instance.m_peers, SendWavesConfigs()); Logger.LogInfo((object)"Sent WaveDefinition configs to clients."); } catch { Logger.LogError((object)"Error while server syncing Wave configs"); } } private static void UpdateRewardsConfigFileOnChange(object sender, FileSystemEventArgs e) { if (!File.Exists(rewardFilePath)) { return; } Logger.LogInfo((object)"Rewards filewatcher called, updating rewards values."); string text = File.ReadAllText(rewardFilePath); RewardEntryCollection rewards; try { rewards = CONST.yamldeserializer.Deserialize(text); } catch (Exception) { if (EnableDebugMode.Value) { Logger.LogWarning((object)"Rewards failed deserializing, skipping update."); } return; } RewardsData.UpdateRewardsEntries(rewards); Logger.LogInfo((object)"Updated rewards in-memory values."); try { rewardSyncRPC.SendPackage(ZNet.instance.m_peers, SendRewardsConfigs()); Logger.LogInfo((object)"Sent rewards configs to clients."); } catch (Exception) { Logger.LogError((object)"Error while server syncing rewards configs"); } } private static void UpdateWildShrineConfigFileOnChange(object sender, FileSystemEventArgs e) { if (!File.Exists(rewardFilePath)) { return; } Logger.LogInfo((object)"Rewards filewatcher called, updating Wildshrines values."); string text = File.ReadAllText(wildShrineConfigurationFilePath); WildShrineConfigurationCollection wildShrineDefinitions; try { wildShrineDefinitions = CONST.yamldeserializer.Deserialize(text); } catch (Exception) { Logger.LogWarning((object)"WildShrineConfigs failed deserializing, skipping update."); return; } WildShrineData.UpdateWildShrineDefinition(wildShrineDefinitions); Logger.LogInfo((object)"Updated WildshrineConfigs in-memory values."); try { WildShrineSyncRPC.SendPackage(ZNet.instance.m_peers, SendWildShrineConfigs()); Logger.LogInfo((object)"Sent Wildshrine configs to clients."); } catch (Exception) { Logger.LogError((object)"Error while server syncing Wildshrine configs"); } } private static void UpdateMainConfigFile(object sender, FileSystemEventArgs e) { if (!File.Exists(Paths.ConfigPath)) { return; } try { cfg.SaveOnConfigSet = false; cfg.Reload(); cfg.SaveOnConfigSet = true; } catch { Logger.LogError((object)"There was an issue reloading MidnightsFX.ValheimFortress.cfg."); } } public static ConfigEntry BindServerConfig(string catagory, string key, bool value, string description, bool advanced = false) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown return cfg.Bind(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry BindServerConfig(string catagory, string key, string value, string description, bool advanced = false) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown return cfg.Bind(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry BindServerConfig(string catagory, string key, short value, string description, bool advanced = false, short valmin = 0, short valmax = 150) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry BindServerConfig(string catagory, string key, float value, string description, bool advanced = false, float valmin = 0f, float valmax = 150f) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown return cfg.Bind(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } private void CreateConfigValues(ConfigFile Config) { //IL_04ed: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Expected O, but got Unknown //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Expected O, but got Unknown //IL_053e: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_0550: Expected O, but got Unknown //IL_0550: Unknown result type (might be due to invalid IL or missing references) //IL_055a: Expected O, but got Unknown MaxSpawnRange = BindServerConfig("Shrine of Challenge", "MaxSpawnRange", 100, "The radius around the shrine that enemies can spawn in.", advanced: false, 10, 800); NumberOfRemoteSpawnPoints = BindServerConfig("Shrine of Challenge", "NumberOfRemoteSpawnPoints", 3, "How many remote spawn points (portals) the challenge and wild shrines attempt to place. Creatures emerge from a randomly chosen point each spawn.", advanced: false, 1, 20); EnableHardModifier = BindServerConfig("Shrine of Challenge", "EnableHardModifier", value: true, "Whether or not the hard mode modifier is available (100% bigger wave size for 50% more rewards)", advanced: true); EnableBossModifier = BindServerConfig("Shrine of Challenge", "EnableBossModifier", value: true, "Whether or not boss mod is available as a level modifier (more rewards & spawns the biome specific boss)", advanced: true); EnableSiegeModifer = BindServerConfig("Shrine of Challenge", "EnableSiegeModifer", value: true, "Whether or not siege mode is available as a modifier. Siege mode gives much larger pauses between waves, and 100% larger waves for 50% more reward.", advanced: true); EnableMapPings = BindServerConfig("Shrine of Challenge", "EnableMapPings", value: false, "Whether or not waves spawning from the shrine of challenge should ping the map when they spawn.", advanced: true); EnableShrineMapOverlay = BindServerConfig("Shrine of Challenge", "EnableShrineMapOverlay", value: true, "Whether the shrines should mark each creature spawn location on the minimap (using the vanilla event-area circle and animated event icon) while a challenge is active. Local/cosmetic only; only renders for the instance driving the challenge (singleplayer or the P2P host).", advanced: true); EnableRewardsEstimate = BindServerConfig("Shrine of Challenge", "EnableRewardsEstimate", value: true, "Enables showing an estimate of how many rewards you will get for doing the selected level for the specified reward.", advanced: true); rewardsDifficultyScalar = BindServerConfig("Shrine of Challenge", "rewardsDifficultyScalar", 0.02f, "Multiplier for rewards that scales with level, each level adds this to the value, making high level challenges much more rewarding.", advanced: true); NotifyCreatureThreshold = BindServerConfig("Shrine of Challenge", "NotifyCreatureThreshold", 10, "Sets the level at which interacting with the shrine will add notifier to remaining creatures.", advanced: true, 1, 50); TeleportCreatureThreshold = BindServerConfig("Shrine of Challenge", "TeleportCreatureThreshold", 3, "Sets the level at which interacting with the shrine teleport remaining creatures to the shrine.", advanced: true, 1, 50); ShrineAnnouncementRange = BindServerConfig("Shrine of Challenge", "ShrineAnnouncementRange", 150f, "Sets the range at which announcements will display for shrine of challenge related activities", advanced: true, 50f, 800f); ShrineReconnectRange = BindServerConfig("Shrine of Challenge", "ShrineReconnectRange", 150f, "Sets the max range for the shrine to scan creatures for reconnection when an area is unloaded/reloaded (this includes exit/loading singleplayer).", advanced: true, 500f, 5000f); ShrineReconnectPauseBetweenAmount = BindServerConfig("Shrine of Challenge", "ShrineReconnectPauseBetweenAmount", 30, "Sets the maximun number of creatures to process for reconnection in a singular second.", advanced: true, 1, 60); ShrineStallTimeout = BindServerConfig("Shrine of Challenge", "ShrineStallTimeout", 120f, "Seconds an active challenge may sit with no living creatures and no spawn in progress before it is forced to advance. Protects a run from stalling (and losing its rewards) when the shrine changes network owners.", advanced: true, 30f, 600f); DistanceBetweenShrines = BindServerConfig("Wild Shrines", "DistanceBetweenShrines", 750f, "The mimum distance between shrines, setting this higher will result in fewer wild shrines, lower more.", advanced: true, 100f, 5000f); NumberOfEachWildShrine = BindServerConfig("Wild Shrines", "NumberOfEachWildShrine", 100, "Each wild shrine type will attempt to be placed this many times", advanced: true, 5, 200); ShrineRewardPlayerBonus = BindServerConfig("Shrine of Challenge", "ShrineRewardPlayerBonus", 1f, "How much rewards are multipled for each additional player", advanced: true, 0f, 3f); BaseChallengePoints = BindServerConfig("Difficulty Levels", "BaseChallengePoints", 100, "The base number of points that all waves add. This is especially impactful in early levels (meadows).", advanced: false, 100, 1000); MaxChallengePoints = BindServerConfig("Difficulty Levels", "MaxChallengePoints", 3000, "The absolute max number of points a wave can generate with, higher values will be clamped down to this value.", advanced: true, 1000, 30000); ChallengeSlope = BindServerConfig("Difficulty Levels", "ChallengeSlope", 15f, "The linear regression slope which increases difficulty. If you want harder waves, add 1 and try out the difficulty again.", advanced: false, 5f, 50f); ChanceOfPreviousBiomeCreature = BindServerConfig("Difficulty Levels", "ChanceOfPreviousBiomeCreature", 0.05f, "The chance that a valid prior biome creature will be selected. Only 1 can be selected per wave. Setting to zero disables generating waves with previous biome creatures.", advanced: false, 0f, 1f); MaxCreatureStars = BindServerConfig("Difficulty Levels", "MaxCreatureStars", 2, "The max number of stars a creature can have. SLE or CLLC is required for anything over 2.", advanced: true, 0, 10); ScaleRewardsFromWorldSetting = BindServerConfig("Rewards", "ScaleRewardsFromWorldSetting", value: true, "Whether or not the rewards should scale with the world setting. This will make the rewards more valuable in harder worlds.", advanced: true); MaxRewardsPerSecond = BindServerConfig("Rewards", "MaxRewardsPerSecond", 120, "Sets how fast the shrine will spawn rewards. Reducing this will reduce the performance impact of spawning so many items at once.", advanced: true, 10, 400); rewardsMultiplier = BindServerConfig("Rewards", "rewardsMultiplier", 1.1f, "The base multiplier for rewards, higher values will make every wave more rewarding", advanced: true); ChallengeShrineMaxCreaturesPerWave = BindServerConfig("Shrine of Challenge", "ChallengeShrineMaxCreaturesPerWave", 60, "The max number of creatures that a wave can generate with, creatures will attempt to upgrade and reduce counts based on this.", advanced: true, 12, 200); ArenaShrineMaxCreaturesPerWave = BindServerConfig("Shrine of Arena", "ArenaShrineMaxCreaturesPerWave", 25, "The max number of creatures that a wave can generate with, creatures will attempt to upgrade and reduce counts based on this.", advanced: true, 12, 200); BallistaTargetsPassives = BindServerConfig("Auto Ballista", "EnableTargetingPassiveCreatures", value: false, "Whether or not the automated ballista will target passive creatures (like deer)", advanced: true); BallistaDamage = BindServerConfig("Auto Ballista", "BallistaDamage", 120f, "How much damage the automated ballista does per shot.", advanced: true, 10f, 5000f); BallistaRange = BindServerConfig("Auto Ballista", "BallistaRange", 30f, "How far the ballista can aquire targets and shoot", advanced: true, 10f, 100f); BallistaAmmoAccuracyPenalty = BindServerConfig("Auto Ballista", "BallistaAmmoAccuracyPenalty", 0.05f, "How inaccurate the ammo is for the ballista", advanced: true, 0f, 0.15f); BallistaCooldownTime = BindServerConfig("Auto Ballista", "BallistaCooldownTime", 2f, "How long the ballista waits before another shot", advanced: true, 0.5f, 10f); BallistaTargetUpdateCacheInterval = BindServerConfig("Auto Ballista", "BallistaTargetUpdateCacheInterval", 5, "How many ticks until the ballista updates its cache of nearby enemies.", advanced: true, 1, 10); BallistaEnableShotSafetyCheck = BindServerConfig("Auto Ballista", "BallistaEnableShotSafetyCheck", value: true, "Whether or not the ballista will verify it won't hit other things before shooting.", advanced: true); ServerConfigsLocked = BindServerConfig("Server", "ServerConfigsLocked", value: false, "Server synced configs are not editable.", advanced: true); EnableDebugMode = Config.Bind("Client config", "EnableDebugMode", false, new ConfigDescription("Enables Debug logging for Valheim Fortress.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); EnableDebugMode.SettingChanged += Logger.toggleDebug; EnableTurretDebugMode = Config.Bind("Client config", "EnableTurretDebugMode", false, new ConfigDescription("Enables debug mode for turrets, this can be noisy.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); } } internal class VFLocations { public VFLocations(AssetBundle EmbeddedResourceBundle, VFConfig cfg) { AddWildShrineLocationWithWorldGen(cfg, EmbeddedResourceBundle.LoadAsset("Assets/Custom/Locations/VFortress/VF_wild_shrine_green1.prefab"), (Biome)1); AddWildShrineLocationWithWorldGen(cfg, EmbeddedResourceBundle.LoadAsset("Assets/Custom/Locations/VFortress/VF_wild_shrine_blue1.prefab"), (Biome)8); AddWildShrineLocationWithWorldGen(cfg, EmbeddedResourceBundle.LoadAsset("Assets/Custom/Locations/VFortress/VF_wild_shrine_green2.prefab"), (Biome)2); AddWildShrineLocationWithWorldGen(cfg, EmbeddedResourceBundle.LoadAsset("Assets/Custom/Locations/VFortress/VF_wild_shrine_blue2.prefab"), (Biome)4); AddWildShrineLocationWithWorldGen(cfg, EmbeddedResourceBundle.LoadAsset("Assets/Custom/Locations/VFortress/VF_wild_shrine_yellow1.prefab"), (Biome)16); AddWildShrineLocationWithWorldGen(cfg, EmbeddedResourceBundle.LoadAsset("Assets/Custom/Locations/VFortress/VF_wild_shrine_purple1.prefab"), (Biome)512); } public void AddWildShrineLocationWithWorldGen(VFConfig cfg, GameObject prefab, Biome biome) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown if (!VFConfig.BindServerConfig("Wild Shrines", ((Object)prefab).name + "-Enable", value: true, "Enable/Disable the " + ((Object)prefab).name + " wildshrine.").Value) { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)("Skipped loading location " + ((Object)prefab).name)); } return; } prefab.AddComponent(); prefab.AddComponent(); LocationConfig val = new LocationConfig(); val.Biome = biome; val.Quantity = VFConfig.NumberOfEachWildShrine.Value; val.Priotized = false; val.ExteriorRadius = 5f; val.SlopeRotation = true; val.MinAltitude = 1f; val.ClearArea = true; val.RandomRotation = false; val.MinDistanceFromSimilar = VFConfig.DistanceBetweenShrines.Value; ZoneManager.Instance.AddCustomLocation(new CustomLocation(prefab, true, val)); } } } namespace ValheimFortress.Defenses { internal static class BallistaOnChange { internal static void BallistaCooldownTime_SettingChanged(object sender, EventArgs e) { foreach (GameObject item in findPrefabInScene()) { Logger.LogInfo("Updating attack cooldown duration on " + ((Object)item).name); item.GetComponent().m_attackCooldown = VFConfig.BallistaCooldownTime.Value; } } internal static void BallistaAmmoAccuracyPenalty_SettingChanged(object sender, EventArgs e) { foreach (GameObject item in findPrefabInScene()) { Logger.LogInfo("Updating accuracy on " + ((Object)item).name); item.GetComponent().m_ammo_accuracy = VFConfig.BallistaAmmoAccuracyPenalty.Value; } } internal static void BallistaRange_SettingChanged(object sender, EventArgs e) { foreach (GameObject item in findPrefabInScene()) { Logger.LogInfo("Updating range on " + ((Object)item).name); item.GetComponent().m_viewDistance = VFConfig.BallistaRange.Value; } } internal static void BallistaDamageChange(object sender, EventArgs e) { foreach (GameObject item in findPrefabInScene()) { Logger.LogInfo("Updating dmg on " + ((Object)item).name); item.GetComponent().m_Ammo.m_shared.m_damages.m_pierce = VFConfig.BallistaDamage.Value; } } private static IEnumerable findPrefabInScene() { IEnumerable enumerable = from obj in Resources.FindObjectsOfTypeAll() where ((Object)obj).name.StartsWith("VFpiece_turret") select obj; Logger.LogInfo($"Found in scene objects: {enumerable.Count()}"); return enumerable; } } public class VFTurret : MonoBehaviour, Hoverable, IPieceMarker { private static float m_turnRate = 80f; private static float m_horizontalAngle = 85f; private static float m_hitNoise = 10f; private static float m_shootWhenAimDiff = 0.99f; private static float m_predictionModifier = 1f; private static float m_updateTargetIntervalNear = 2f; private static float m_updateTargetIntervalFar = 8f; private static float m_aimDiffToTarget = -1f; public static float m_markerHideTime = 0.5f; public float m_viewDistance = VFConfig.BallistaRange.Value; public float m_attackCooldown = VFConfig.BallistaCooldownTime.Value; public float m_ammo_accuracy = VFConfig.BallistaAmmoAccuracyPenalty.Value; private static LayerMask lmsk; private GameObject m_Projectile; public ItemData m_Ammo; private GameObject m_shootEffect; private GameObject m_reloadEffect; private GameObject m_newTargetEffect; private GameObject m_lostTargetEffect; private ZNetView m_nview; private Character m_target; private GameObject turretBodyArmed; private GameObject turretBodyUnarmed; private GameObject turretBodyArmedBolt; private GameObject turretBody; private GameObject turretNeck; private GameObject eye; private CircleProjector areaMarker; private Quaternion m_baseBodyRotation; private Quaternion m_baseNeckRotation; private List nearby_targets = new List(); private bool m_haveTarget; private float m_updateTargetTimer; private float m_scan; private float m_noTargetScanRate = 12f; private ZDOIDZNetProperty target { get; set; } protected void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) m_nview = ((Component)this).GetComponent(); if (Object.op_Implicit((Object)(object)m_nview)) { target = new ZDOIDZNetProperty("VFTurret_Target", m_nview, ZDOID.None); } m_updateTargetTimer = Random.Range(0f, m_updateTargetIntervalNear); if (Object.op_Implicit((Object)(object)m_nview)) { GameObject gameObject = ((Component)((Component)this).transform.Find("New")).gameObject; _ = ((Component)gameObject.transform.Find("Base")).gameObject; GameObject gameObject2 = ((Component)gameObject.transform.Find("NeckRotation")).gameObject; _ = ((Component)gameObject2.transform.GetChild(0)).gameObject; turretNeck = gameObject2; m_baseNeckRotation = turretNeck.transform.localRotation; GameObject val = (turretBody = ((Component)gameObject.transform.Find("BodyRotation")).gameObject); m_baseBodyRotation = turretBody.transform.localRotation; turretBodyArmed = ((Component)val.transform.Find("Body")).gameObject; turretBodyUnarmed = ((Component)val.transform.Find("Body_Unarmed")).gameObject; turretBodyArmedBolt = ((Component)val.transform.Find("Bolt_Black_Metal")).gameObject; eye = ((Component)val.transform.Find("Eye")).gameObject; m_Projectile = PrefabManager.Instance.GetPrefab("TurretBolt"); m_Ammo = m_Projectile.GetComponent().m_itemData; m_Ammo.m_shared.m_damages.m_pierce = VFConfig.BallistaDamage.Value; areaMarker = ((Component)((Component)this).transform.Find("AreaMarker")).gameObject.GetComponent(); m_shootEffect = PrefabManager.Instance.GetPrefab("fx_turret_fire"); m_reloadEffect = PrefabManager.Instance.GetPrefab("fx_turret_reload"); m_newTargetEffect = PrefabManager.Instance.GetPrefab("fx_turret_newtarget"); m_lostTargetEffect = PrefabManager.Instance.GetPrefab("fx_turret_notarget"); m_noTargetScanRate = Random.Range(8, 16); lmsk = LayerMask.op_Implicit(LayerMask.GetMask(new string[3] { "Default", "TransparentFX", "character" })); lmsk = LayerMask.op_Implicit(~LayerMask.op_Implicit(lmsk)); } } private void FixedUpdate() { float fixedDeltaTime = Time.fixedDeltaTime; UpdateMarker(); if (m_nview.IsValid()) { ConnectTargetIfSetAndInRange(); UpdateTurretRotation(fixedDeltaTime); if (m_nview.IsOwner() && !IsCoolingDown()) { TurretRearmAnimate(); UpdateTarget(fixedDeltaTime); ShootProjectile(fixedDeltaTime); } } } private void TurretRearmAnimate() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!turretBodyArmed.activeSelf) { Object.Instantiate(m_reloadEffect, turretBodyArmed.transform.position, turretBodyArmed.transform.rotation); turretBodyArmed.SetActive(true); turretBodyArmedBolt.SetActive(true); turretBodyUnarmed.SetActive(false); } } private void UpdateTurretRotation(float fixedDeltaTime) { //IL_001b: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: 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_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: 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_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) Vector3 val2; Quaternion rotation; if (Object.op_Implicit((Object)(object)m_target)) { float num = Vector2.Distance(Vector2.op_Implicit(((Component)m_target).transform.position), Vector2.op_Implicit(eye.transform.position)) / (m_Ammo.m_shared.m_attack.m_projectileVel * 2f); Vector3 val = m_target.GetVelocity() * num * m_predictionModifier; val2 = ((Component)m_target).transform.position + val - turretBody.transform.position; ref float y = ref val2.y; float num2 = y; CapsuleCollider componentInChildren = ((Component)m_target).GetComponentInChildren(); y = num2 + ((componentInChildren != null) ? (componentInChildren.height / 2f) : 1f); } else { m_scan += fixedDeltaTime; if (m_scan > m_noTargetScanRate * 2f) { m_scan = 0f; } rotation = ((Component)this).transform.rotation; val2 = Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y + (float)((m_scan - m_noTargetScanRate > 0f) ? 1 : (-1)) * (m_horizontalAngle / 2f), 0f) * Vector3.forward; } ((Vector3)(ref val2)).Normalize(); Quaternion val3 = Quaternion.LookRotation(val2, Vector3.up); Vector3 eulerAngles = ((Quaternion)(ref val3)).eulerAngles; rotation = ((Component)this).transform.rotation; float y2 = ((Quaternion)(ref rotation)).eulerAngles.y; eulerAngles.y -= y2; if (m_horizontalAngle >= 0f) { float num3 = eulerAngles.y; if (num3 > 180f) { num3 -= 360f; } else if (num3 < -180f) { num3 += 360f; } if (num3 > m_horizontalAngle) { ((Vector3)(ref eulerAngles))..ctor(eulerAngles.x, m_horizontalAngle + y2, eulerAngles.z); ((Quaternion)(ref val3)).eulerAngles = eulerAngles; } else if (num3 < 0f - m_horizontalAngle) { ((Vector3)(ref eulerAngles))..ctor(eulerAngles.x, 0f - m_horizontalAngle + y2, eulerAngles.z); ((Quaternion)(ref val3)).eulerAngles = eulerAngles; } } Quaternion val4 = Quaternion.RotateTowards(turretBody.transform.rotation, val3, m_turnRate * fixedDeltaTime); turretBody.transform.rotation = m_baseBodyRotation * val4; Transform transform = turretNeck.transform; Quaternion baseNeckRotation = m_baseNeckRotation; rotation = turretBody.transform.rotation; float y3 = ((Quaternion)(ref rotation)).eulerAngles.y; rotation = turretBody.transform.rotation; transform.rotation = baseNeckRotation * Quaternion.Euler(0f, y3, ((Quaternion)(ref rotation)).eulerAngles.z); m_aimDiffToTarget = (m_haveTarget ? Math.Abs(Quaternion.Dot(val4, val3)) : (-1f)); } private void UpdateTarget(float dt) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)m_target)) { return; } m_updateTargetTimer -= dt; if (m_updateTargetTimer <= 0f) { nearby_targets.Clear(); Character.GetCharactersInRange(((Component)this).transform.position, m_viewDistance, nearby_targets); nearby_targets.Sort((Character a, Character b) => Vector3.SqrMagnitude(((Component)this).transform.position - ((Component)a).transform.position).CompareTo(Vector3.SqrMagnitude(((Component)this).transform.position - ((Component)b).transform.position))); bool flag = IsCharacterInRangeAndNotPlayer(((Component)this).transform.position, VFConfig.BallistaRange.Value, nearby_targets); m_updateTargetTimer = (flag ? m_updateTargetIntervalNear : m_updateTargetIntervalFar); Character val = selectTarget(flag); if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)m_target) { if (Object.op_Implicit((Object)(object)val)) { Object.Instantiate(m_newTargetEffect, ((Component)this).transform.position, ((Component)this).transform.rotation); } else { Object.Instantiate(m_lostTargetEffect, ((Component)this).transform.position, ((Component)this).transform.rotation); } if (VFConfig.EnableTurretDebugMode.Value) { Logger.LogInfo((object)$"set target {val}"); } target.Set(Object.op_Implicit((Object)(object)val) ? val.GetZDOID() : ZDOID.None); m_target = val; m_haveTarget = true; } } if (m_haveTarget && (!Object.op_Implicit((Object)(object)m_target) || m_target.IsDead())) { target.Set(ZDOID.None); m_haveTarget = false; m_scan = 0f; Object.Instantiate(m_lostTargetEffect, ((Component)this).transform.position, ((Component)this).transform.rotation); } } public static bool IsCharacterInRangeAndNotPlayer(Vector3 point, float range, List character_list) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) foreach (Character item in character_list) { if (Vector3.Distance(((Component)item).transform.position, point) < range && !item.IsPlayer() && (int)item.GetFaction() != 0 && !(item is Player)) { return true; } } return false; } private bool IsValidTarget(Character ptarget) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 if ((Object)(object)ptarget == (Object)null) { return false; } if (ptarget.IsDead() || ptarget.IsTamed() || ptarget.IsPlayer()) { return false; } if (!VFConfig.BallistaTargetsPassives.Value && (int)ptarget.GetFaction() == 1) { return false; } if ((int)ptarget.GetFaction() == 0 || ptarget is Player) { return false; } return true; } private Character selectTarget(bool character_in_range) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_00f8: Unknown result type (might be due to invalid IL or missing references) if (!character_in_range) { return null; } Character val = null; if (VFConfig.EnableTurretDebugMode.Value) { Logger.LogInfo((object)$"checking targets {nearby_targets.Count}"); } RaycastHit val3 = default(RaycastHit); foreach (Character nearby_target in nearby_targets) { if (IsValidTarget(nearby_target) && !nearby_target.GetBaseAI().IsSleeping() && Vector3.Distance(((Component)this).transform.position, ((Component)nearby_target).transform.position) < m_viewDistance) { Vector3 val2 = ((Component)nearby_target).transform.position - eye.transform.position; Vector3 normalized = ((Vector3)(ref val2)).normalized; Physics.Raycast(eye.transform.position, normalized, ref val3, m_viewDistance, LayerMask.op_Implicit(lmsk)); float num = Vector3.Distance(eye.transform.position, ((Component)nearby_target).transform.position); bool flag = ((RaycastHit)(ref val3)).distance > num - 2f; if (VFConfig.EnableTurretDebugMode.Value) { Logger.LogInfo((object)$"TargetCheck: distance to target: {num}, raycast distance test: {((RaycastHit)(ref val3)).distance}, can hit distance: {flag}"); } if (flag) { val = nearby_target; break; } } } if ((Object)(object)val != (Object)null && VFConfig.EnableTurretDebugMode.Value) { Logger.LogInfo((object)$"Selected target: {val}"); } return val; } public void ShootProjectile(float dt) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Expected O, but got Unknown //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)m_target) || !(m_aimDiffToTarget > m_shootWhenAimDiff) || IsCoolingDown()) { return; } if (VFConfig.BallistaEnableShotSafetyCheck.Value) { RaycastHit val = default(RaycastHit); bool flag = Physics.Raycast(eye.transform.position, eye.transform.forward, ref val, m_viewDistance, LayerMask.op_Implicit(lmsk)); Vector3 position = eye.transform.position; position.z += 0.5f; float num = Vector3.Distance(position, ((Component)m_target).transform.position); bool flag2 = ((RaycastHit)(ref val)).distance > num - 2f; if (VFConfig.EnableTurretDebugMode.Value) { Logger.LogInfo((object)$" distance to target: {num}, raycast distance test: {((RaycastHit)(ref val)).distance}, can hit distance: {flag2} hit bool: {flag}"); } if (!flag2) { return; } } if (VFConfig.EnableTurretDebugMode.Value) { Logger.LogInfo((object)$"Turret target status:{!Object.op_Implicit((Object)(object)m_target)} aimdiff:{m_aimDiffToTarget} > {m_shootWhenAimDiff} ({!(m_aimDiffToTarget > m_shootWhenAimDiff)}) cooldown:{IsCoolingDown()}"); } Object.Instantiate(m_shootEffect, turretBodyArmed.transform.position, eye.transform.rotation); m_nview.GetZDO().Set("lastAttack", (float)ZNet.instance.GetTimeSeconds()); Vector3 forward = eye.transform.forward; Vector3 val2 = Vector3.Cross(forward, Vector3.up); Quaternion val3 = Quaternion.AngleAxis(Random.Range(0f - m_ammo_accuracy, m_ammo_accuracy), Vector3.up); forward = Quaternion.AngleAxis(Random.Range(0f - m_ammo_accuracy, m_ammo_accuracy), val2) * forward; forward = val3 * forward; GameObject obj = Object.Instantiate(m_Ammo.m_shared.m_attack.m_attackProjectile, eye.transform.position, eye.transform.rotation); HitData val4 = new HitData(); val4.m_pushForce = m_Ammo.m_shared.m_attackForce; val4.m_backstabBonus = m_Ammo.m_shared.m_backstabBonus; val4.m_staggerMultiplier = m_Ammo.m_shared.m_attack.m_staggerMultiplier; ((DamageTypes)(ref val4.m_damage)).Add(m_Ammo.GetDamage(), 1); val4.m_blockable = m_Ammo.m_shared.m_blockable; val4.m_dodgeable = m_Ammo.m_shared.m_dodgeable; val4.m_skill = m_Ammo.m_shared.m_skillType; IProjectile component = obj.GetComponent(); if (component != null) { component.Setup((Character)null, forward * (m_Ammo.m_shared.m_attack.m_projectileVel * 3f), m_hitNoise, val4, (ItemData)null, m_Ammo); } turretBodyArmed.SetActive(false); turretBodyArmedBolt.SetActive(false); turretBodyUnarmed.SetActive(true); } public bool IsCoolingDown() { if (!m_nview.IsValid()) { return false; } return (double)(m_nview.GetZDO().GetFloat("lastAttack", 0f) + m_attackCooldown) > ZNet.instance.GetTimeSeconds(); } public string GetHoverText() { if (!m_nview.IsValid()) { return ""; } return Localization.instance.Localize("$piece_vfturret"); } public string GetHoverName() { return Localization.instance.Localize("$piece_vfturret"); } private void ConnectTargetIfSetAndInRange() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!(target.Get() != ZDOID.None) || m_haveTarget) { return; } GameObject val = ZNetScene.instance.FindInstance(target.Get()); if (Object.op_Implicit((Object)(object)val)) { if (Vector3.Distance(eye.transform.position, val.transform.position) <= m_viewDistance) { Character component = val.GetComponent(); if (component != null) { m_target = component; m_haveTarget = true; } } } else { target.ForceSet(ZDOID.None); m_target = null; m_haveTarget = false; m_scan = 0f; } } private void OnDestroyed() { ((Component)this).GetComponent().m_onDestroyed(); } public void ShowHoverMarker() { ShowBuildMarker(); } public void ShowBuildMarker() { if (!Object.op_Implicit((Object)(object)areaMarker)) { areaMarker.m_radius = m_viewDistance; ((Component)areaMarker).gameObject.SetActive(false); } if (Object.op_Implicit((Object)(object)areaMarker)) { ((Component)areaMarker).gameObject.SetActive(true); ((MonoBehaviour)this).CancelInvoke("HideMarker"); ((MonoBehaviour)this).Invoke("HideMarker", m_markerHideTime); } } private void UpdateMarker() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)areaMarker) && ((Behaviour)areaMarker).isActiveAndEnabled) { CircleProjector obj = areaMarker; Quaternion rotation = ((Component)this).transform.rotation; obj.m_start = ((Quaternion)(ref rotation)).eulerAngles.y - m_horizontalAngle; areaMarker.m_turns = m_horizontalAngle * 2f / 360f; } } private void HideMarker() { if (Object.op_Implicit((Object)(object)areaMarker)) { ((Component)areaMarker).gameObject.SetActive(false); } } } } namespace ValheimFortress.Data { public class ChallengeLevels { public static List ChallengeLevelDefinitions = new List { new ChallengeLevelDefinition { levelIndex = 1, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_meadow", requiredGlobalKey = "NONE", biome = (Biome)1, waveFormat = WaveStyles.WaveStyleName.Tutorial, bossWaveFormat = WaveStyles.WaveStyleName.TutorialBoss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_meadows", bossLevelWarningLocalization = "$shrine_warning_meadows_boss", onlySelectMonsters = new List(), excludeSelectMonsters = new List(), commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true, linearDecreaseRandomWaveAdjustment = false, partialRandomWaveAdjustment = false, onlyGenerateInSecondHalf = false }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true, linearDecreaseRandomWaveAdjustment = false, partialRandomWaveAdjustment = false, onlyGenerateInSecondHalf = false }, eliteSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true, linearDecreaseRandomWaveAdjustment = false, partialRandomWaveAdjustment = false, onlyGenerateInSecondHalf = false } }, new ChallengeLevelDefinition { levelIndex = 2, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_meadow", requiredGlobalKey = "NONE", biome = (Biome)1, waveFormat = WaveStyles.WaveStyleName.Tutorial, bossWaveFormat = WaveStyles.WaveStyleName.TutorialBoss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_meadows", bossLevelWarningLocalization = "$shrine_warning_meadows_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true } }, new ChallengeLevelDefinition { levelIndex = 3, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_meadow", requiredGlobalKey = "NONE", biome = (Biome)1, waveFormat = WaveStyles.WaveStyleName.Tutorial, bossWaveFormat = WaveStyles.WaveStyleName.TutorialBoss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_meadows", bossLevelWarningLocalization = "$shrine_warning_meadows_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true } }, new ChallengeLevelDefinition { levelIndex = 4, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_meadow", requiredGlobalKey = "NONE", biome = (Biome)1, waveFormat = WaveStyles.WaveStyleName.Starter, bossWaveFormat = WaveStyles.WaveStyleName.TutorialBoss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_meadows", bossLevelWarningLocalization = "$shrine_warning_meadows_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true } }, new ChallengeLevelDefinition { levelIndex = 5, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_meadow", requiredGlobalKey = "NONE", biome = (Biome)1, waveFormat = WaveStyles.WaveStyleName.Starter, bossWaveFormat = WaveStyles.WaveStyleName.TutorialBoss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_meadows", bossLevelWarningLocalization = "$shrine_warning_meadows_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true } }, new ChallengeLevelDefinition { levelIndex = 6, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_forest", requiredGlobalKey = "defeated_eikthyr", biome = (Biome)8, waveFormat = WaveStyles.WaveStyleName.Easy, bossWaveFormat = WaveStyles.WaveStyleName.EasyBoss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_forest", bossLevelWarningLocalization = "$shrine_warning_forest_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true } }, new ChallengeLevelDefinition { levelIndex = 7, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_forest", requiredGlobalKey = "defeated_eikthyr", biome = (Biome)8, waveFormat = WaveStyles.WaveStyleName.Normal, bossWaveFormat = WaveStyles.WaveStyleName.EasyBoss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_forest", bossLevelWarningLocalization = "$shrine_warning_forest_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true } }, new ChallengeLevelDefinition { levelIndex = 8, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_forest", requiredGlobalKey = "defeated_eikthyr", biome = (Biome)8, waveFormat = WaveStyles.WaveStyleName.Normal, bossWaveFormat = WaveStyles.WaveStyleName.Boss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_forest", bossLevelWarningLocalization = "$shrine_warning_forest_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true } }, new ChallengeLevelDefinition { levelIndex = 9, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_forest", requiredGlobalKey = "defeated_eikthyr", biome = (Biome)8, waveFormat = WaveStyles.WaveStyleName.Normal, bossWaveFormat = WaveStyles.WaveStyleName.Boss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_forest", bossLevelWarningLocalization = "$shrine_warning_forest_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true } }, new ChallengeLevelDefinition { levelIndex = 10, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_forest", requiredGlobalKey = "defeated_eikthyr", biome = (Biome)8, waveFormat = WaveStyles.WaveStyleName.Hard, bossWaveFormat = WaveStyles.WaveStyleName.Boss, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = "$shrine_warning_forest", bossLevelWarningLocalization = "$shrine_warning_forest_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 11, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_swamp", requiredGlobalKey = "defeated_gdking", biome = (Biome)2, waveFormat = WaveStyles.WaveStyleName.Easy, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_swamp", bossLevelWarningLocalization = "$shrine_warning_swamp_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 12, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_swamp", requiredGlobalKey = "defeated_gdking", biome = (Biome)2, waveFormat = WaveStyles.WaveStyleName.Normal, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_swamp", bossLevelWarningLocalization = "$shrine_warning_swamp_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 13, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_swamp", requiredGlobalKey = "defeated_gdking", biome = (Biome)2, waveFormat = WaveStyles.WaveStyleName.Normal, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_swamp", bossLevelWarningLocalization = "$shrine_warning_swamp_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 14, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_swamp", requiredGlobalKey = "defeated_gdking", biome = (Biome)2, waveFormat = WaveStyles.WaveStyleName.Hard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_swamp", bossLevelWarningLocalization = "$shrine_warning_swamp_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 15, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_swamp", requiredGlobalKey = "defeated_gdking", biome = (Biome)2, waveFormat = WaveStyles.WaveStyleName.Hard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_swamp", bossLevelWarningLocalization = "$shrine_warning_swamp_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 16, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mountain", requiredGlobalKey = "defeated_bonemass", biome = (Biome)4, waveFormat = WaveStyles.WaveStyleName.Normal, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mountain", bossLevelWarningLocalization = "$shrine_warning_mountain_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 17, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mountain", requiredGlobalKey = "defeated_bonemass", biome = (Biome)4, waveFormat = WaveStyles.WaveStyleName.Normal, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mountain", bossLevelWarningLocalization = "$shrine_warning_mountain_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 18, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mountain", requiredGlobalKey = "defeated_bonemass", biome = (Biome)4, waveFormat = WaveStyles.WaveStyleName.Hard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mountain", bossLevelWarningLocalization = "$shrine_warning_mountain_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 19, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mountain", requiredGlobalKey = "defeated_bonemass", biome = (Biome)4, waveFormat = WaveStyles.WaveStyleName.Hard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mountain", bossLevelWarningLocalization = "$shrine_warning_mountain_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 20, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mountain", requiredGlobalKey = "defeated_bonemass", biome = (Biome)4, waveFormat = WaveStyles.WaveStyleName.Expert, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mountain", bossLevelWarningLocalization = "$shrine_warning_mountain_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 21, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_plains", requiredGlobalKey = "defeated_dragon", biome = (Biome)16, waveFormat = WaveStyles.WaveStyleName.Normal, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_plains", bossLevelWarningLocalization = "$shrine_warning_plains_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 22, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_plains", requiredGlobalKey = "defeated_dragon", biome = (Biome)16, waveFormat = WaveStyles.WaveStyleName.Hard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_plains", bossLevelWarningLocalization = "$shrine_warning_plains_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 23, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_plains", requiredGlobalKey = "defeated_dragon", biome = (Biome)16, waveFormat = WaveStyles.WaveStyleName.VeryHard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_plains", bossLevelWarningLocalization = "$shrine_warning_plains_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 24, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_plains", requiredGlobalKey = "defeated_dragon", biome = (Biome)16, waveFormat = WaveStyles.WaveStyleName.Normal, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_plains", bossLevelWarningLocalization = "$shrine_warning_plains_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 25, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_plains", requiredGlobalKey = "defeated_dragon", biome = (Biome)16, waveFormat = WaveStyles.WaveStyleName.Expert, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_plains", bossLevelWarningLocalization = "$shrine_warning_plains_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 26, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mistland", requiredGlobalKey = "defeated_goblinking", biome = (Biome)512, waveFormat = WaveStyles.WaveStyleName.Hard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mistlands", bossLevelWarningLocalization = "$shrine_warning_mistlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 27, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mistland", requiredGlobalKey = "defeated_goblinking", biome = (Biome)512, waveFormat = WaveStyles.WaveStyleName.VeryHard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mistlands", bossLevelWarningLocalization = "$shrine_warning_mistlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 28, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mistland", requiredGlobalKey = "defeated_goblinking", biome = (Biome)512, waveFormat = WaveStyles.WaveStyleName.Expert, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mistlands", bossLevelWarningLocalization = "$shrine_warning_mistlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 29, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mistland", requiredGlobalKey = "defeated_goblinking", biome = (Biome)512, waveFormat = WaveStyles.WaveStyleName.Extreme, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mistlands", bossLevelWarningLocalization = "$shrine_warning_mistlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 30, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_mistland", requiredGlobalKey = "defeated_goblinking", biome = (Biome)512, waveFormat = WaveStyles.WaveStyleName.Dynamic, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_mistlands", bossLevelWarningLocalization = "$shrine_warning_mistlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 31, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_ashland", requiredGlobalKey = "defeated_fader", biome = (Biome)32, waveFormat = WaveStyles.WaveStyleName.Hard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_ashlands", bossLevelWarningLocalization = "$shrine_warning_ashlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 32, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_ashland", requiredGlobalKey = "defeated_fader", biome = (Biome)32, waveFormat = WaveStyles.WaveStyleName.VeryHard, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_ashlands", bossLevelWarningLocalization = "$shrine_warning_ashlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 33, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_ashland", requiredGlobalKey = "defeated_fader", biome = (Biome)32, waveFormat = WaveStyles.WaveStyleName.Expert, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_ashlands", bossLevelWarningLocalization = "$shrine_warning_ashlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 34, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_ashland", requiredGlobalKey = "defeated_fader", biome = (Biome)32, waveFormat = WaveStyles.WaveStyleName.Extreme, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_ashlands", bossLevelWarningLocalization = "$shrine_warning_ashlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 35, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, true }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_ashland", requiredGlobalKey = "defeated_fader", biome = (Biome)32, waveFormat = WaveStyles.WaveStyleName.Dynamic, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_ashlands", bossLevelWarningLocalization = "$shrine_warning_ashlands_boss", commonSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, rareSpawnModifiers = new SpawnModifiers { linearIncreaseRandomWaveAdjustment = true }, eliteSpawnModifiers = new SpawnModifiers { onlyGenerateInSecondHalf = true } }, new ChallengeLevelDefinition { levelIndex = 9, levelForShrineTypes = new Dictionary { { ShrineType.Challenge, false }, { ShrineType.Arena, true } }, levelMenuLocalization = "$shrine_menu_troll_level", requiredGlobalKey = "KilledTroll", biome = (Biome)8, waveFormat = WaveStyles.WaveStyleName.ElitesOnly, bossWaveFormat = WaveStyles.WaveStyleName.DynamicBoss, maxCreatureFromPreviousBiomes = 1, levelWarningLocalization = "$shrine_warning_trolls", bossLevelWarningLocalization = "$shrine_warning_forest_boss", onlySelectMonsters = new List { "Troll" } } }; public static List GetChallengeLevelDefinitions() { return ChallengeLevelDefinitions; } public static void UpdateLevelsDefinition(ChallengeLevelDefinitionCollection levelDefinitions) { ChallengeLevelDefinitions.Clear(); ChallengeLevelDefinitions = levelDefinitions.Levels; if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Updated Level definitions."); } } public static string YamlLevelsDefinition() { ChallengeLevelDefinitionCollection challengeLevelDefinitionCollection = new ChallengeLevelDefinitionCollection(); challengeLevelDefinitionCollection.Levels = ChallengeLevelDefinitions; return CONST.yamlserializer.Serialize((object)challengeLevelDefinitionCollection); } } public class Monsters { private const string COMMON = "common"; private const string RARE = "rare"; private const string ELITE = "elite"; private const string UNIQUE = "unique"; private const string MEADOWS = "Meadows"; private const string BLACKFOREST = "BlackForest"; private const string SWAMP = "Swamp"; private const string MOUNTAIN = "Mountain"; private const string PLAINS = "Plains"; private const string MISTLANDS = "Mistlands"; private const string ASHLANDS = "Ashlands"; public static Dictionary SpawnableCreatures = new Dictionary { { "Neck", new CreatureValues { spawnCost = 2, prefabName = "Neck", spawnType = "common", biome = (Biome)1, enabled = true, dropsEnabled = false } }, { "Boar", new CreatureValues { spawnCost = 2, prefabName = "Boar", spawnType = "common", biome = (Biome)1, enabled = true, dropsEnabled = false } }, { "Deer", new CreatureValues { spawnCost = 2, prefabName = "Deer", spawnType = "common", biome = (Biome)1, enabled = false, dropsEnabled = false } }, { "Greyling", new CreatureValues { spawnCost = 3, prefabName = "Greyling", spawnType = "common", biome = (Biome)1, enabled = true, dropsEnabled = false } }, { "GreyDwarf", new CreatureValues { spawnCost = 4, prefabName = "Greydwarf", spawnType = "common", biome = (Biome)8, enabled = true, dropsEnabled = false } }, { "GreyDwarfBrute", new CreatureValues { spawnCost = 8, prefabName = "Greydwarf_Elite", spawnType = "rare", biome = (Biome)8, enabled = true, dropsEnabled = false } }, { "GreyDwarfShaman", new CreatureValues { spawnCost = 8, prefabName = "Greydwarf_Shaman", spawnType = "rare", biome = (Biome)8, enabled = true, dropsEnabled = false } }, { "Skeleton", new CreatureValues { spawnCost = 4, prefabName = "Skeleton_NoArcher", spawnType = "common", biome = (Biome)8, enabled = true, dropsEnabled = false } }, { "SkeletonArcher", new CreatureValues { spawnCost = 5, prefabName = "Skeleton", spawnType = "common", biome = (Biome)8, enabled = true, dropsEnabled = false } }, { "RancidSkeleton", new CreatureValues { spawnCost = 9, prefabName = "Skeleton_Poison", spawnType = "rare", biome = (Biome)8, enabled = true, dropsEnabled = false } }, { "Ghost", new CreatureValues { spawnCost = 7, prefabName = "Ghost", spawnType = "rare", biome = (Biome)8, enabled = true, dropsEnabled = false } }, { "Troll", new CreatureValues { spawnCost = 20, prefabName = "Troll", spawnType = "elite", biome = (Biome)8, enabled = true, dropsEnabled = false } }, { "Surtling", new CreatureValues { spawnCost = 6, prefabName = "Surtling", spawnType = "rare", biome = (Biome)2, enabled = true, dropsEnabled = false } }, { "Leech", new CreatureValues { spawnCost = 8, prefabName = "Leech", spawnType = "common", biome = (Biome)2, enabled = false, dropsEnabled = false } }, { "Wraith", new CreatureValues { spawnCost = 10, prefabName = "Wraith", spawnType = "rare", biome = (Biome)2, enabled = true, dropsEnabled = false } }, { "Abomination", new CreatureValues { spawnCost = 30, prefabName = "Abomination", spawnType = "elite", biome = (Biome)2, enabled = true, dropsEnabled = false } }, { "Draugr", new CreatureValues { spawnCost = 10, prefabName = "Draugr", spawnType = "common", biome = (Biome)2, enabled = true, dropsEnabled = false } }, { "DraugrArcher", new CreatureValues { spawnCost = 20, prefabName = "Draugr_Ranged", spawnType = "rare", biome = (Biome)2, enabled = true, dropsEnabled = false } }, { "DraugrElite", new CreatureValues { spawnCost = 15, prefabName = "Draugr_Elite", spawnType = "rare", biome = (Biome)2, enabled = true, dropsEnabled = false } }, { "Blob", new CreatureValues { spawnCost = 7, prefabName = "Blob", spawnType = "common", biome = (Biome)2, enabled = true, dropsEnabled = false } }, { "BlobElite", new CreatureValues { spawnCost = 15, prefabName = "BlobElite", spawnType = "rare", biome = (Biome)2, enabled = true, dropsEnabled = false } }, { "Bat", new CreatureValues { spawnCost = 3, prefabName = "Bat", spawnType = "common", biome = (Biome)4, enabled = false, dropsEnabled = false } }, { "IceDrake", new CreatureValues { spawnCost = 25, prefabName = "Hatchling", spawnType = "rare", biome = (Biome)4, enabled = true, dropsEnabled = false } }, { "Wolf", new CreatureValues { spawnCost = 18, prefabName = "Wolf", spawnType = "common", biome = (Biome)4, enabled = true, dropsEnabled = false } }, { "Fenring", new CreatureValues { spawnCost = 28, prefabName = "Fenring", spawnType = "rare", biome = (Biome)4, enabled = true, dropsEnabled = false } }, { "Ulv", new CreatureValues { spawnCost = 20, prefabName = "Ulv", spawnType = "common", biome = (Biome)4, enabled = true, dropsEnabled = false } }, { "Cultist", new CreatureValues { spawnCost = 40, prefabName = "Fenring_Cultist", spawnType = "rare", biome = (Biome)4, enabled = true, dropsEnabled = false } }, { "StoneGolem", new CreatureValues { spawnCost = 50, prefabName = "StoneGolem", spawnType = "elite", biome = (Biome)4, enabled = true, dropsEnabled = false } }, { "Deathsquito", new CreatureValues { spawnCost = 20, prefabName = "Deathsquito", spawnType = "common", biome = (Biome)16, enabled = true, dropsEnabled = false } }, { "Fuling", new CreatureValues { spawnCost = 15, prefabName = "Goblin", spawnType = "common", biome = (Biome)16, enabled = true, dropsEnabled = false } }, { "FulingArcher", new CreatureValues { spawnCost = 20, prefabName = "GoblinArcher", spawnType = "common", biome = (Biome)16, enabled = true, dropsEnabled = false } }, { "FulingBerserker", new CreatureValues { spawnCost = 45, prefabName = "GoblinBrute", spawnType = "elite", biome = (Biome)16, enabled = true, dropsEnabled = false } }, { "FulingShaman", new CreatureValues { spawnCost = 40, prefabName = "GoblinShaman", spawnType = "rare", biome = (Biome)16, enabled = true, dropsEnabled = false } }, { "Growth", new CreatureValues { spawnCost = 35, prefabName = "BlobTar", spawnType = "rare", biome = (Biome)16, enabled = true, dropsEnabled = false } }, { "Seeker", new CreatureValues { spawnCost = 30, prefabName = "Seeker", spawnType = "common", biome = (Biome)512, enabled = true, dropsEnabled = false } }, { "SeekerSoldier", new CreatureValues { spawnCost = 75, prefabName = "SeekerBrute", spawnType = "elite", biome = (Biome)512, enabled = true, dropsEnabled = false } }, { "SeekerBrood", new CreatureValues { spawnCost = 10, prefabName = "SeekerBrood", spawnType = "common", biome = (Biome)512, enabled = true, dropsEnabled = false } }, { "Gjall", new CreatureValues { spawnCost = 75, prefabName = "Gjall", spawnType = "elite", biome = (Biome)512, enabled = true, dropsEnabled = false } }, { "Tick", new CreatureValues { spawnCost = 15, prefabName = "Tick", spawnType = "common", biome = (Biome)512, enabled = true, dropsEnabled = false } }, { "DvergerRouge", new CreatureValues { spawnCost = 40, prefabName = "Dverger", spawnType = "rare", biome = (Biome)512, enabled = true, dropsEnabled = false } }, { "DvergerMage", new CreatureValues { spawnCost = 75, prefabName = "DvergerMage", spawnType = "rare", biome = (Biome)512, enabled = true, dropsEnabled = false } }, { "DvergerMageFire", new CreatureValues { spawnCost = 75, prefabName = "DvergerMageFire", spawnType = "rare", biome = (Biome)512, enabled = false, dropsEnabled = false } }, { "DvergerMageIce", new CreatureValues { spawnCost = 75, prefabName = "DvergerMageIce", spawnType = "rare", biome = (Biome)512, enabled = false, dropsEnabled = false } }, { "DvergerMageSupport", new CreatureValues { spawnCost = 75, prefabName = "DvergerMageSupport", spawnType = "elite", biome = (Biome)512, enabled = true, dropsEnabled = false } }, { "Asksvin", new CreatureValues { spawnCost = 70, prefabName = "Asksvin", spawnType = "rare", biome = (Biome)32, enabled = true, dropsEnabled = false } }, { "Charred_Archer", new CreatureValues { spawnCost = 60, prefabName = "Charred_Archer", spawnType = "common", biome = (Biome)32, enabled = true, dropsEnabled = false } }, { "Charred_Twitcher", new CreatureValues { spawnCost = 45, prefabName = "Charred_Twitcher", spawnType = "common", biome = (Biome)32, enabled = true, dropsEnabled = false } }, { "Charred_Mage", new CreatureValues { spawnCost = 100, prefabName = "Charred_Mage", spawnType = "elite", biome = (Biome)32, enabled = true, dropsEnabled = false } }, { "Charred_Melee", new CreatureValues { spawnCost = 75, prefabName = "Charred_Melee", spawnType = "rare", biome = (Biome)32, enabled = true, dropsEnabled = false } }, { "FallenValkyrie", new CreatureValues { spawnCost = 100, prefabName = "FallenValkyrie", spawnType = "elite", biome = (Biome)32, enabled = true, dropsEnabled = false } }, { "BlobLava", new CreatureValues { spawnCost = 75, prefabName = "BlobLava", spawnType = "rare", biome = (Biome)32, enabled = true, dropsEnabled = false } }, { "Morgen", new CreatureValues { spawnCost = 85, prefabName = "Morgen", spawnType = "elite", biome = (Biome)32, enabled = true, dropsEnabled = false } }, { "Volture", new CreatureValues { spawnCost = 30, prefabName = "Volture", spawnType = "common", biome = (Biome)32, enabled = true, dropsEnabled = false } }, { "Eikthyr", new CreatureValues { spawnCost = 40, prefabName = "Eikthyr", spawnType = "unique", biome = (Biome)1, enabled = true, dropsEnabled = false } }, { "TheElder", new CreatureValues { spawnCost = 180, prefabName = "gd_king", spawnType = "unique", biome = (Biome)8, enabled = true, dropsEnabled = false } }, { "Bonemass", new CreatureValues { spawnCost = 250, prefabName = "Bonemass", spawnType = "unique", biome = (Biome)2, enabled = true, dropsEnabled = false } }, { "Moder", new CreatureValues { spawnCost = 320, prefabName = "Dragon", spawnType = "unique", biome = (Biome)4, enabled = true, dropsEnabled = false } }, { "Yagluth", new CreatureValues { spawnCost = 450, prefabName = "GoblinKing", spawnType = "unique", biome = (Biome)16, enabled = true, dropsEnabled = false } }, { "TheQueen", new CreatureValues { spawnCost = 600, prefabName = "SeekerQueen", spawnType = "unique", biome = (Biome)512, enabled = true, dropsEnabled = false } }, { "Fader", new CreatureValues { spawnCost = 800, prefabName = "Fader", spawnType = "unique", biome = (Biome)32, enabled = true, dropsEnabled = false } } }; public static void UpdateSpawnableCreatures(SpawnableCreatureCollection spawnables) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) SpawnableCreatures.Clear(); foreach (KeyValuePair creature in spawnables.Creatures) { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Updating Creature Entry {creature.Key} Prefab:{creature.Value.prefabName} SpawnCost:{creature.Value.spawnCost} Biome:{creature.Value.biome} SpawnType:{creature.Value.spawnType}"); } SpawnableCreatures.Add(creature.Key, creature.Value); } } public static string YamlCreatureDefinition() { SpawnableCreatureCollection spawnableCreatureCollection = new SpawnableCreatureCollection(); spawnableCreatureCollection.Creatures = SpawnableCreatures; return CONST.yamlserializer.Serialize((object)spawnableCreatureCollection); } } public class WaveStyles { public enum WaveStyleName { Tutorial, Starter, Easy, Normal, Hard, VeryHard, Expert, Extreme, Dynamic, ElitesOnly, RaresOnly, CommonOnly, TutorialBoss, EasyBoss, Boss, DynamicBoss } private const string COMMON = "common"; private const string RARE = "rare"; private const string ELITE = "elite"; private const string UNIQUE = "unique"; private const string MEADOWS = "Meadows"; private const string BLACKFOREST = "BlackForest"; private const string SWAMP = "Swamp"; private const string MOUNTAIN = "Mountain"; private const string PLAINS = "Plains"; private const string MISTLANDS = "Mistlands"; private const string ASHLANDS = "Ashlands"; private static Dictionary WaveGenerationStyles = new Dictionary { { WaveStyleName.Tutorial, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("common", 30), new WaveFormatEntry("common", 30) } } }, { WaveStyleName.Starter, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("common", 25), new WaveFormatEntry("common", 25), new WaveFormatEntry("common", 15) } } }, { WaveStyleName.Easy, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("rare", 15), new WaveFormatEntry("common", 25), new WaveFormatEntry("common", 30) } } }, { WaveStyleName.Normal, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("rare", 15), new WaveFormatEntry("rare", 10), new WaveFormatEntry("common", 30), new WaveFormatEntry("common", 20) } } }, { WaveStyleName.Hard, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("elite", 5), new WaveFormatEntry("rare", 20), new WaveFormatEntry("common", 20), new WaveFormatEntry("common", 30) } } }, { WaveStyleName.VeryHard, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("elite", 10), new WaveFormatEntry("rare", 25), new WaveFormatEntry("common", 20), new WaveFormatEntry("common", 30) } } }, { WaveStyleName.Expert, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("elite", 10), new WaveFormatEntry("rare", 15), new WaveFormatEntry("rare", 15), new WaveFormatEntry("common", 20), new WaveFormatEntry("common", 30) } } }, { WaveStyleName.Extreme, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("elite", 15), new WaveFormatEntry("rare", 20), new WaveFormatEntry("rare", 15), new WaveFormatEntry("common", 20), new WaveFormatEntry("common", 25) } } }, { WaveStyleName.Dynamic, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("elite", 15), new WaveFormatEntry("rare", 25), new WaveFormatEntry("rare", 15), new WaveFormatEntry("common", 20), new WaveFormatEntry("common", 25) } } }, { WaveStyleName.ElitesOnly, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("elite", 25), new WaveFormatEntry("elite", 25), new WaveFormatEntry("elite", 25) } } }, { WaveStyleName.RaresOnly, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("rare", 25), new WaveFormatEntry("rare", 25), new WaveFormatEntry("rare", 25) } } }, { WaveStyleName.CommonOnly, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("common", 25), new WaveFormatEntry("common", 25), new WaveFormatEntry("common", 25) } } }, { WaveStyleName.TutorialBoss, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("unique", 100), new WaveFormatEntry("common", 30), new WaveFormatEntry("common", 40) } } }, { WaveStyleName.EasyBoss, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("unique", 100), new WaveFormatEntry("rare", 30), new WaveFormatEntry("common", 30) } } }, { WaveStyleName.Boss, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("unique", 100), new WaveFormatEntry("elite", 20), new WaveFormatEntry("rare", 30), new WaveFormatEntry("common", 25) } } }, { WaveStyleName.DynamicBoss, new WaveGenerationFormat { waveFormats = new List { new WaveFormatEntry("unique", 100), new WaveFormatEntry("elite", 20), new WaveFormatEntry("rare", 20), new WaveFormatEntry("rare", 20), new WaveFormatEntry("common", 20), new WaveFormatEntry("common", 20) } } } }; public static WaveGenerationFormat GetWaveStyle(WaveStyleName waveStyle) { return WaveGenerationStyles[waveStyle]; } public static void UpdateWaveDefinition(WaveFormatCollection waveStyles) { WaveGenerationStyles.Clear(); foreach (KeyValuePair waveFormat in waveStyles.WaveFormats) { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Updating Wavestyle Entry {waveFormat.Key} {waveFormat.Value}"); } if (!Enum.IsDefined(typeof(WaveStyleName), waveFormat.Key)) { _ = Enum.GetValues(typeof(WaveStyleName)).Length + 1; } WaveGenerationStyles.Add(waveFormat.Key, waveFormat.Value); } } public static string YamlWaveDefinition() { WaveFormatCollection waveFormatCollection = new WaveFormatCollection(); waveFormatCollection.WaveFormats = WaveGenerationStyles; return CONST.yamlserializer.Serialize((object)waveFormatCollection); } } } namespace ValheimFortress.Common { internal class JotunnPieceLoader { internal static AssetBundle Assets; internal static List resourceDefinitions = new List(); public bool AddPiece(PieceDefinition itemdef) { resourceDefinitions.Add(itemdef); return true; } public bool BatchSetup(AssetBundle assetBundle, bool reverse_order = true) { Assets = assetBundle; if (reverse_order) { resourceDefinitions.Reverse(); } WireConfigs(); bool flag = false; if ((Object)(object)ZNet.instance != (Object)null && ZNetExtension.IsServerInstance(ZNet.instance)) { flag = true; } if (!flag) { BatchAddPieces(); SetupOnChange(); } VFConfig.cfg.Save(); VFConfig.SaveOnSet(enabled: true); return true; } private static bool WireConfigs() { foreach (PieceDefinition resourceDefinition in resourceDefinitions) { resourceDefinition.DisplayName = string.Join("", resourceDefinition.Name.Split((string[]?)null, StringSplitOptions.RemoveEmptyEntries)); resourceDefinition.enabled_cfg = VFConfig.BindServerConfig($"{resourceDefinition.Category} - {resourceDefinition.Name}", resourceDefinition.DisplayName + "-craftable", resourceDefinition.enabled, "Enable/Disables " + resourceDefinition.Name + "."); resourceDefinition.requiredWorkstation_cfg = VFConfig.BindServerConfig($"{resourceDefinition.Category} - {resourceDefinition.Name}", resourceDefinition.DisplayName + "-requiredBench", resourceDefinition.requiredWorkstation, "Sets the required crafting station for " + resourceDefinition.Name + "."); resourceDefinition.recipe.recipeConfig = VFConfig.BindServerConfig($"{resourceDefinition.Category} - {resourceDefinition.Name}", resourceDefinition.DisplayName + "-recipe", BuildStringCraftingCostFromItemDef(resourceDefinition), "Recipe for " + resourceDefinition.Name + ". Should be in the format of Prefab,Amount,refund|Prefab,Amount,refund eg: Wood,12,false|Stone,2,true"); if (!ValidateRecipeConfig(resourceDefinition)) { BuildRecipeReqsFromDefault(resourceDefinition); } } return true; } private static bool BatchAddPieces() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown foreach (PieceDefinition resourceDefinition in resourceDefinitions) { GameObject val = Assets.LoadAsset($"Assets/Custom/Pieces/{resourceDefinition.Category}/{resourceDefinition.prefab}.prefab"); Sprite icon = Assets.LoadAsset("Assets/Custom/Icons/" + resourceDefinition.icon + ".png"); if (resourceDefinition.setupScripts != null) { resourceDefinition.setupScripts(val); } PieceConfig val2 = new PieceConfig { PieceTable = PieceTables.Hammer, CraftingStation = (resourceDefinition.requiredWorkstation_cfg.Value ?? ""), Enabled = resourceDefinition.enabled_cfg.Value, Icon = icon, Category = resourceDefinition.Category.ToString(), Requirements = resourceDefinition.recipe.recipeReqs.ToArray() }; PieceManager.Instance.AddPiece(new CustomPiece(val, true, val2)); } return true; } private static bool SetupOnChange() { foreach (PieceDefinition piecedef in resourceDefinitions) { piecedef.enabled_cfg.SettingChanged += delegate { if (((Behaviour)ZNet.instance).enabled) { Piece component = PrefabManager.Instance.GetPrefab(piecedef.prefab).GetComponent(); if ((Object)(object)component != (Object)null) { Logger.LogInfo($"Setting {piecedef.Name} to {piecedef.enabled_cfg.Value}."); component.m_enabled = piecedef.enabled_cfg.Value; } } }; piecedef.requiredWorkstation_cfg.SettingChanged += delegate { if (((Behaviour)ZNet.instance).enabled) { RequiredBench_SettingChanged(piecedef); } }; piecedef.recipe.recipeConfig.SettingChanged += delegate { if (((Behaviour)ZNet.instance).enabled && ValidateRecipeConfig(piecedef)) { BuildRequirements(piecedef); Piece component = PrefabManager.Instance.GetPrefab(piecedef.prefab).GetComponent(); if ((Object)(object)component != (Object)null) { Logger.LogInfo("Updating crafting cost for " + piecedef.prefab); component.m_resources = piecedef.recipe.resolvedRequirements; } } }; } return true; } private static void BuildRequirements(PieceDefinition piecedef) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown Requirement[] array = (Requirement[])(object)new Requirement[piecedef.recipe.recipeReqs.Count]; int num = 0; foreach (RequirementConfig recipeReq in piecedef.recipe.recipeReqs) { Requirement val = new Requirement(); GameObject prefab = PrefabManager.Instance.GetPrefab(recipeReq.Item.Replace("JVLmock_", "")); val.m_resItem = ((prefab != null) ? prefab.GetComponent() : null); val.m_amount = recipeReq.Amount; val.m_recover = recipeReq.Recover; array[num] = val; num++; } piecedef.recipe.resolvedRequirements = array; } private static void RequiredBench_SettingChanged(PieceDefinition piecedef) { CraftingStation val = null; if (piecedef.requiredWorkstation_cfg.Value == "" || piecedef.requiredWorkstation_cfg.Value == null || piecedef.requiredWorkstation_cfg.Value.ToLower() == "NONE") { Logger.LogInfo("Setting required crafting station to none."); val = null; } else { GameObject prefab = PrefabManager.Instance.GetPrefab(piecedef.requiredWorkstation_cfg.Value); val = ((prefab != null) ? prefab.GetComponent() : null); if ((Object)(object)val == (Object)null) { Logger.LogWarning("Required crafting station does not exist or does not have a crafting station componet, check your prefab name (" + piecedef.requiredWorkstation_cfg.Value + ")."); return; } } Logger.LogInfo("Setting required crafting station to " + piecedef.requiredWorkstation_cfg.Value + "."); Piece component = PrefabManager.Instance.GetPrefab(piecedef.prefab).GetComponent(); if ((Object)(object)component != (Object)null) { component.m_craftingStation = val; } } private static void Enabled_cfg_SettingChanged(object sender, EventArgs e) { throw new NotImplementedException(); } private static void BuildRecipeReqsFromDefault(PieceDefinition piecedef) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown List list = new List(); foreach (PieceIngredient recipeItem in piecedef.recipe.recipeItems) { list.Add(new RequirementConfig { Item = recipeItem.prefab, Amount = recipeItem.amount, Recover = recipeItem.refund }); } piecedef.recipe.recipeReqs = list; } private static string BuildStringCraftingCostFromItemDef(PieceDefinition piecedef) { List list = new List(); foreach (PieceIngredient recipeItem in piecedef.recipe.recipeItems) { list.Add($"{recipeItem.prefab},{recipeItem.amount},{recipeItem.refund}"); } return string.Join("|", list); } private static bool ValidateRecipeConfig(PieceDefinition piecedef) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown List list = new List(); try { string[] array = piecedef.recipe.recipeConfig.Value.Split(new char[1] { '|' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ',' }); if (array2.Length == 1) { return false; } if (array2.Length != 3) { Logger.LogWarning("Invalid (" + piecedef.Name + ") cost config detected: " + text + ". Needs three entries eg: Wood,1,true"); return false; } list.Add(new RequirementConfig { Item = array2[0], Amount = int.Parse(array2[1]), Recover = bool.Parse(array2[2]) }); } piecedef.recipe.recipeReqs = list; return true; } catch { Logger.LogWarning("Recipe is Invalid. Should have the format of Wood,1,1|Stone,2,0 - Prefab,cost,upgrade."); return false; } } } internal enum PieceCategory { Misc, Crafting, Furniture, Building, HeavyBuild, Feasts, Food, Mead } internal class PieceDefinition { public string Name { get; set; } public string DisplayName { get; set; } public PieceCategory Category { get; set; } public string prefab { get; set; } public string icon { get; set; } public ConfigEntry enabled_cfg { get; set; } public bool enabled { get; set; } = true; public ConfigEntry requiredWorkstation_cfg { get; set; } public string requiredWorkstation { get; set; } public Action setupScripts { get; set; } public PieceCostDefinition recipe { get; set; } } internal class PieceCostDefinition { public ConfigEntry recipeConfig { get; set; } public List recipeItems { get; set; } public List recipeReqs { get; set; } public Requirement[] resolvedRequirements { get; set; } } internal class PieceIngredient { public string prefab { get; set; } public int amount { get; set; } public bool refund { get; set; } } internal static class Compression { public static string CompressToBase64(this string data) { return Convert.ToBase64String(Encoding.UTF8.GetBytes(data).Compress()); } public static string DecompressFromBase64(this string data) { return Encoding.UTF8.GetString(Convert.FromBase64String(data).Decompress()); } public static byte[] Compress(this byte[] data) { using MemoryStream stream = new MemoryStream(data); using MemoryStream memoryStream = new MemoryStream(); stream.CompressTo(memoryStream); return memoryStream.ToArray(); } public static byte[] Decompress(this byte[] data) { using MemoryStream stream = new MemoryStream(data); using MemoryStream memoryStream = new MemoryStream(); stream.DecompressTo(memoryStream); return memoryStream.ToArray(); } public static void CompressTo(this Stream stream, Stream outputStream) { using GZipStream gZipStream = new GZipStream(outputStream, CompressionMode.Compress); stream.CopyTo(gZipStream); gZipStream.Flush(); } public static void DecompressTo(this Stream stream, Stream outputStream) { using GZipStream gZipStream = new GZipStream(stream, CompressionMode.Decompress); gZipStream.CopyTo(outputStream); } } } namespace ValheimFortress.Challenge { internal class ArenaShrine : GenericShrine { private ArenaShrineUI ui_controller; private Vector3[] arena_spawn_locations = (Vector3[])(object)new Vector3[0]; private short fail_to_start; public override string GetHoverName() { return Localization.instance.Localize("$piece_shrine_of_gladiator"); } public override string GetHoverText() { string text = "[$KEY_Use] $piece_shrine_of_gladiator"; return Localization.instance.Localize(text); } public override bool Interact(Humanoid user, bool hold, bool alt) { if (hold) { return false; } if (base.challenge_active.Get()) { ((Character)Player.m_localPlayer).Message((MessageType)2, $"Creatures remaining {base.spawned_creatures.Get()}", 0, (Sprite)null); ui_controller.DisplayCancelUI(); } else { ui_controller.DisplayUI(); } return true; } public override void StartChallengeMode() { if (!base.challenge_active.Get()) { base.challenge_active.Set(value: true); base.currentPhase.Set(0); BeginPhaseSpawn(); spawn_controller.TrySpawningPhase(5f, send_message: false, wave_phases_definitions.hordePhases[base.currentPhase.Get()], ((Component)this).gameObject, arena_spawn_locations); SetCurrentCreatureList(wave_phases_definitions.hordePhases[base.currentPhase.Get()]); Logger.LogInfo((object)$"Challenge started. Level: {base.selected_level.Get()} Reward: {base.selected_reward.Get()}"); base.start_challenge.Set(value: false); base.currentPhase.Set(base.currentPhase.Get() + 1); Logger.LogInfo((object)"Start challenge functions completed. Challenge started!"); } else { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Challenge mode is already active."); } fail_to_start++; } if (fail_to_start > 3) { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Challenge mode failed to start, resetting."); } base.challenge_active.Set(value: false); base.wave_definition_ready.Set(value: false); base.spawn_locations_ready.Set(value: false); fail_to_start = 0; base.currentPhase.Set(0); base.start_challenge.Set(value: true); } } public override void Update() { //IL_0058: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) if (!zNetView.IsValid()) { return; } if ((Object)(object)ui_controller == (Object)null || (Object)(object)spawn_controller == (Object)null || arena_spawn_locations.Length == 0) { spawn_controller = ((Component)this).gameObject.GetComponent(); arena_spawn_locations = (Vector3[])(object)new Vector3[3] { shrine_spawnpoint.transform.position, shrine_spawnpoint.transform.position, shrine_spawnpoint.transform.position }; ui_controller = ((Component)this).gameObject.GetComponent(); } if (ui_controller.IsShrineOrCancelUIVisible() && Input.GetKeyDown((KeyCode)27)) { ui_controller.HideUI(); ui_controller.HideCancelUI(); } if (base.challenge_active.Get()) { EnablePortal(); } else if (base.portal_disabled.Get()) { Disableportal(); } NoteOwnershipState(zNetView.IsOwner()); if (!zNetView.IsOwner()) { return; } if (base.start_challenge.Get()) { if (!base.wave_definition_ready.Get()) { ChallengeLevelDefinition levelDefinition = ChallengeLevels.GetChallengeLevelDefinitions().ElementAt(base.selected_level.Get()); wave_phases_definitions = Levels.generateRandomWaveWithOptions(levelDefinition, base.hard_mode.Get(), base.boss_mode.Get(), base.siege_mode.Get(), VFConfig.ArenaShrineMaxCreaturesPerWave.Value); base.wave_definition_ready.Set(value: true); } if (base.wave_definition_ready.Get()) { SendUpdatedPhaseConfigs(); StartChallengeMode(); } } else { if (!base.challenge_active.Get()) { return; } ReconcileIfDue(); CheckProgressWatchdog(); if (!local_enemies_synced) { local_enemies_synced = true; ((MonoBehaviour)this).StartCoroutine(ReconnectUnlinkedCreatures(shrine_spawnpoint.transform.position, ((Component)this).gameObject.GetComponent())); } if (wave_phases_definitions == null || wave_phases_definitions.hordePhases == null) { Logger.LogInfo((object)"Shrine is missing its wave definition, regenerating it."); ChallengeLevelDefinition levelDefinition2 = ChallengeLevels.GetChallengeLevelDefinitions().ElementAt(base.selected_level.Get()); wave_phases_definitions = Levels.generateRandomWaveWithOptions(levelDefinition2, base.hard_mode.Get(), base.boss_mode.Get(), base.siege_mode.Get(), VFConfig.ChallengeShrineMaxCreaturesPerWave.Value); base.wave_definition_ready.Set(value: true); } else { if (wave_phases_definitions.hordePhases.Count <= 0 || !ShouldAdvancePhase()) { return; } if (RemainingPhases()) { base.should_add_creature_beacons.Set(value: false); base.force_next_phase.Set(value: false); BeginPhaseSpawn(); int num = base.currentPhase.Get(); spawn_controller.TrySpawningPhase(10f, send_message: true, wave_phases_definitions.hordePhases[num], ((Component)this).gameObject, arena_spawn_locations); SetCurrentCreatureList(wave_phases_definitions.hordePhases[num]); base.currentPhase.Set(num + 1); return; } Logger.LogInfo((object)"Challenge complete! Spawning reward."); List list = new List(); Player.GetPlayersInRange(((Component)this).transform.position, VFConfig.ShrineAnnouncementRange.Value, list); foreach (Player item in list) { ((Character)item).Message((MessageType)2, Localization.instance.Localize("$shrine_challenge_complete"), 0, (Sprite)null); } SpawnReward(shrine_spawnpoint.transform.position); base.challenge_active.Set(value: false); DestroyAllSpawnedCreatures(); base.boss_mode.Set(value: false); base.hard_mode.Set(value: false); base.siege_mode.Set(value: false); base.portal_disabled.Set(value: true); base.force_next_phase.Set(value: false); Disableportal(); wave_phases_definitions = new PhasedWaveTemplate { hordePhases = new List>() }; SendUpdatedPhaseConfigs(); base.wave_definition_ready.Set(value: false); base.spawn_locations_ready.Set(value: false); base.phase_spawned_total.Set(0); base.phase_spawn_in_flight.Set(value: false); base.challenge_progress_time.Set(0); } } } } internal class ArenaShrineUI : GenericShrineUI { public override void AddCreatureFlares() { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Adding creature flares."); } HideCancelUI(); Shrine.NotifyRemainingCreatures(); } public override void Awake() { cleanupPortals = false; CreateStaticUIObjects(); createCancelUI(); UITriggersUpdatePanelSizeOnConfigChangeArena(); Shrine = ((Component)this).GetComponent(); } public override void CancelChallengeButtonClick() { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Cancelling the active challenge."); } HideCancelUI(); Shrine.CancelShrineRun(); } public override void CleanupPortalsButtonClick() { } public override void StartChallenge() { HideUI(); string text = availableRewards[rewardSelector.GetComponent().value]; short num = (short)(short.Parse(ValheimFortress.ReplaceWhitespace(levelSelector.GetComponent().options[levelSelector.GetComponent().value].text.Split(new char[1] { '-' })[0], "")) - 1); List challengeLevelDefinitions = ChallengeLevels.GetChallengeLevelDefinitions(); bool flag = false; if (VFConfig.EnableHardModifier.Value) { flag = hardModeToggle.GetComponent().isOn; } bool flag2 = false; if (VFConfig.EnableBossModifier.Value) { flag2 = bossModeToggle.GetComponent().isOn; } bool flag3 = false; if (VFConfig.EnableSiegeModifer.Value) { flag3 = siegeModeToggle.GetComponent().isOn; } ChallengeLevelDefinition challengeLevelDefinition = challengeLevelDefinitions.ElementAt(num); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Shrine challenge. Selected reward: {text}, selected level ID {num} selected level index: {challengeLevelDefinition.levelIndex}"); } UserInterfaceData.PreparePhase(challengeLevelDefinition, flag2, ((Component)Shrine).gameObject); Shrine.SetLevel(num, challengeLevelDefinition.levelIndex); Shrine.SetReward(text); if (flag) { Shrine.SetHardMode(); } if (flag2) { Shrine.SetBossMode(); } if (flag3) { Shrine.SetSiegeMode(); } Shrine.SetStartChallenge(); } public override void TeleportCreatures() { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Teleporting creatures to the shrine."); } HideCancelUI(); Shrine.TeleportRemainingCreatures(); } public override void DisplayUI() { CreateChallengeUI(ShrineType.Arena); ChallengePanel.SetActive(true); GUIManager.BlockInput(true); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Enabled UI from Shrine object."); } } public override void ApplyAdminFunctions(adminFunctions function, List values) { if (function == adminFunctions.filtername) { Shrine.adminLevelLimits.ForceSet(values); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Set Admin level limit filter."); } } } } internal class ChallengeShrine : GenericShrine { private ChallengeShrineUI ui_controller; private short fail_to_start; public override string GetHoverName() { return Localization.instance.Localize("$piece_shrine_of_challenge"); } public override string GetHoverText() { string text = "[$KEY_Use] $piece_shrine_of_challenge"; return Localization.instance.Localize(text); } public override bool Interact(Humanoid user, bool hold, bool alt) { if (hold) { return false; } if (base.challenge_active.Get()) { ((Character)Player.m_localPlayer).Message((MessageType)2, $"Creatures remaining {base.spawned_creatures.Get()}", 0, (Sprite)null); ui_controller.DisplayCancelUI(); } else { ui_controller.DisplayUI(); Logger.LogInfo((object)$"Challenge UI from {((Object)this).GetInstanceID()}"); } return true; } public override void StartChallengeMode() { if (!base.challenge_active.Get()) { RemoteLocationPortals.DrawMapOverlayAndPortals(base.remote_spawn_locations.Get(), ((Component)this).gameObject.GetComponent(), VFConfig.EnableShrineMapOverlay.Value); base.currentPhase.Set(0); base.challenge_active.Set(value: true); BeginPhaseSpawn(); spawn_controller.TrySpawningPhase(5f, send_message: false, wave_phases_definitions.hordePhases[base.currentPhase.Get()], ((Component)this).gameObject, base.remote_spawn_locations.Get()); SetCurrentCreatureList(wave_phases_definitions.hordePhases[base.currentPhase.Get()]); Logger.LogInfo((object)$"Challenge started. Level: {base.selected_level.Get()} Reward: {base.selected_reward.Get()}"); base.start_challenge.Set(value: false); base.currentPhase.Set(base.currentPhase.Get() + 1); Logger.LogInfo((object)"Start challenge functions completed. Challenge started!"); } else { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Challenge mode is already active."); } fail_to_start++; } if (fail_to_start > 3) { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Challenge mode failed to start, resetting."); } base.challenge_active.Set(value: false); base.wave_definition_ready.Set(value: false); base.spawn_locations_ready.Set(value: false); fail_to_start = 0; base.currentPhase.Set(0); base.start_challenge.Set(value: true); } } public override void Update() { //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) if (!zNetView.IsValid()) { return; } if ((Object)(object)ui_controller == (Object)null || (Object)(object)spawn_controller == (Object)null) { spawn_controller = ((Component)this).gameObject.GetComponent(); ui_controller = ((Component)this).gameObject.GetComponent(); } if (ui_controller.IsShrineOrCancelUIVisible() && Input.GetKeyDown((KeyCode)27)) { ui_controller.HideUI(); ui_controller.HideCancelUI(); } if (base.challenge_active.Get()) { EnablePortal(); } else if (base.portal_disabled.Get()) { Disableportal(); } NoteOwnershipState(zNetView.IsOwner()); if (!zNetView.IsOwner()) { return; } if (base.start_challenge.Get()) { if (!base.wave_definition_ready.Get() && !base.spawn_locations_ready.Get()) { ChallengeLevelDefinition levelDefinition = ChallengeLevels.GetChallengeLevelDefinitions().ElementAt(base.selected_level.Get()); wave_phases_definitions = Levels.generateRandomWaveWithOptions(levelDefinition, base.hard_mode.Get(), base.boss_mode.Get(), base.siege_mode.Get(), VFConfig.ChallengeShrineMaxCreaturesPerWave.Value); base.wave_definition_ready.Set(value: true); ((MonoBehaviour)this).StartCoroutine(RemoteLocationPortals.DetermineRemoteSpawnLocations(((Component)this).gameObject, ((Component)this).gameObject.GetComponent())); } if (base.wave_definition_ready.Get() && base.spawn_locations_ready.Get()) { SendUpdatedPhaseConfigs(); StartChallengeMode(); } } else { if (!base.challenge_active.Get()) { return; } ReconcileIfDue(); CheckProgressWatchdog(); if (!local_enemies_synced) { local_enemies_synced = true; ((MonoBehaviour)this).StartCoroutine(ReconnectUnlinkedCreatures(shrine_spawnpoint.transform.position, ((Component)this).gameObject.GetComponent())); } if (wave_phases_definitions == null || wave_phases_definitions.hordePhases == null) { Logger.LogInfo((object)"Shrine is missing its wave definition, regenerating it."); ChallengeLevelDefinition levelDefinition2 = ChallengeLevels.GetChallengeLevelDefinitions().ElementAt(base.selected_level.Get()); wave_phases_definitions = Levels.generateRandomWaveWithOptions(levelDefinition2, base.hard_mode.Get(), base.boss_mode.Get(), base.siege_mode.Get(), VFConfig.ChallengeShrineMaxCreaturesPerWave.Value); RemoteLocationPortals.DrawMapOverlayAndPortals(base.remote_spawn_locations.Get(), ((Component)this).gameObject.GetComponent(), VFConfig.EnableShrineMapOverlay.Value); base.wave_definition_ready.Set(value: true); } else { if (wave_phases_definitions.hordePhases == null || wave_phases_definitions.hordePhases.Count <= 0 || !ShouldAdvancePhase()) { return; } if (RemainingPhases()) { Logger.LogInfo((object)"Starting next phase"); base.should_add_creature_beacons.Set(value: false); base.force_next_phase.Set(value: false); int num = base.currentPhase.Get(); BeginPhaseSpawn(); spawn_controller.TrySpawningPhase(10f, send_message: true, wave_phases_definitions.hordePhases[num], ((Component)this).gameObject, base.remote_spawn_locations.Get()); SetCurrentCreatureList(wave_phases_definitions.hordePhases[num]); base.currentPhase.Set(num + 1); return; } Logger.LogInfo((object)"Challenge complete! Spawning reward."); List list = new List(); Player.GetPlayersInRange(((Component)this).transform.position, VFConfig.ShrineAnnouncementRange.Value, list); foreach (Player item in list) { ((Character)item).Message((MessageType)2, Localization.instance.Localize("$shrine_challenge_complete"), 0, (Sprite)null); } SpawnReward(shrine_spawnpoint.transform.position); base.challenge_active.Set(value: false); RemoteLocationPortals.ClearMapOverlay(); base.boss_mode.Set(value: false); base.hard_mode.Set(value: false); base.siege_mode.Set(value: false); DestroyAllSpawnedCreatures(); base.force_next_phase.Set(value: false); base.portal_disabled.Set(value: true); Disableportal(); wave_phases_definitions = new PhasedWaveTemplate { hordePhases = new List>() }; SendUpdatedPhaseConfigs(); base.wave_definition_ready.Set(value: false); base.spawn_locations_ready.Set(value: false); base.phase_spawned_total.Set(0); base.phase_spawn_in_flight.Set(value: false); base.challenge_progress_time.Set(0); } } } } internal class ChallengeShrineUI : GenericShrineUI { public override void Awake() { CreateStaticUIObjects(); createCancelUI(); UITriggersUpdatePanelSizeOnConfigChangeChallenge(); Shrine = ((Component)this).GetComponent(); } public override void AddCreatureFlares() { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Adding creature flares."); } HideCancelUI(); Shrine.NotifyRemainingCreatures(); } public override void CancelChallengeButtonClick() { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Cancelling the active challenge."); } HideCancelUI(); Shrine.CancelShrineRun(); } public override void CleanupPortalsButtonClick() { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Cleaning up portals."); } HideCancelUI(); Shrine.CleanupOldPortals(3); } public override void StartChallenge() { HideUI(); string text = availableRewards[rewardSelector.GetComponent().value]; short num = (short)(short.Parse(ValheimFortress.ReplaceWhitespace(levelSelector.GetComponent().options[levelSelector.GetComponent().value].text.Split(new char[1] { '-' })[0], "")) - 1); List challengeLevelDefinitions = ChallengeLevels.GetChallengeLevelDefinitions(); bool flag = false; if (VFConfig.EnableHardModifier.Value) { flag = hardModeToggle.GetComponent().isOn; } bool flag2 = false; if (VFConfig.EnableBossModifier.Value) { flag2 = bossModeToggle.GetComponent().isOn; } bool flag3 = false; if (VFConfig.EnableSiegeModifer.Value) { flag3 = siegeModeToggle.GetComponent().isOn; } ChallengeLevelDefinition challengeLevelDefinition = challengeLevelDefinitions.ElementAt(num); UserInterfaceData.PreparePhase(challengeLevelDefinition, flag2, ((Component)Shrine).gameObject); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Shrine challenge. Selected reward: {text}, selected level ID {num} selected level index: {challengeLevelDefinition.levelIndex}"); } Shrine.SetLevel(num, challengeLevelDefinition.levelIndex); Shrine.SetReward(text); if (flag) { Shrine.SetHardMode(); } if (flag2) { Shrine.SetBossMode(); } if (flag3) { Shrine.SetSiegeMode(); } Shrine.SetStartChallenge(); } public override void TeleportCreatures() { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Teleporting creatures to the shrine."); } HideCancelUI(); Shrine.TeleportRemainingCreatures(); } public override void DisplayUI() { CreateChallengeUI(ShrineType.Challenge); ChallengePanel.SetActive(true); GUIManager.BlockInput(true); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Enabled UI from Shrine object."); } } public override void ApplyAdminFunctions(adminFunctions function, List values) { if (function == adminFunctions.filtername) { Shrine.adminLevelLimits.ForceSet(values); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Set Admin level limit filter."); } } } } internal class ExternalShrine : GenericShrine { private Vector3ZNetProperty api_reward_location; private DictionaryZNetProperty api_scaled_rewards; private DictionaryZNetProperty api_fixed_rewards; private BoolZNetProperty api_creature_drops_enabled; private DictionaryZNetProperty api_creature_drop_overrides; private string api_wave_start_msg; private string api_wave_end_msg; private ListStringZNetProperty api_between_wave_phrases; private BoolZNetProperty api_ordered_phrases; private IntZNetProperty api_phase_message_index; private bool api_draw_map_overlay; public override void Awake() { //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Expected O, but got Unknown //IL_030a: Expected O, but got Unknown if (((Component)this).gameObject.TryGetComponent(ref zNetView) && Object.op_Implicit((Object)(object)zNetView)) { base.spawned_creatures = new IntZNetProperty("spawned_creatures", zNetView, 0); base.hard_mode = new BoolZNetProperty("shrine_hard_mode", zNetView, defaultValue: false); base.boss_mode = new BoolZNetProperty("shrine_boss_mode", zNetView, defaultValue: false); base.siege_mode = new BoolZNetProperty("shrine_siege_mode", zNetView, defaultValue: false); base.challenge_active = new BoolZNetProperty("shrine_challenge_active", zNetView, defaultValue: false); base.start_challenge = new BoolZNetProperty("shrine_start_challenge", zNetView, defaultValue: false); base.selected_level = new IntZNetProperty("shrine_selected_level", zNetView, 0); base.selected_level_index = new IntZNetProperty("selected_level_index", zNetView, 0); base.selected_reward = new StringZNetProperty("shrine_selected_reward", zNetView, "coins"); base.portal_disabled = new BoolZNetProperty("end_of_challenge", zNetView, defaultValue: false); base.should_add_creature_beacons = new BoolZNetProperty("should_add_creature_beacons", zNetView, defaultValue: false); base.currentPhase = new IntZNetProperty("shrine_current_phase", zNetView, 0); base.wave_definition_ready = new BoolZNetProperty("wave_definition_ready", zNetView, defaultValue: false); base.spawn_locations_ready = new BoolZNetProperty("spawn_locations_ready", zNetView, defaultValue: false); base.force_next_phase = new BoolZNetProperty("force_next_phase", zNetView, defaultValue: false); base.phase_spawned_total = new IntZNetProperty("phase_spawned_total", zNetView, 0); base.phase_spawn_in_flight = new BoolZNetProperty("phase_spawn_in_flight", zNetView, defaultValue: false); base.challenge_progress_time = new IntZNetProperty("challenge_progress_time", zNetView, 0); base.remote_spawn_locations = new ArrayVectorZNetProperty("remote_spawn_locations", zNetView, (Vector3[])(object)new Vector3[0]); base.alive_creature_list = new DictionaryZNetProperty("alive_creature_list", zNetView, new Dictionary()); base.spawned_creature_records = new SpawnedCreatureRecordsZNetProperty("spawned_creature_records", zNetView, new List()); api_reward_location = new Vector3ZNetProperty("api_reward_location", zNetView, Vector3.zero); api_scaled_rewards = new DictionaryZNetProperty("api_scaled_rewards", zNetView, new Dictionary()); api_fixed_rewards = new DictionaryZNetProperty("api_fixed_rewards", zNetView, new Dictionary()); api_creature_drops_enabled = new BoolZNetProperty("api_creature_drops_enabled", zNetView, defaultValue: false); api_creature_drop_overrides = new DictionaryZNetProperty("api_creature_drop_overrides", zNetView, new Dictionary()); api_between_wave_phrases = new ListStringZNetProperty("api_between_wave_phrases", zNetView, new List()); api_ordered_phrases = new BoolZNetProperty("api_ordered_phrases", zNetView, defaultValue: false); api_phase_message_index = new IntZNetProperty("api_phase_message_index", zNetView, 0); WaveDefinitionRPC = NetworkManager.Instance.AddRPC("VF_levelsyaml_rpc", new CoroutineHandler(VFConfig.OnServerRecieveConfigs), new CoroutineHandler(base.OnClientReceivePhaseConfigs)); spawn_controller = ((Component)this).gameObject.GetComponent(); if ((Object)(object)spawn_controller == (Object)null) { spawn_controller = ((Component)this).gameObject.AddComponent(); } availablePhases = 0; } } public void BeginApiChallenge(PhasedWaveTemplate waves, Vector3[] spawnPoints, Vector3 rewardLocation, Dictionary scaledRewards, Dictionary fixedRewards, short difficulty, bool hard, bool boss, bool siege, bool enableCreatureDrops, Dictionary creatureDropOverrides, string startMessage, string endMessage, bool drawMapOverlay, List betweenWavePhrases, bool orderedPhrases) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) wave_phases_definitions = waves; availablePhases = waves.hordePhases.Count; SetWaveSpawnPoints(spawnPoints); base.wave_definition_ready.ForceSet(value: true); api_reward_location.ForceSet(rewardLocation); api_scaled_rewards.ForceSet(scaledRewards ?? new Dictionary()); api_fixed_rewards.ForceSet(fixedRewards ?? new Dictionary()); base.selected_level_index.ForceSet(difficulty); base.selected_level.ForceSet(difficulty); base.hard_mode.ForceSet(hard); base.boss_mode.ForceSet(boss); base.siege_mode.ForceSet(siege); api_creature_drops_enabled.ForceSet(enableCreatureDrops); api_creature_drop_overrides.ForceSet(creatureDropOverrides ?? new Dictionary()); api_wave_start_msg = startMessage; api_wave_end_msg = endMessage; api_draw_map_overlay = drawMapOverlay; api_between_wave_phrases.ForceSet(betweenWavePhrases ?? new List()); api_ordered_phrases.ForceSet(orderedPhrases); api_phase_message_index.ForceSet(0); base.start_challenge.ForceSet(value: true); } public override void StartChallengeMode() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) base.currentPhase.Set(0); base.challenge_active.Set(value: true); BeginPhaseSpawn(); if (api_draw_map_overlay) { RemoteLocationPortals.DrawSpawnLocationOverlay(base.remote_spawn_locations.Get(), ((Component)this).gameObject.transform.position); } spawn_controller.TrySpawningPhase(5f, send_message: false, wave_phases_definitions.hordePhases[base.currentPhase.Get()], ((Component)this).gameObject, base.remote_spawn_locations.Get()); SetCurrentCreatureList(wave_phases_definitions.hordePhases[base.currentPhase.Get()]); base.start_challenge.Set(value: false); base.currentPhase.Set(base.currentPhase.Get() + 1); AnnounceToNearbyPlayers(api_wave_start_msg); Logger.LogInfo((object)$"API challenge started. Level: {base.selected_level.Get()} Phases: {availablePhases}"); } public override void Update() { if ((Object)(object)zNetView == (Object)null || !zNetView.IsValid()) { return; } if ((Object)(object)spawn_controller == (Object)null) { spawn_controller = ((Component)this).gameObject.GetComponent(); } NoteOwnershipState(zNetView.IsOwner()); if (!zNetView.IsOwner()) { return; } if (base.start_challenge.Get()) { if (base.wave_definition_ready.Get() && base.spawn_locations_ready.Get()) { SendUpdatedPhaseConfigs(); StartChallengeMode(); } } else { if (!base.challenge_active.Get()) { return; } ReconcileIfDue(); CheckProgressWatchdog(); if (wave_phases_definitions == null) { Logger.LogWarning((object)"API challenge runner lost its wave definition; finishing the run."); FinishChallenge(); } else if (wave_phases_definitions.hordePhases != null && wave_phases_definitions.hordePhases.Count > 0 && ShouldAdvancePhase()) { if (RemainingPhases()) { base.should_add_creature_beacons.Set(value: false); base.force_next_phase.Set(value: false); int index = base.currentPhase.Get(); BeginPhaseSpawn(); spawn_controller.TrySpawningPhase(10f, send_message: true, wave_phases_definitions.hordePhases[index], ((Component)this).gameObject, base.remote_spawn_locations.Get()); SetCurrentCreatureList(wave_phases_definitions.hordePhases[index]); int count = wave_phases_definitions.hordePhases.Count; int num = base.currentPhase.Get() + 1; base.currentPhase.Set((count <= num) ? count : num); } else { FinishChallenge(); } } } } private void FinishChallenge() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) Logger.LogInfo((object)"API challenge complete! Spawning rewards."); AnnounceToNearbyPlayers(string.IsNullOrEmpty(api_wave_end_msg) ? "$shrine_challenge_complete" : api_wave_end_msg); Vector3 spawn_position = api_reward_location.Get(); Dictionary dictionary = api_scaled_rewards.Get(); if (dictionary != null && dictionary.Count > 0) { SpawnMultiRewardsDirectly(dictionary, (short)base.selected_level_index.Get(), spawn_position, base.hard_mode.Get(), base.boss_mode.Get(), base.siege_mode.Get()); } Dictionary dictionary2 = api_fixed_rewards.Get(); if (dictionary2 != null && dictionary2.Count > 0) { SpawnFixedRewardsDirectly(dictionary2, spawn_position); } base.challenge_active.Set(value: false); RemoteLocationPortals.ClearMapOverlay(); DestroyAllSpawnedCreatures(); base.boss_mode.Set(value: false); base.hard_mode.Set(value: false); base.siege_mode.Set(value: false); base.force_next_phase.Set(value: false); wave_phases_definitions = new PhasedWaveTemplate { hordePhases = new List>() }; SendUpdatedPhaseConfigs(); base.currentPhase.Set(0); base.wave_definition_ready.Set(value: false); base.spawn_locations_ready.Set(value: false); base.phase_spawned_total.Set(0); base.phase_spawn_in_flight.Set(value: false); base.challenge_progress_time.Set(0); ((MonoBehaviour)this).StartCoroutine(DestroyRunnerAfterDelay(10f)); } private IEnumerator DestroyRunnerAfterDelay(float delay) { yield return (object)new WaitForSeconds(delay); if ((Object)(object)zNetView != (Object)null && zNetView.IsValid() && zNetView.IsOwner()) { ZNetScene.instance.Destroy(((Component)this).gameObject); } } private void AnnounceToNearbyPlayers(string message) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(message)) { return; } List list = new List(); Player.GetPlayersInRange(((Component)this).transform.position, VFConfig.ShrineAnnouncementRange.Value, list); foreach (Player item in list) { ((Character)item).Message((MessageType)2, Localization.instance.Localize(message), 0, (Sprite)null); } } public override bool ShouldDropLoot(string creature) { Dictionary dictionary = api_creature_drop_overrides.Get(); if (dictionary != null && dictionary.TryGetValue(creature, out var value)) { return value != 0; } return api_creature_drops_enabled.Get(); } public override string SelectPhasePauseMessage() { List list = api_between_wave_phrases.Get(); if (list == null || list.Count == 0) { return null; } if (api_ordered_phrases.Get()) { int index = api_phase_message_index.Get() % list.Count; api_phase_message_index.Set(api_phase_message_index.Get() + 1); return list[index]; } return list[Random.Range(0, list.Count)]; } public override string GetHoverName() { return ""; } public override string GetHoverText() { return ""; } public override bool Interact(Humanoid user, bool hold, bool alt) { return false; } } public static class Patches { [HarmonyPatch(typeof(Character), "OnDeath")] [HarmonyPriority(700)] public static class DisableDropsCheck { public static void Prefix(Character __instance) { if (!__instance.m_nview.GetZDO().GetBool("VFDrops", true)) { __instance.m_onDeath = null; } } } } public class CONST { public const string COMMON = "common"; public const string RARE = "rare"; public const string ELITE = "elite"; public const string UNIQUE = "unique"; public const string MEADOWS = "Meadows"; public const string BLACKFOREST = "BlackForest"; public const string SWAMP = "Swamp"; public const string MOUNTAIN = "Mountain"; public const string PLAINS = "Plains"; public const string MISTLANDS = "Mistlands"; public const string ASHLANDS = "Ashlands"; public const string NONE = "None"; public const string EIKYTHR = "Eikythr"; public const string ELDER = "TheElder"; public const string BONEMASS = "BoneMass"; public const string MODER = "Moder"; public const string YAGLUTH = "Yagluth"; public const string QUEEN = "TheQueen"; public const string FADER = "Fader"; public static IDeserializer yamldeserializer = ((BuilderSkeleton)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build(); public static ISerializer yamlserializer = ((BuilderSkeleton)new SerializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).DisableAliases().Build(); } public enum ShrineType { Challenge, Arena, Wild } public class ExternalNoUIShrineConfiguration { public string shrineName { get; set; } public string shrineInteractionMessage { get; set; } public string shrineUnacceptedTributeMessage { get; set; } public string shrineLargerTributeRequiredMessage { get; set; } public List shrineLevelsConfig { get; set; } } public class ExternalShrineLevelConfiguration { public string tributePrefab { get; set; } public short tributeAmount { get; set; } public Dictionary rewards { get; set; } public string waveStartMessage { get; set; } public string waveEndMessage { get; set; } public ExternalShrineLevel wildLevelDefinition { get; set; } } public class WildShrineConfigurationCollection { public List WildShrines { get; set; } } [DataContract] public class WildShrineConfiguration { public string definitionForWildShrine { get; set; } public string wildShrineNameLocalization { get; set; } public string wildShrineRequestLocalization { get; set; } public string shrine_unaccepted_tribute_localization { get; set; } public string shrine_larger_tribute_required_localization { get; set; } public List wildShrineLevelsConfig { get; set; } } [DataContract] public class WildShrineLevelConfiguration { public string tributeName { get; set; } public short tributeAmount { get; set; } public Dictionary rewards { get; set; } public bool hardMode { get; set; } public bool siegeMode { get; set; } public string wildshrine_wave_start_localization { get; set; } public string wildshrine_wave_end_localization { get; set; } public WildLevelDefinition wildLevelDefinition { get; set; } } [DataContract] public class HoardConfig { public string creature { get; set; } public string prefab { get; set; } public short amount { get; set; } public short stars { get; set; } } [DataContract] public class PhasedWaveTemplate { public List> hordePhases { get; set; } } [DataContract] public class CreatureValues { public short spawnCost { get; set; } public string prefabName { get; set; } public string spawnType { get; set; } public Biome biome { get; set; } public bool enabled { get; set; } public bool dropsEnabled { get; set; } } [DataContract] public class RewardEntry { public short resourceCost { get; set; } public string requiredBoss { get; set; } public string resourcePrefab { get; set; } public bool enabled { get; set; } } [DataContract] public class WaveGenerationFormat { public List waveFormats { get; set; } } [DataContract] public struct WaveFormatEntry { public string SpawnType { get; set; } public short SpawnPercentage { get; set; } public WaveFormatEntry(string spawnType, short spawnPercentage) { SpawnType = spawnType; SpawnPercentage = spawnPercentage; } } [DataContract] public class ChallengeLevelDefinition { [DefaultValue("")] public string levelName { get; set; } public short levelIndex { get; set; } [DefaultValue(4)] public short numPhases { get; set; } public Dictionary levelForShrineTypes { get; set; } public string levelMenuLocalization { get; set; } public string requiredGlobalKey { get; set; } public Biome biome { get; set; } public WaveStyles.WaveStyleName waveFormat { get; set; } public WaveStyles.WaveStyleName bossWaveFormat { get; set; } public short maxCreatureFromPreviousBiomes { get; set; } [DefaultValue(1)] public short previousBiomeSearchRange { get; set; } [DefaultValue(0.05f)] public float chancePreviousBiomeCreatureSelected { get; set; } [DefaultValue(true)] public bool previousBiomeCreaturesAddedStarPerBiome { get; set; } public string levelWarningLocalization { get; set; } public string bossLevelWarningLocalization { get; set; } public List levelRewardOptionsLimitedTo { get; set; } public List onlySelectMonsters { get; set; } public List excludeSelectMonsters { get; set; } public SpawnModifiers commonSpawnModifiers { get; set; } public SpawnModifiers rareSpawnModifiers { get; set; } public SpawnModifiers eliteSpawnModifiers { get; set; } public SpawnModifiers uniqueSpawnModifiers { get; set; } } [DataContract] public class WildLevelDefinition { public short levelIndex { get; set; } public Biome biome { get; set; } public WaveStyles.WaveStyleName waveFormat { get; set; } public string levelWarningLocalization { get; set; } public short maxCreaturesPerPhaseOverride { get; set; } public List onlySelectMonsters { get; set; } public List excludeSelectMonsters { get; set; } public SpawnModifiers commonSpawnModifiers { get; set; } public SpawnModifiers rareSpawnModifiers { get; set; } public SpawnModifiers eliteSpawnModifiers { get; set; } public ChallengeLevelDefinition ToChallengeLevelDefinition() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) return new ChallengeLevelDefinition { levelIndex = levelIndex, levelForShrineTypes = new Dictionary { { ShrineType.Wild, true } }, levelMenuLocalization = "", requiredGlobalKey = "NONE", biome = biome, waveFormat = waveFormat, bossWaveFormat = WaveStyles.WaveStyleName.Normal, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = levelWarningLocalization, bossLevelWarningLocalization = "", onlySelectMonsters = onlySelectMonsters, excludeSelectMonsters = excludeSelectMonsters, commonSpawnModifiers = commonSpawnModifiers, rareSpawnModifiers = rareSpawnModifiers, eliteSpawnModifiers = eliteSpawnModifiers, uniqueSpawnModifiers = new SpawnModifiers() }; } } public class ExternalShrineLevel { public Biome Biome { get; set; } public short Difficulty { get; set; } public WaveStyles.WaveStyleName WaveFormat { get; set; } public string LevelWarningLocalization { get; set; } public LevelModifiers levelModifiers { get; set; } public List OnlySelectMonsters { get; set; } public List ExcludeSelectMonsters { get; set; } public SpawnModifiers CommonSpawnModifiers { get; set; } public SpawnModifiers RareSpawnModifiers { get; set; } public SpawnModifiers EliteSpawnModifiers { get; set; } public ChallengeLevelDefinition ToChallengeLevelDefinition() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) return new ChallengeLevelDefinition { levelIndex = Difficulty, levelForShrineTypes = new Dictionary { { ShrineType.Wild, true } }, levelMenuLocalization = "", requiredGlobalKey = "NONE", biome = Biome, waveFormat = WaveFormat, bossWaveFormat = WaveStyles.WaveStyleName.Normal, maxCreatureFromPreviousBiomes = 0, levelWarningLocalization = LevelWarningLocalization, bossLevelWarningLocalization = "", onlySelectMonsters = OnlySelectMonsters, excludeSelectMonsters = ExcludeSelectMonsters, commonSpawnModifiers = CommonSpawnModifiers, rareSpawnModifiers = RareSpawnModifiers, eliteSpawnModifiers = EliteSpawnModifiers, uniqueSpawnModifiers = new SpawnModifiers() }; } } public class SpawnModifiers { public bool linearIncreaseRandomWaveAdjustment { get; set; } public bool linearIncreaseWaveAdjustment { get; set; } public bool linearDecreaseRandomWaveAdjustment { get; set; } public bool partialRandomWaveAdjustment { get; set; } public bool onlyGenerateInSecondHalf { get; set; } public bool AnyEnabled() { if (!linearIncreaseRandomWaveAdjustment && !linearIncreaseWaveAdjustment && !linearDecreaseRandomWaveAdjustment && !partialRandomWaveAdjustment) { return onlyGenerateInSecondHalf; } return true; } } public class LevelModifiers { public bool SiegeMode { get; set; } public bool HardMode { get; set; } public bool BossMode { get; set; } } public class ChallengeLevelDefinitionCollection { public List Levels { get; set; } } public class RewardEntryCollection { public Dictionary Rewards { get; set; } } public class SpawnableCreatureCollection { public Dictionary Creatures { get; set; } } public class WaveFormatCollection { public Dictionary WaveFormats { get; set; } } public abstract class ZNetProperty { protected readonly ZNetView zNetView; public string Key { get; private set; } public T DefaultValue { get; private set; } protected ZNetProperty(string key, ZNetView zNetView, T defaultValue) { Key = key; DefaultValue = defaultValue; this.zNetView = zNetView; } private void ClaimOwnership() { if (!zNetView.IsOwner()) { zNetView.ClaimOwnership(); } } public void Set(T value) { SetValue(value); } public void ForceSet(T value) { ClaimOwnership(); Set(value); } public abstract T Get(); protected abstract void SetValue(T value); } public class BoolZNetProperty : ZNetProperty { public BoolZNetProperty(string key, ZNetView zNetView, bool defaultValue) : base(key, zNetView, defaultValue) { } public override bool Get() { return zNetView.GetZDO().GetBool(base.Key, base.DefaultValue); } protected override void SetValue(bool value) { zNetView.GetZDO().Set(base.Key, value); } } public class IntZNetProperty : ZNetProperty { public IntZNetProperty(string key, ZNetView zNetView, int defaultValue) : base(key, zNetView, defaultValue) { } public override int Get() { return zNetView.GetZDO().GetInt(base.Key, base.DefaultValue); } protected override void SetValue(int value) { zNetView.GetZDO().Set(base.Key, value); } } public class StringZNetProperty : ZNetProperty { public StringZNetProperty(string key, ZNetView zNetView, string defaultValue) : base(key, zNetView, defaultValue) { } public override string Get() { return zNetView.GetZDO().GetString(base.Key, base.DefaultValue); } protected override void SetValue(string value) { zNetView.GetZDO().Set(base.Key, value); } } public class Vector3ZNetProperty : ZNetProperty { public Vector3ZNetProperty(string key, ZNetView zNetView, Vector3 defaultValue) : base(key, zNetView, defaultValue) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) public override Vector3 Get() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) return zNetView.GetZDO().GetVec3(base.Key, base.DefaultValue); } protected override void SetValue(Vector3 value) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) zNetView.GetZDO().Set(base.Key, value); } } public class ListStringZNetProperty : ZNetProperty> { public ListStringZNetProperty(string key, ZNetView zNetView, List defaultValue) : base(key, zNetView, defaultValue) { } public override List Get() { byte[] byteArray = zNetView.GetZDO().GetByteArray(base.Key, (byte[])null); List list = new List(); if (byteArray == null || byteArray.Length == 0) { return list; } using MemoryStream input = new MemoryStream(byteArray); using BinaryReader binaryReader = new BinaryReader(input); int num = binaryReader.ReadInt32(); for (int i = 0; i < num; i++) { list.Add(binaryReader.ReadString()); } return list; } protected override void SetValue(List value) { using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(value.Count); foreach (string item in value) { binaryWriter.Write(item ?? ""); } zNetView.GetZDO().Set(base.Key, memoryStream.ToArray()); } } public class ArrayVectorZNetProperty : ZNetProperty { public ArrayVectorZNetProperty(string key, ZNetView zNetView, Vector3[] defaultValue) : base(key, zNetView, defaultValue) { } public override Vector3[] Get() { byte[] byteArray = zNetView.GetZDO().GetByteArray(base.Key, (byte[])null); if (byteArray == null) { return base.DefaultValue; } Vector3[] array = (Vector3[])(object)new Vector3[byteArray.Length / 12]; for (int i = 0; i < array.Length; i++) { array[i].x = BitConverter.ToSingle(byteArray, i * 12); array[i].y = BitConverter.ToSingle(byteArray, i * 12 + 4); array[i].z = BitConverter.ToSingle(byteArray, i * 12 + 8); } return array; } protected override void SetValue(Vector3[] value) { byte[] array = new byte[value.Length * 12]; for (int i = 0; i < value.Length; i++) { BitConverter.GetBytes(value[i].x).CopyTo(array, i * 12); BitConverter.GetBytes(value[i].y).CopyTo(array, i * 12 + 4); BitConverter.GetBytes(value[i].z).CopyTo(array, i * 12 + 8); } zNetView.GetZDO().Set(base.Key, array); } } public class DictionaryZNetProperty : ZNetProperty> { public DictionaryZNetProperty(string key, ZNetView zNetView, Dictionary defaultValue) : base(key, zNetView, defaultValue) { } public override Dictionary Get() { byte[] byteArray = zNetView.GetZDO().GetByteArray(base.Key, (byte[])null); Dictionary dictionary = new Dictionary(); if (byteArray == null || byteArray.Length == 0) { return dictionary; } using MemoryStream input = new MemoryStream(byteArray); using BinaryReader binaryReader = new BinaryReader(input); int num = binaryReader.ReadInt32(); for (int i = 0; i < num; i++) { string key = binaryReader.ReadString(); short value = binaryReader.ReadInt16(); dictionary[key] = value; } return dictionary; } protected override void SetValue(Dictionary value) { using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(value.Count); foreach (KeyValuePair item in value) { binaryWriter.Write(item.Key); binaryWriter.Write(item.Value); } zNetView.GetZDO().Set(base.Key, memoryStream.ToArray()); } } public struct SpawnedCreatureRecord { public ZDOID Id; public string Name; public SpawnedCreatureRecord(ZDOID id, string name) { //IL_0001: 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) Id = id; Name = name; } } public class SpawnedCreatureRecordsZNetProperty : ZNetProperty> { public SpawnedCreatureRecordsZNetProperty(string key, ZNetView zNetView, List defaultValue) : base(key, zNetView, defaultValue) { } public override List Get() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) byte[] byteArray = zNetView.GetZDO().GetByteArray(base.Key, (byte[])null); List list = new List(); if (byteArray == null || byteArray.Length == 0) { return list; } using MemoryStream input = new MemoryStream(byteArray); using BinaryReader binaryReader = new BinaryReader(input); int num = binaryReader.ReadInt32(); for (int i = 0; i < num; i++) { long num2 = binaryReader.ReadInt64(); uint num3 = binaryReader.ReadUInt32(); string name = binaryReader.ReadString(); list.Add(new SpawnedCreatureRecord(new ZDOID(num2, num3), name)); } return list; } protected override void SetValue(List value) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(value.Count); foreach (SpawnedCreatureRecord item in value) { SpawnedCreatureRecord current = item; ZDOID id = current.Id; binaryWriter.Write(((ZDOID)(ref id)).UserID); binaryWriter.Write(((ZDOID)(ref current.Id)).ID); binaryWriter.Write(current.Name ?? ""); } zNetView.GetZDO().Set(base.Key, memoryStream.ToArray()); } } public class ZDOIDZNetProperty : ZNetProperty { public ZDOIDZNetProperty(string key, ZNetView zNetView, ZDOID defaultValue) : base(key, zNetView, defaultValue) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) public override ZDOID Get() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) return zNetView.GetZDO().GetZDOID(base.Key); } protected override void SetValue(ZDOID value) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) zNetView.GetZDO().Set(base.Key, value); } } public class ListUINTZNetProperty : ZNetProperty> { private BinaryFormatter binFormatter = new BinaryFormatter(); public ListUINTZNetProperty(string key, ZNetView zNetView, List defaultValue) : base(key, zNetView, defaultValue) { } public override List Get() { byte[] byteArray = zNetView.GetZDO().GetByteArray(base.Key, (byte[])null); if (byteArray == null) { return new List(); } MemoryStream serializationStream = new MemoryStream(byteArray); return (List)binFormatter.Deserialize(serializationStream); } protected override void SetValue(List value) { MemoryStream memoryStream = new MemoryStream(); binFormatter.Serialize(memoryStream, value); zNetView.GetZDO().Set(base.Key, memoryStream.ToArray()); } } public class DictionaryZDOIDZNetProperty : ZNetProperty> { private BinaryFormatter binFormatter = new BinaryFormatter(); public DictionaryZDOIDZNetProperty(string key, ZNetView zNetView, Dictionary defaultValue) : base(key, zNetView, defaultValue) { } public override Dictionary Get() { byte[] byteArray = zNetView.GetZDO().GetByteArray(base.Key, (byte[])null); if (byteArray == null) { return new Dictionary(); } MemoryStream serializationStream = new MemoryStream(byteArray); return (Dictionary)binFormatter.Deserialize(serializationStream); } protected override void SetValue(Dictionary value) { MemoryStream memoryStream = new MemoryStream(); binFormatter.Serialize(memoryStream, value); zNetView.GetZDO().Set(base.Key, memoryStream.ToArray()); } } internal abstract class GenericShrine : MonoBehaviour, Hoverable, Interactable { protected ZNetView zNetView; protected bool client_set_creature_beacons; protected bool local_enemies_synced; private bool was_owner; protected List enemies = new List(); protected GameObject shrine_spawnpoint; protected GameObject shrine_portal; protected PhasedWaveTemplate wave_phases_definitions; protected Spawner spawn_controller; protected int availablePhases; protected Rewards reward_controller = new Rewards(); protected int reconcile_tick; protected const int reconcile_tick_interval = 20; protected CustomRPC WaveDefinitionRPC; public IntZNetProperty spawned_creatures { get; set; } public DictionaryZNetProperty alive_creature_list { get; set; } public SpawnedCreatureRecordsZNetProperty spawned_creature_records { get; set; } public BoolZNetProperty hard_mode { get; set; } public BoolZNetProperty boss_mode { get; set; } public BoolZNetProperty siege_mode { get; set; } public BoolZNetProperty challenge_active { get; set; } public BoolZNetProperty start_challenge { get; set; } public IntZNetProperty selected_level { get; set; } public IntZNetProperty selected_level_index { get; set; } public StringZNetProperty selected_reward { get; set; } public BoolZNetProperty portal_disabled { get; set; } public BoolZNetProperty should_add_creature_beacons { get; set; } public IntZNetProperty currentPhase { get; set; } public BoolZNetProperty wave_definition_ready { get; set; } public BoolZNetProperty spawn_locations_ready { get; set; } public BoolZNetProperty force_next_phase { get; set; } public ArrayVectorZNetProperty remote_spawn_locations { get; set; } public ListStringZNetProperty adminLevelLimits { get; set; } public StringZNetProperty adminConfigData { get; set; } public IntZNetProperty phase_spawned_total { get; set; } public BoolZNetProperty phase_spawn_in_flight { get; set; } public IntZNetProperty challenge_progress_time { get; set; } public virtual void Awake() { //IL_0547: Unknown result type (might be due to invalid IL or missing references) //IL_0553: Unknown result type (might be due to invalid IL or missing references) //IL_055d: Expected O, but got Unknown //IL_055d: Expected O, but got Unknown if (!((Component)this).gameObject.TryGetComponent(ref zNetView)) { ((Component)this).gameObject.AddComponent(); zNetView = ((Component)this).gameObject.GetComponent(); zNetView.m_persistent = true; if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"ZnetView was not found, and was added manually."); } } if (Object.op_Implicit((Object)(object)zNetView)) { spawned_creatures = new IntZNetProperty("spawned_creatures", zNetView, 0); hard_mode = new BoolZNetProperty("shrine_hard_mode", zNetView, defaultValue: false); boss_mode = new BoolZNetProperty("shrine_boss_mode", zNetView, defaultValue: false); siege_mode = new BoolZNetProperty("shrine_siege_mode", zNetView, defaultValue: false); challenge_active = new BoolZNetProperty("shrine_challenge_active", zNetView, defaultValue: false); start_challenge = new BoolZNetProperty("shrine_start_challenge", zNetView, defaultValue: false); selected_level = new IntZNetProperty("shrine_selected_level", zNetView, 0); selected_level_index = new IntZNetProperty("selected_level_index", zNetView, 0); selected_reward = new StringZNetProperty("shrine_selected_reward", zNetView, "coins"); portal_disabled = new BoolZNetProperty("end_of_challenge", zNetView, defaultValue: false); should_add_creature_beacons = new BoolZNetProperty("should_add_creature_beacons", zNetView, defaultValue: false); currentPhase = new IntZNetProperty("shrine_current_phase", zNetView, 0); wave_definition_ready = new BoolZNetProperty("wave_definition_ready", zNetView, defaultValue: false); spawn_locations_ready = new BoolZNetProperty("spawn_locations_ready", zNetView, defaultValue: false); force_next_phase = new BoolZNetProperty("force_next_phase", zNetView, defaultValue: false); phase_spawned_total = new IntZNetProperty("phase_spawned_total", zNetView, 0); phase_spawn_in_flight = new BoolZNetProperty("phase_spawn_in_flight", zNetView, defaultValue: false); challenge_progress_time = new IntZNetProperty("challenge_progress_time", zNetView, 0); remote_spawn_locations = new ArrayVectorZNetProperty("remote_spawn_locations", zNetView, (Vector3[])(object)new Vector3[0]); adminLevelLimits = new ListStringZNetProperty("adminLevelLimits", zNetView, new List()); adminConfigData = new StringZNetProperty("adminConfigData", zNetView, "filter:levelname,levelname2"); Dictionary defaultValue = new Dictionary(); alive_creature_list = new DictionaryZNetProperty("alive_creature_list", zNetView, defaultValue); spawned_creature_records = new SpawnedCreatureRecordsZNetProperty("spawned_creature_records", zNetView, new List()); if (VFConfig.EnableDebugMode.Value && zNetView.IsValid()) { Logger.LogInfo((object)"Created Shrine Znet View Values."); Logger.LogInfo((object)$"spawned_creatures={spawned_creatures.Get()}"); Logger.LogInfo((object)$"hard_mode={hard_mode.Get()}"); Logger.LogInfo((object)$"boss_mode={boss_mode.Get()}"); Logger.LogInfo((object)$"siege_mode={siege_mode.Get()}"); Logger.LogInfo((object)$"challenge_active={challenge_active.Get()}"); Logger.LogInfo((object)$"start_challenge={start_challenge.Get()}"); Logger.LogInfo((object)$"selected_level={selected_level.Get()}"); Logger.LogInfo((object)$"selected_level_index={selected_level_index.Get()}"); Logger.LogInfo((object)("selected_reward=" + selected_reward.Get())); Logger.LogInfo((object)$"end_of_challenge={portal_disabled.Get()}"); Logger.LogInfo((object)$"should_add_creature_beacons={should_add_creature_beacons.Get()}"); Logger.LogInfo((object)$"currentPhase={currentPhase.Get()}"); Logger.LogInfo((object)$"wave_definition_ready={wave_definition_ready.Get()}"); Logger.LogInfo((object)$"spawn_locations_ready={spawn_locations_ready.Get()}"); Logger.LogInfo((object)$"force_next_phase={force_next_phase.Get()}"); Logger.LogInfo((object)$"remote_spawn_locations={remote_spawn_locations}"); Logger.LogInfo((object)$"adminLevelLimits={adminLevelLimits.Get()}"); string text = ""; foreach (KeyValuePair item in alive_creature_list.Get()) { text += $"\n{item.Key}={item.Value}"; } Logger.LogInfo((object)$"alive_creature_list size {alive_creature_list.Get().Count} values:{text}"); } WaveDefinitionRPC = NetworkManager.Instance.AddRPC("VF_levelsyaml_rpc", new CoroutineHandler(VFConfig.OnServerRecieveConfigs), new CoroutineHandler(OnClientReceivePhaseConfigs)); } shrine_portal = ((Component)((Component)this).gameObject.transform.Find("portal")).gameObject; shrine_spawnpoint = ((Component)TransformExtensions.FindDeepChild(((Component)this).gameObject.transform, "spawnpoint", (IterativeSearchType)1)).gameObject; availablePhases = 0; } protected void SetCurrentCreatureList(List phase_hoard_configs) { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Updating current creature list."); } Dictionary dictionary = new Dictionary(); foreach (HoardConfig phase_hoard_config in phase_hoard_configs) { if (dictionary.ContainsKey(phase_hoard_config.prefab)) { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Updating creature count for existing creature."); } short value = 0; dictionary.TryGetValue(phase_hoard_config.prefab, out value); dictionary[phase_hoard_config.prefab ?? ""] = (short)(value + phase_hoard_config.amount); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Updating {phase_hoard_config.prefab} {value} + {phase_hoard_config.amount} to existing creature list."); } } else { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Adding {phase_hoard_config.amount} {phase_hoard_config.prefab} to existing creature list."); } dictionary.Add(phase_hoard_config.prefab, phase_hoard_config.amount); } } alive_creature_list.Set(dictionary); } public virtual bool ShouldDropLoot(string creature) { if (Monsters.SpawnableCreatures.TryGetValue(creature, out var value) && value != null) { return value.dropsEnabled; } return true; } public virtual string SelectPhasePauseMessage() { return null; } protected IEnumerator ReconnectUnlinkedCreatures(Vector3 shrine_location, GenericShrine shrine_ref) { ReconcileSpawnedCreatures(); List list = spawned_creature_records.Get(); Logger.LogDebug((object)$"creatures to reconnect: {list.Count}"); if (list.Count == 0) { if (phase_spawned_total.Get() > 0) { force_next_phase.Set(value: true); } yield break; } enemies.Clear(); foreach (SpawnedCreatureRecord item in list) { GameObject val = ZNetScene.instance.FindInstance(item.Id); if ((Object)(object)val == (Object)null) { continue; } Character component = val.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_faction = (Faction)8; BaseAI component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.SetHuntPlayer(true); } if ((Object)(object)component.m_nview != (Object)null && component.m_nview.GetZDO() != null && !component.m_nview.GetZDO().GetBool("VFDrops", true)) { Object.Destroy((Object)(object)val.GetComponent()); component.m_onDeath = null; } } enemies.Add(val); } if (enemies.Count == 0 && spawned_creatures.Get() <= 0 && !phase_spawn_in_flight.Get() && phase_spawned_total.Get() > 0) { Logger.LogInfo((object)"No live creatures remain after reconnection, force starting next phase."); force_next_phase.ForceSet(value: true); } } protected IEnumerator OnClientReceivePhaseConfigs(long sender, ZPackage package) { string text = package.ReadString(); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Updated Non-primary znet owner with phased config."); } wave_phases_definitions = CONST.yamldeserializer.Deserialize(text); availablePhases = wave_phases_definitions.hordePhases.Count; if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Set wave phases: {availablePhases}."); } yield return null; } protected ZPackage SendPhaseConfigs() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_0064: 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_0071: Expected O, but got Unknown if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Sending Hoard phase configs to peer clients."); } try { availablePhases = wave_phases_definitions.hordePhases.Count; if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Set wave phases: {availablePhases}."); } string text = CONST.yamlserializer.Serialize((object)wave_phases_definitions); ZPackage val = new ZPackage(); val.Write(text); return val; } catch { PhasedWaveTemplate phasedWaveTemplate = new PhasedWaveTemplate(); string text2 = CONST.yamlserializer.Serialize((object)phasedWaveTemplate); ZPackage val2 = new ZPackage(); val2.Write(text2); return val2; } } protected void SendUpdatedPhaseConfigs() { try { if (wave_phases_definitions != null) { WaveDefinitionRPC.SendPackage(ZNet.instance.m_peers, SendPhaseConfigs()); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Sent Phase configs to clients."); } } } catch { Logger.LogError((object)"Error while server syncing phase configs"); } } protected bool RemainingPhases() { Logger.LogInfo((object)"Checking for remaining phases."); if (availablePhases > wave_phases_definitions.hordePhases.Count) { availablePhases = wave_phases_definitions.hordePhases.Count; Logger.LogInfo((object)$"Phases Available was undefined too large and was reset to: {availablePhases}."); } if (availablePhases == 0) { availablePhases = wave_phases_definitions.hordePhases.Count; Logger.LogInfo((object)$"Phases Available was undefined, updating it to reflect current wavephase definition {availablePhases}."); } bool flag = availablePhases - currentPhase.Get() > 0; Logger.LogInfo((object)$"Phases remaining check: available:{availablePhases} current{currentPhase.Get()} {flag}."); return flag; } public void SetHardMode() { hard_mode.ForceSet(value: true); } public void SetBossMode() { boss_mode.ForceSet(value: true); } public void SetSiegeMode() { siege_mode.ForceSet(value: true); } public void SetReward(string reward) { selected_reward.ForceSet(reward); } public void SetLevel(int level, int level_index) { selected_level.ForceSet(level); selected_level_index.ForceSet(level_index); } public void SetStartChallenge() { Logger.LogInfo((object)$"Challenge started at {((Object)this).GetInstanceID()}"); start_challenge.ForceSet(value: true); spawned_creatures.ForceSet(0); } public void RegisterSpawnedCreature(ZDOID creature_id, string prefab_name) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!(creature_id == ZDOID.None)) { List list = spawned_creature_records.Get(); list.Add(new SpawnedCreatureRecord(creature_id, prefab_name)); spawned_creature_records.Set(list); spawned_creatures.Set(list.Count); phase_spawned_total.Set(phase_spawned_total.Get() + 1); TouchProgressWatchdog(); } } public void ReconcileIfDue() { reconcile_tick++; if (reconcile_tick >= 20) { reconcile_tick = 0; ReconcileSpawnedCreatures(); } } protected void NoteOwnershipState(bool is_owner) { if (!is_owner) { was_owner = false; } else if (!was_owner) { was_owner = true; local_enemies_synced = false; } } protected void BeginPhaseSpawn() { phase_spawned_total.Set(0); phase_spawn_in_flight.Set(value: true); TouchProgressWatchdog(); } protected bool ShouldAdvancePhase() { if (force_next_phase.Get()) { return true; } if (phase_spawned_total.Get() > 0 && spawned_creatures.Get() <= 0) { return !phase_spawn_in_flight.Get(); } return false; } protected void TouchProgressWatchdog() { if (!((Object)(object)ZNet.instance == (Object)null)) { int num = (int)ZNet.instance.GetTimeSeconds(); if (challenge_progress_time.Get() != num) { challenge_progress_time.Set(num); } } } protected void CheckProgressWatchdog() { if ((Object)(object)ZNet.instance == (Object)null) { return; } if (spawned_creatures.Get() > 0) { TouchProgressWatchdog(); return; } int num = (int)ZNet.instance.GetTimeSeconds(); int num2 = challenge_progress_time.Get(); if (num2 <= 0 || num2 > num) { TouchProgressWatchdog(); } else if (!((float)(num - num2) < VFConfig.ShrineStallTimeout.Value)) { Logger.LogWarning((object)$"Challenge made no progress for {num - num2}s; forcing it forward so rewards are not lost."); phase_spawn_in_flight.Set(value: false); if (phase_spawned_total.Get() == 0 && currentPhase.Get() > 0) { currentPhase.Set(currentPhase.Get() - 1); } force_next_phase.Set(value: true); TouchProgressWatchdog(); } } public void ReconcileSpawnedCreatures() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)zNetView == (Object)null || !zNetView.IsValid() || !zNetView.IsOwner()) { return; } List list = spawned_creature_records.Get(); if (list.Count == 0) { if (spawned_creatures.Get() != 0) { spawned_creatures.Set(0); } return; } List list2 = new List(list.Count); Dictionary dictionary = new Dictionary(); foreach (SpawnedCreatureRecord item in list) { if (ZDOMan.instance.GetZDO(item.Id) != null) { list2.Add(item); if (dictionary.ContainsKey(item.Name)) { dictionary[item.Name]++; } else { dictionary[item.Name] = 1; } } } if (list2.Count != list.Count) { spawned_creature_records.Set(list2); alive_creature_list.Set(dictionary); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Reconciled challenge creatures: {list.Count} -> {list2.Count} alive."); } } if (spawned_creatures.Get() != list2.Count) { spawned_creatures.Set(list2.Count); } } public void DestroyAllSpawnedCreatures() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)zNetView == (Object)null || !zNetView.IsValid() || !zNetView.IsOwner()) { return; } foreach (SpawnedCreatureRecord item in spawned_creature_records.Get()) { GameObject val = ZNetScene.instance.FindInstance(item.Id); if ((Object)(object)val != (Object)null) { ZNetView component = val.GetComponent(); if ((Object)(object)component != (Object)null && component.IsValid() && !component.IsOwner()) { component.ClaimOwnership(); } ZNetScene.instance.Destroy(val); } else { ZDO zDO = ZDOMan.instance.GetZDO(item.Id); if (zDO != null) { zDO.SetOwner(ZDOMan.GetSessionID()); ZDOMan.instance.DestroyZDO(zDO); } } } spawned_creature_records.Set(new List()); spawned_creatures.Set(0); alive_creature_list.Set(new Dictionary()); enemies.Clear(); } public bool IsChallengeActive() { return challenge_active.Get(); } public bool ChallengeNoLongerSpawnable() { if (!challenge_active.Get()) { return !wave_definition_ready.Get(); } return false; } public bool CentralPortalActiveStatus() { if ((Object)(object)shrine_portal == (Object)null) { shrine_portal = ((Component)((Component)this).gameObject.transform.Find("portal")).gameObject; } return shrine_portal.activeSelf; } public void EnablePortal() { if ((Object)(object)shrine_portal == (Object)null) { shrine_portal = ((Component)((Component)this).gameObject.transform.Find("portal")).gameObject; } shrine_portal.SetActive(true); } public void Disableportal() { if ((Object)(object)shrine_portal == (Object)null) { shrine_portal = ((Component)((Component)this).gameObject.transform.Find("portal")).gameObject; } shrine_portal.SetActive(false); } public void addEnemy(GameObject enemy) { enemies.Add(enemy); } public void phaseCompleted() { phase_spawn_in_flight.Set(value: false); } public int EnemiesRemaining() { try { return spawned_creatures.Get(); } catch { Logger.LogInfo((object)"Znet Value not retrieved for enemies remaining."); return 0; } } public void SetWaveSpawnPoints(Vector3[] spawn_points) { remote_spawn_locations.Set(spawn_points); spawn_locations_ready.Set(value: true); } public abstract void StartChallengeMode(); public void CleanupOldPortals(short max_cleanup_iterations = 6) { Logger.LogInfo((object)"Starting cleanup of old portals."); int num = 1; int num2 = max_cleanup_iterations + 1; try { for (int i = 0; i <= num && i <= num2; i++) { GameObject val = GameObject.Find("VF_portal(Clone)"); if ((Object)(object)val != (Object)null) { Logger.LogInfo((object)("Found gameobject: " + ((Object)val).name + ".")); Object.Destroy((Object)(object)val.gameObject); num++; } } } catch { Logger.LogInfo((object)"Cleanup of portals failed."); } } public abstract void Update(); public abstract string GetHoverText(); public abstract string GetHoverName(); public abstract bool Interact(Humanoid user, bool hold, bool alt); public virtual bool UseItem(Humanoid user, ItemData item) { return false; } public void CancelShrineRun() { challenge_active.ForceSet(value: false); boss_mode.ForceSet(value: false); hard_mode.ForceSet(value: false); siege_mode.ForceSet(value: false); DestroyAllSpawnedCreatures(); Disableportal(); RemoteLocationPortals.ClearMapOverlay(); wave_phases_definitions = new PhasedWaveTemplate(); wave_definition_ready.Set(value: false); spawn_locations_ready.Set(value: false); phase_spawned_total.Set(0); phase_spawn_in_flight.Set(value: false); challenge_progress_time.Set(0); availablePhases = 0; currentPhase.ForceSet(0); } public void ReconnectCreatureList() { if (enemies.Count == 0) { spawned_creatures.ForceSet(0); force_next_phase.ForceSet(value: true); } } public void NotifyRemainingCreatures() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (client_set_creature_beacons) { return; } int num = 0; foreach (GameObject enemy in enemies) { if (!((Object)(object)enemy == (Object)null)) { num++; Object.Instantiate(ValheimFortress.getNotifier(), enemy.transform.localPosition, enemy.transform.rotation).transform.parent = enemy.transform; } } client_set_creature_beacons = true; } public void TeleportRemainingCreatures() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) if (spawned_creatures.Get() > VFConfig.TeleportCreatureThreshold.Value) { List list = new List(); Player.GetPlayersInRange(((Component)this).transform.position, VFConfig.ShrineAnnouncementRange.Value, list); { foreach (Player item in list) { ((Character)item).Message((MessageType)2, string.Format("{0} {1} {2} {3}.", Localization.instance.Localize("$shrine_too_many_creautres_to_teleport"), VFConfig.TeleportCreatureThreshold.Value, Localization.instance.Localize("$shrine_too_many_creautres_to_teleport_2"), spawned_creatures.Get()), 0, (Sprite)null); } return; } } int num = 0; foreach (GameObject enemy in enemies) { if (!((Object)(object)enemy == (Object)null)) { enemy.transform.position = shrine_spawnpoint.transform.position; num++; } } if (num != spawned_creatures.Get()) { spawned_creatures.Set(num); } } protected Vector3 ResolveRewardPosition(Vector3 spawn_position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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) if (spawn_position == Vector3.zero) { Logger.LogWarning((object)"Reward spawn position was unset; falling back to the shrine position."); return ((Component)this).transform.position; } return spawn_position; } public void SpawnMultiRewardsDirectly(Dictionary rewards_and_costs, short level, Vector3 spawn_position, bool hard_mode, bool boss_mode, bool siege_mode) { //IL_0001: 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) spawn_position = ResolveRewardPosition(spawn_position); float num = RewardsData.DetermineRewardPoints(level, hard_mode, boss_mode, siege_mode, DetermineMultiplayerBonus()) / (float)rewards_and_costs.Count; foreach (KeyValuePair rewards_and_cost in rewards_and_costs) { short num2 = (short)(num / (float)rewards_and_cost.Value); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Spawning reward {num2} {rewards_and_cost.Key}"); } ((MonoBehaviour)this).StartCoroutine(reward_controller.InitReward(rewards_and_cost.Key, num2, spawn_position)); } } public void SpawnReward(Vector3 spawn_position) { //IL_0001: 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_0007: 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) spawn_position = ResolveRewardPosition(spawn_position); string text = selected_reward.Get(); short number_of_rewards = RewardsData.DetermineRewardAmount(text, (short)selected_level_index.Get(), hard_mode.Get(), boss_mode.Get(), siege_mode.Get(), DetermineMultiplayerBonus()); string resourcePrefab = RewardsData.resourceRewards[text].resourcePrefab; ((MonoBehaviour)this).StartCoroutine(reward_controller.InitReward(resourcePrefab, number_of_rewards, spawn_position)); } public void SpawnFixedRewardsDirectly(Dictionary rewards_and_amounts, Vector3 spawn_position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) if (rewards_and_amounts == null) { return; } spawn_position = ResolveRewardPosition(spawn_position); foreach (KeyValuePair rewards_and_amount in rewards_and_amounts) { if (rewards_and_amount.Value > 0) { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Spawning fixed reward {rewards_and_amount.Value} {rewards_and_amount.Key}"); } ((MonoBehaviour)this).StartCoroutine(reward_controller.InitReward(rewards_and_amount.Key, rewards_and_amount.Value, spawn_position)); } } } public float DetermineMultiplayerBonus() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Player.GetPlayersInRange(((Component)this).transform.position, VFConfig.ShrineAnnouncementRange.Value, list); float num = (float)list.Count * VFConfig.ShrineRewardPlayerBonus.Value; if (VFConfig.ShrineRewardPlayerBonus.Value < 1f) { num += 1f; } if (list.Count == 1) { return 1f; } if (num > 1f) { return num; } return 1f; } } internal abstract class GenericShrineUI : MonoBehaviour { public enum adminFunctions { filtername } protected GameObject ChallengePanel; protected GameObject CancelPanel; protected GenericShrine Shrine; protected List currentLevels = new List(); protected List availableRewards = new List(); public GameObject levelSelector; public GameObject rewardSelector; public GameObject hardModeToggle; public GameObject bossModeToggle; public GameObject siegeModeToggle; public GameObject estimate_text; public short estimatedRewards; public string estimatedRewardName = ""; protected GameObject estimate_symbol; protected GameObject hardmode_label; protected GameObject hardmode_desc; protected GameObject hardmode_reward_desc; protected GameObject bossmode_label; protected GameObject bossmode_desc; protected GameObject bossmode_reward_desc; protected GameObject siegemode_label; protected GameObject siegemode_desc; protected GameObject siegemode_reward_desc; protected GameObject cancelButtonGO; protected GameObject startChallengeButtonGO; protected GameObject AdminMenuButtonGO; protected GameObject AdminMenuPanel; protected GameObject adminEntryField; protected bool cleanupPortals = true; private short selected_level_index; public bool current_hard_mode; public bool current_boss_mode; public bool current_siege_mode; public abstract void Awake(); public bool IsPanelVisible() { if ((Object)(object)ChallengePanel == (Object)null) { return false; } return ChallengePanel.activeSelf; } public bool IsShrineOrCancelUIVisible() { if (ChallengePanel.activeSelf) { return true; } if (CancelPanel.activeSelf) { return true; } return false; } public void Update() { if (!IsPanelVisible() || !VFConfig.EnableRewardsEstimate.Value) { return; } bool flag = false; string text = availableRewards[rewardSelector.GetComponent().value]; short num = (short)(short.Parse(ValheimFortress.ReplaceWhitespace(levelSelector.GetComponent().options[levelSelector.GetComponent().value].text.Split(new char[1] { '-' })[0], "")) - 1); short levelIndex = ChallengeLevels.GetChallengeLevelDefinitions().ElementAt(num).levelIndex; bool flag2 = false; bool flag3 = false; bool flag4 = false; if (text != estimatedRewardName || selected_level_index != num) { flag = true; } if (VFConfig.EnableHardModifier.Value) { flag2 = hardModeToggle.GetComponent().isOn; if (flag2 != current_hard_mode) { flag = true; } current_hard_mode = flag2; } if (VFConfig.EnableBossModifier.Value) { flag3 = bossModeToggle.GetComponent().isOn; if (flag3 != current_boss_mode) { flag = true; } current_boss_mode = flag3; } if (VFConfig.EnableSiegeModifer.Value) { flag4 = siegeModeToggle.GetComponent().isOn; if (flag4 != current_siege_mode) { flag = true; } current_siege_mode = flag4; } if (flag) { estimatedRewardName = text; selected_level_index = num; estimatedRewards = RewardsData.DetermineRewardAmount(estimatedRewardName, levelIndex, flag2, flag3, flag4); estimate_text.GetComponent().text = $"{estimatedRewards}"; } } public abstract void StartChallenge(); public abstract void DisplayUI(); public void HideUI() { ChallengePanel.SetActive(false); HideAdminUI(); GUIManager.BlockInput(false); } public void ShowAdminUI() { CreateAdminSelectionUI(); AdminMenuPanel.SetActive(true); } public void HideAdminUI() { if (Object.op_Implicit((Object)(object)AdminMenuPanel)) { AdminMenuPanel.SetActive(false); } } public void UpdatePossibleRewards(Dropdown reward_dropdown, Dropdown level_dropdown) { if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"Retrieving level from level dropdown value: {level_dropdown.value}"); } string text = ValheimFortress.ReplaceWhitespace(level_dropdown.options[level_dropdown.value].text.Split(new char[1] { '-' })[0], ""); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)("Leveltext: " + text)); } short num = (short)(short.Parse(text) - 1); if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)$"level index: {num}"); } List challengeLevelDefinitions = ChallengeLevels.GetChallengeLevelDefinitions(); availableRewards = UserInterfaceData.UpdateRewards(challengeLevelDefinitions.ElementAt(num)); reward_dropdown.ClearOptions(); reward_dropdown.AddOptions(availableRewards); } public void UITriggersUpdatePanelSizeOnConfigChangeArena() { VFConfig.EnableBossModifier.SettingChanged += UpdatePanelUIOnSettingsChangedArena; VFConfig.EnableHardModifier.SettingChanged += UpdatePanelUIOnSettingsChangedArena; VFConfig.EnableSiegeModifer.SettingChanged += UpdatePanelUIOnSettingsChangedArena; } public void UITriggersUpdatePanelSizeOnConfigChangeChallenge() { VFConfig.EnableBossModifier.SettingChanged += UpdatePanelUIOnSettingsChangedChallenge; VFConfig.EnableHardModifier.SettingChanged += UpdatePanelUIOnSettingsChangedChallenge; VFConfig.EnableSiegeModifer.SettingChanged += UpdatePanelUIOnSettingsChangedChallenge; } public void UpdatePanelUIOnSettingsChangedArena(object sender, EventArgs e) { CreateStaticUIObjects(); CreateChallengeUI(ShrineType.Arena); } public void UpdatePanelUIOnSettingsChangedChallenge(object sender, EventArgs e) { CreateStaticUIObjects(); CreateChallengeUI(ShrineType.Challenge); } public void CreateStaticUIObjects() { //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_0486: Unknown result type (might be due to invalid IL or missing references) //IL_0495: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Unknown result type (might be due to invalid IL or missing references) //IL_052a: Unknown result type (might be due to invalid IL or missing references) //IL_0569: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Unknown result type (might be due to invalid IL or missing references) //IL_0587: Unknown result type (might be due to invalid IL or missing references) //IL_059d: Unknown result type (might be due to invalid IL or missing references) //IL_05a3: Unknown result type (might be due to invalid IL or missing references) //IL_0615: Unknown result type (might be due to invalid IL or missing references) //IL_0624: Unknown result type (might be due to invalid IL or missing references) //IL_0633: Unknown result type (might be due to invalid IL or missing references) //IL_0649: Unknown result type (might be due to invalid IL or missing references) //IL_064f: Unknown result type (might be due to invalid IL or missing references) //IL_068e: Unknown result type (might be due to invalid IL or missing references) //IL_069d: Unknown result type (might be due to invalid IL or missing references) //IL_06ac: Unknown result type (might be due to invalid IL or missing references) //IL_06c2: Unknown result type (might be due to invalid IL or missing references) //IL_06c8: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: 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_024b: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_072d: Unknown result type (might be due to invalid IL or missing references) //IL_073c: Unknown result type (might be due to invalid IL or missing references) //IL_074b: Unknown result type (might be due to invalid IL or missing references) //IL_07bf: Unknown result type (might be due to invalid IL or missing references) //IL_07ce: Unknown result type (might be due to invalid IL or missing references) //IL_07dd: Unknown result type (might be due to invalid IL or missing references) //IL_082c: Unknown result type (might be due to invalid IL or missing references) //IL_083b: Unknown result type (might be due to invalid IL or missing references) //IL_084a: Unknown result type (might be due to invalid IL or missing references) //IL_08de: Unknown result type (might be due to invalid IL or missing references) //IL_08ed: Unknown result type (might be due to invalid IL or missing references) //IL_08fc: Unknown result type (might be due to invalid IL or missing references) //IL_0a65: Unknown result type (might be due to invalid IL or missing references) //IL_0a6f: Expected O, but got Unknown //IL_0a86: Unknown result type (might be due to invalid IL or missing references) //IL_0a90: Expected O, but got Unknown //IL_0aa8: Unknown result type (might be due to invalid IL or missing references) //IL_0ab2: Expected O, but got Unknown //IL_0970: Unknown result type (might be due to invalid IL or missing references) //IL_097f: Unknown result type (might be due to invalid IL or missing references) //IL_098e: Unknown result type (might be due to invalid IL or missing references) //IL_09dd: Unknown result type (might be due to invalid IL or missing references) //IL_09ec: Unknown result type (might be due to invalid IL or missing references) //IL_09fb: Unknown result type (might be due to invalid IL or missing references) if (GUIManager.Instance == null) { Logger.LogError((object)"GUIManager instance is null"); return; } if (!Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront)) { Logger.LogError((object)"GUIManager CustomGUI is null"); return; } if (!VFConfig.EnableBossModifier.Value && !VFConfig.EnableHardModifier.Value && !VFConfig.EnableSiegeModifer.Value) { ChallengePanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 600f, 400f, true); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_header"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(60f, 165f), GUIManager.Instance.AveriaSerifBold, 30, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_description"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(45f, 100f), GUIManager.Instance.AveriaSerifBold, 14, GUIManager.Instance.ValheimBeige, true, Color.black, 500f, 80f, false); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_warning"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(85f, 60f), GUIManager.Instance.AveriaSerifBold, 18, GUIManager.Instance.ValheimYellow, true, Color.black, 400f, 40f, false); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_reward_label"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-60f, -60f), GUIManager.Instance.AveriaSerifBold, 16, GUIManager.Instance.ValheimBeige, true, Color.black, 300f, 40f, false); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_level_label"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-60f, 5f), GUIManager.Instance.AveriaSerifBold, 16, GUIManager.Instance.ValheimBeige, true, Color.black, 300f, 40f, false); } else { ChallengePanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 600f, 600f, true); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_header"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(60f, 230f), GUIManager.Instance.AveriaSerifBold, 30, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_description"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(45f, 155f), GUIManager.Instance.AveriaSerifBold, 14, GUIManager.Instance.ValheimBeige, true, Color.black, 500f, 80f, false); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_warning"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(85f, 95f), GUIManager.Instance.AveriaSerifBold, 18, GUIManager.Instance.ValheimYellow, true, Color.black, 400f, 40f, false); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_reward_label"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-60f, -5f), GUIManager.Instance.AveriaSerifBold, 16, GUIManager.Instance.ValheimBeige, true, Color.black, 300f, 40f, false); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_level_label"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-60f, 50f), GUIManager.Instance.AveriaSerifBold, 16, GUIManager.Instance.ValheimBeige, true, Color.black, 300f, 40f, false); } ChallengePanel.SetActive(false); if (VFConfig.EnableBossModifier.Value || VFConfig.EnableHardModifier.Value || VFConfig.EnableSiegeModifer.Value) { GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_modifiers_label"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-138f, -48f), GUIManager.Instance.AveriaSerifBold, 16, GUIManager.Instance.ValheimBeige, true, Color.black, 100f, 40f, false); GUIManager.Instance.CreateText(Localization.instance.Localize("$shrine_modifiers_rewards_label"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(28f, -48f), GUIManager.Instance.AveriaSerifBold, 16, GUIManager.Instance.ValheimBeige, true, Color.black, 200f, 40f, false); if ((Object)(object)startChallengeButtonGO != (Object)null) { Object.Destroy((Object)(object)startChallengeButtonGO.gameObject); startChallengeButtonGO = null; } startChallengeButtonGO = GUIManager.Instance.CreateButton(Localization.instance.Localize("$shrine_confirm"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -224f), 150f, 60f); startChallengeButtonGO.SetActive(true); if ((Object)(object)cancelButtonGO != (Object)null) { Object.Destroy((Object)(object)cancelButtonGO.gameObject); cancelButtonGO = null; } cancelButtonGO = GUIManager.Instance.CreateButton(Localization.instance.Localize("$shrine_cancel"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(260f, 260f), 40f, 40f); cancelButtonGO.SetActive(true); AdminMenuButtonGO = GUIManager.Instance.CreateButton(Localization.instance.Localize("$shrine_admin_menu_button"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(220f, 260f), 40f, 40f); AdminMenuButtonGO.SetActive(false); if (SynchronizationManager.Instance.PlayerIsAdmin) { AdminMenuButtonGO.SetActive(true); } } else { if ((Object)(object)startChallengeButtonGO != (Object)null) { Object.Destroy((Object)(object)startChallengeButtonGO.gameObject); startChallengeButtonGO = null; } startChallengeButtonGO = GUIManager.Instance.CreateButton(Localization.instance.Localize("$shrine_confirm"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -125f), 150f, 60f); startChallengeButtonGO.SetActive(true); if ((Object)(object)cancelButtonGO != (Object)null) { Object.Destroy((Object)(object)cancelButtonGO.gameObject); cancelButtonGO = null; } cancelButtonGO = GUIManager.Instance.CreateButton(Localization.instance.Localize("$shrine_cancel"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(260f, 165f), 40f, 40f); cancelButtonGO.SetActive(true); AdminMenuButtonGO = GUIManager.Instance.CreateButton(Localization.instance.Localize("$shrine_admin_menu_button"), ChallengePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(218f, 165f), 40f, 40f); AdminMenuButtonGO.SetActive(false); if (SynchronizationManager.Instance.PlayerIsAdmin) { AdminMenuButtonGO.SetActive(true); } } if (VFConfig.EnableDebugMode.Value) { Logger.LogInfo((object)"Shrine UI Created."); } ((UnityEvent)cancelButtonGO.GetComponent