Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PokeMoons v1.0.2
Pokemoons.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalLib.Modules; using LethalQuantities; using LethalQuantities.Json; using LethalQuantities.Objects; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Pokemoons; using Pokemoons.NetcodePatcher; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Pokemoons")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Pokemoons Mod")] [assembly: AssemblyFileVersion("0.0.1.0")] [assembly: AssemblyInformationalVersion("0.0.1+c6a7c7490f8f6b1fc2f43008cf1bf645c7acc66b")] [assembly: AssemblyProduct("Pokemoons")] [assembly: AssemblyTitle("Pokemoons")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] internal class <Module> { static <Module>() { } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } [HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")] internal static class DexReleasePatch { internal class TrackedPokemon { public NetworkObject networkObject; public KeyValuePair<int, bool> pokemon; } [HarmonyPrefix] private static void BeforeDespawn(out List<TrackedPokemon> __state) { __state = null; if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } __state = new List<TrackedPokemon>(); PokemonProp[] array = Object.FindObjectsOfType<PokemonProp>(); foreach (PokemonProp pokemonProp in array) { if (((GrabbableObject)pokemonProp).isInShipRoom && (Object)(object)((NetworkBehaviour)pokemonProp).NetworkObject != (Object)null && ((NetworkBehaviour)pokemonProp).NetworkObject.IsSpawned && DexData.TryGetDexNumber((GrabbableObject)(object)pokemonProp, out var dexNumber)) { __state.Add(new TrackedPokemon { networkObject = ((NetworkBehaviour)pokemonProp).NetworkObject, pokemon = new KeyValuePair<int, bool>(dexNumber, pokemonProp.IsShiny) }); } } } [HarmonyPostfix] private static void AfterDespawn(List<TrackedPokemon> __state) { if (__state == null) { return; } List<KeyValuePair<int, bool>> list = new List<KeyValuePair<int, bool>>(); foreach (TrackedPokemon item in __state) { if ((Object)(object)item.networkObject == (Object)null || !item.networkObject.IsSpawned) { list.Add(item.pokemon); } } DexData.AddReleased(list); } } [HarmonyPatch(typeof(GameNetworkManager))] internal static class DexSavePatch { [HarmonyPatch("SaveItemsInShip")] [HarmonyPostfix] private static void AfterSaveItems() { Commit(); } [HarmonyPatch("ResetSavedGameValues")] [HarmonyPostfix] private static void AfterReset() { Commit(); } private static void Commit() { if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer) { DexData.Commit(); } } } [HarmonyPatch(typeof(ES3), "DeleteFile", new Type[] { typeof(string) })] internal static class DexDeletePatch { [HarmonyPostfix] private static void AfterDelete(string filePath) { if (!string.IsNullOrEmpty(filePath) && filePath.StartsWith("LCSaveFile") && !filePath.EndsWith("_Pokemoons.es3") && ES3.FileExists(filePath + "_Pokemoons.es3")) { ES3.DeleteFile(filePath + "_Pokemoons.es3"); } } } [HarmonyPatch(typeof(DepositItemsDesk), "SellItemsOnServer")] internal static class DexSellPatch { private static readonly List<KeyValuePair<int, bool>> _pending = new List<KeyValuePair<int, bool>>(); [HarmonyPrefix] private static void BeforeSell(DepositItemsDesk __instance) { _pending.Clear(); if (!((NetworkBehaviour)__instance).IsServer || __instance.itemsOnCounter == null) { return; } foreach (GrabbableObject item in __instance.itemsOnCounter) { if (DexData.TryGetDexNumber(item, out var dexNumber)) { _pending.Add(new KeyValuePair<int, bool>(dexNumber, ((PokemonProp)(object)item).IsShiny)); } } } [HarmonyPostfix] private static void AfterSell() { DexData.AddSold(_pending); _pending.Clear(); } } [HarmonyPatch(typeof(RoundManager))] internal static class RoundManagerPatches { [HarmonyPatch("Start")] [HarmonyPostfix] [HarmonyPriority(200)] public static void AfterStart() { DexData.Initialise(); DexSync.Register(); if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer) { DexData.EnsureLoaded(); } else { DexSync.RequestFromHost(); } DexSpawnTables.EstimateAll(); } } internal static class DexSpawnTables { public static void EstimateAll() { SelectableLevel[] array = StartOfRound.Instance?.levels; if (array == null) { return; } int num = 0; SelectableLevel[] array2 = array; foreach (SelectableLevel val in array2) { if ((Object)(object)val == (Object)null || val.spawnableScrap == null) { continue; } try { List<SpawnableItemWithRarity> list = val.spawnableScrap; if (LQCompat.Enabled) { list = LQCompat.TryApplyPreset(val, list) ?? list; } DexData.RecordMoon(val.PlanetName, SpawnWeights.Preview(val, list), observed: false); num++; } catch (Exception) { Plugin.logger.LogWarning((object)("Dex: invalid loot table for '" + val.PlanetName + "'")); } } Plugin.logger.LogInfo((object)$"Dex: estimated loot tables for {num} moons."); } } internal static class LQCompat { private static bool _failed; public static bool Enabled { get { if (!_failed) { return Chainloader.PluginInfos.ContainsKey("LethalQuantities"); } return false; } } public static List<SpawnableItemWithRarity> TryApplyPreset(SelectableLevel level, List<SpawnableItemWithRarity> table) { try { return ApplyPreset(level, table); } catch (Exception) { _failed = true; Plugin.logger.LogWarning((object)"Dex: couldn't read LethalQuantities presets. Using game tables."); return null; } } [MethodImpl(MethodImplOptions.NoInlining)] private static List<SpawnableItemWithRarity> ApplyPreset(SelectableLevel level, List<SpawnableItemWithRarity> table) { //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown if (!(AccessTools.Field(typeof(Plugin), "presets")?.GetValue(Plugin.INSTANCE) as Dictionary<Guid, LevelPreset>).TryGetValue(SelectableLevelCache.getGuid(level), out var value) || !value.scrap.set) { return null; } Dictionary<Item, int> dictionary = new Dictionary<Item, int>(); foreach (SpawnableItemWithRarity item in table) { if (item != null && !((Object)(object)item.spawnableItem == (Object)null)) { dictionary.TryGetValue(item.spawnableItem, out var value2); dictionary[item.spawnableItem] = value2 + item.rarity; } } List<SpawnableItemWithRarity> list = new List<SpawnableItemWithRarity>(); foreach (KeyValuePair<Item, LevelPresetItem> item2 in value.scrap.value) { if (!((Object)(object)item2.Key == (Object)null)) { dictionary.TryGetValue(item2.Key, out var value3); if (item2.Value.rarity.set) { value3 = item2.Value.rarity.value; } if (value3 > 0) { list.Add(new SpawnableItemWithRarity(item2.Key, value3)); } } } if (list.Count <= 0) { return null; } return list; } } namespace Pokemoons { public class DexEntry { public string Name { get; set; } public int DexNumber { get; set; } public Dictionary<string, int> SpawnWeight { get; set; } = new Dictionary<string, int>(); public Dictionary<string, float> SpawnChance { get; set; } = new Dictionary<string, float>(); } public static class DexData { private static bool _initialised = false; private static string _savedFilePath; public const string FileSuffix = "_Pokemoons.es3"; public static readonly HashSet<string> ObservedMoons = new HashSet<string>(); public static int[] Sold = new int[PokemonList.Gen1PokemonNames.Count]; public static int[] SoldShiny = new int[PokemonList.Gen1PokemonNames.Count]; public static int[] Released = new int[PokemonList.Gen1PokemonNames.Count]; public static int[] ReleasedShiny = new int[PokemonList.Gen1PokemonNames.Count]; private static string _loadedPath; private static bool _unsaved; private const string SoldKey = "DexSold"; private const string SoldShinyKey = "DexSoldShiny"; private const string ReleasedKey = "DexReleased"; private const string ReleasedShinyKey = "DexReleasedShiny"; public static Dictionary<string, DexEntry> DexEntries { get; set; } = new Dictionary<string, DexEntry>(); public static void Initialise() { _savedFilePath = GameNetworkManager.Instance.currentSaveFileName + "_Pokemoons.es3"; ObservedMoons.Clear(); _loadedPath = null; SetCounts(null, null, null, null); NewEntryPopup.Reset(); if (!_initialised) { for (int i = 0; i < PokemonList.Gen1PokemonNames.Count; i++) { DexEntries[PokemonList.Gen1PokemonNames[i]] = new DexEntry { Name = PokemonList.Gen1PokemonNames[i], DexNumber = i + 1 }; } _initialised = true; } } public static void RecordMoon(string moon, IEnumerable<SpawnableItemWithRarity> table, bool observed) { if (!_initialised || string.IsNullOrEmpty(moon) || table == null || (!observed && ObservedMoons.Contains(moon))) { return; } if (observed) { ObservedMoons.Add(moon); } Dictionary<string, int> dictionary = new Dictionary<string, int>(); int num = 0; foreach (SpawnableItemWithRarity item in table) { if (item != null && !((Object)(object)item.spawnableItem == (Object)null) && item.rarity > 0) { num += item.rarity; string name = ((Object)item.spawnableItem).name; if (DexEntries.ContainsKey(name)) { dictionary.TryGetValue(name, out var value); dictionary[name] = value + item.rarity; } } } foreach (DexEntry value3 in DexEntries.Values) { if (dictionary.TryGetValue(value3.Name, out var value2)) { value3.SpawnWeight[moon] = value2; value3.SpawnChance[moon] = (float)value2 / (float)num; } else { value3.SpawnWeight.Remove(moon); value3.SpawnChance.Remove(moon); } } } public static bool TryGetDexNumber(GrabbableObject item, out int dexNumber) { dexNumber = 0; if (!(item is PokemonProp) || (Object)(object)item.itemProperties == (Object)null || !DexEntries.TryGetValue(((Object)item.itemProperties).name, out var value)) { return false; } dexNumber = value.DexNumber; return true; } public static void GetFound(out int[] found, out int[] foundShiny, out int[] onShip) { int count = PokemonList.Gen1PokemonNames.Count; found = new int[count]; foundShiny = new int[count]; onShip = new int[count]; for (int i = 0; i < count; i++) { found[i] = Sold[i] + SoldShiny[i] + Released[i] + ReleasedShiny[i]; foundShiny[i] = SoldShiny[i] + ReleasedShiny[i]; } PokemonProp[] array = Object.FindObjectsOfType<PokemonProp>(); foreach (PokemonProp pokemonProp in array) { if (((GrabbableObject)pokemonProp).isInShipRoom && TryGetDexNumber((GrabbableObject)(object)pokemonProp, out var dexNumber)) { found[dexNumber - 1]++; onShip[dexNumber - 1]++; if (pokemonProp.IsShiny) { foundShiny[dexNumber - 1]++; } } } } public static void EnsureLoaded() { if (!(_loadedPath == _savedFilePath)) { _loadedPath = _savedFilePath; _unsaved = false; SetCounts(ES3.Load<int[]>("DexSold", _savedFilePath, new int[0]), ES3.Load<int[]>("DexSoldShiny", _savedFilePath, new int[0]), ES3.Load<int[]>("DexReleased", _savedFilePath, new int[0]), ES3.Load<int[]>("DexReleasedShiny", _savedFilePath, new int[0])); } } public static void AddSold(List<KeyValuePair<int, bool>> pokemon) { EnsureLoaded(); Add(pokemon, Sold, SoldShiny); } public static void AddReleased(List<KeyValuePair<int, bool>> pokemon) { EnsureLoaded(); Add(pokemon, Released, ReleasedShiny); } private static void Add(List<KeyValuePair<int, bool>> pokemon, int[] normal, int[] shiny) { if (pokemon.Count == 0) { return; } foreach (KeyValuePair<int, bool> item in pokemon) { (item.Value ? shiny : normal)[item.Key - 1]++; } _unsaved = true; DexSync.SendToClients(); } public static void Commit() { if (_unsaved && !(_loadedPath != _savedFilePath)) { ES3.Save<int[]>("DexSold", Sold, _savedFilePath); ES3.Save<int[]>("DexSoldShiny", SoldShiny, _savedFilePath); ES3.Save<int[]>("DexReleased", Released, _savedFilePath); ES3.Save<int[]>("DexReleasedShiny", ReleasedShiny, _savedFilePath); _unsaved = false; } } public static void SetCounts(int[] sold, int[] soldShiny, int[] released, int[] releasedShiny) { Sold = Fit(sold); SoldShiny = Fit(soldShiny); Released = Fit(released); ReleasedShiny = Fit(releasedShiny); } private static int[] Fit(int[] source) { int[] array = new int[PokemonList.Gen1PokemonNames.Count]; if (source != null) { Array.Copy(source, array, Mathf.Min(array.Length, source.Length)); } return array; } } public static class DexSync { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnCounts; public static HandleNamedMessageDelegate <1>__OnRequest; } private const string CountsMessage = "Pokemoons.DexCounts"; private const string RequestMessage = "Pokemoons.DexRequest"; public static void Register() { //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) //IL_0037: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if (val != null) { object obj = <>O.<0>__OnCounts; if (obj == null) { HandleNamedMessageDelegate val2 = OnCounts; <>O.<0>__OnCounts = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("Pokemoons.DexCounts", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnRequest; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnRequest; <>O.<1>__OnRequest = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("Pokemoons.DexRequest", (HandleNamedMessageDelegate)obj2); } } public unsafe static void RequestFromHost() { //IL_002a: 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_0043: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.IsServer) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { byte b = 0; ((FastBufferWriter)(ref val)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("Pokemoons.DexRequest", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } public static void SendToClients() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId != 0L) { Send(connectedClientsId); } } } private unsafe static void Send(ulong clientId) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } int num = 32 + 4 * DexData.Sold.Length * 4; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(DexData.Sold, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(DexData.SoldShiny, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(DexData.Released, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(DexData.ReleasedShiny, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("Pokemoons.DexCounts", clientId, val, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnRequest(ulong senderClientId, FastBufferReader reader) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { DexData.EnsureLoaded(); Send(senderClientId); } } private static void OnCounts(ulong senderClientId, FastBufferReader reader) { //IL_0020: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_005f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)NetworkManager.Singleton == (Object)null) && !NetworkManager.Singleton.IsServer) { int[] sold = default(int[]); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref sold, default(ForPrimitives)); int[] soldShiny = default(int[]); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref soldShiny, default(ForPrimitives)); int[] released = default(int[]); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref released, default(ForPrimitives)); int[] releasedShiny = default(int[]); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref releasedShiny, default(ForPrimitives)); DexData.SetCounts(sold, soldShiny, released, releasedShiny); } } } internal static class LLLCompat { private const string Guid = "imabatby.lethallevelloader"; private static readonly HashSet<string> AlwaysNamed = new HashSet<string> { "artifice", "embrion" }; private static bool _failed; private static PropertyInfo _levels; private static PropertyInfo _selectableLevel; private static PropertyInfo _locked; private static PropertyInfo _hidden; public static bool Enabled { get { if (!_failed) { return Chainloader.PluginInfos.ContainsKey("imabatby.lethallevelloader"); } return false; } } public static HashSet<string> LockedMoons() { HashSet<string> hashSet = new HashSet<string>(); if (!Enabled) { return hashSet; } try { if (_levels == null) { Type type = AccessTools.TypeByName("LethalLevelLoader.PatchedContent"); Type type2 = AccessTools.TypeByName("LethalLevelLoader.ExtendedLevel"); _levels = AccessTools.Property(type, "ExtendedLevels"); _selectableLevel = AccessTools.Property(type2, "SelectableLevel"); _locked = AccessTools.Property(type2, "IsRouteLocked"); _hidden = AccessTools.Property(type2, "IsRouteHidden"); if (_levels == null || _selectableLevel == null || _locked == null || _hidden == null) { throw new MissingMemberException("LethalLevelLoader.ExtendedLevel", "IsRouteLocked / IsRouteHidden"); } } if (!(_levels.GetValue(null) is IEnumerable enumerable)) { return hashSet; } foreach (object item in enumerable) { if (item != null && ((bool)_locked.GetValue(item) || (bool)_hidden.GetValue(item))) { object? value = _selectableLevel.GetValue(item); SelectableLevel val = (SelectableLevel)((value is SelectableLevel) ? value : null); if (val != null && !string.IsNullOrEmpty(val.PlanetName) && !AlwaysNamed.Contains(SpawnWeights.SimplifyMoon(val.PlanetName))) { hashSet.Add(val.PlanetName); } } } } catch (Exception ex) { _failed = true; Plugin.logger.LogWarning((object)("Pokedex: couldn't read LethalLevelLoader's locked moons (" + ex.GetType().Name + ": " + ex.Message + "). All moons will be named.")); } return hashSet; } } public static class NewEntryPopup { public enum PopupPosition { TopRight, Centre } private struct PopupInfo { public int DexNumber; public bool Shiny; public Sprite Icon; public int FoundCount; } public const string SoundPath = "Assets/Pokemons/Sounds/itemgot.ogg"; private const float FadeTime = 0.3f; private const float FlipTime = 1f; private const float HoldTime = 2.5f; private const float SlideDistance = 0.03f; private static readonly Color ShinyColour = new Color(1f, 0.84f, 0f); private const float FrameThickness = 0.003f; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _volume; private static ConfigEntry<PopupPosition> _position; private const float BoxScale = 0.8f; private static AudioClip _sound; private static HashSet<int> _known; private static HashSet<int> _knownShiny; private static readonly Queue<PopupInfo> _queue = new Queue<PopupInfo>(); private static bool _running; public static void Init(ConfigFile config) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown _enabled = config.Bind<bool>("Pokedex", "NewEntryPopup", true, "Show a pop-up when a Pokemon species (or its shiny) is brought back to the ship for the first time."); _volume = config.Bind<float>("Pokedex", "NewEntrySoundVolume", 0.8f, new ConfigDescription("Volume of the pop-up's sound (0 to 1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); _position = config.Bind<PopupPosition>("Pokedex", "NewEntryPosition", PopupPosition.TopRight, "Where the pop-up appears on screen. Try Centre if another mod (e.g. Brutal Company) also uses the top right."); } public static void LoadSound(AssetBundle bundle) { _sound = bundle.LoadAsset<AudioClip>("Assets/Pokemons/Sounds/itemgot.ogg"); } public static void Reset() { _known = null; _knownShiny = null; _queue.Clear(); _running = false; } public static void OnArriving(GrabbableObject item) { if (!_enabled.Value || !(item is PokemonProp pokemonProp) || !DexData.TryGetDexNumber(item, out var dexNumber)) { return; } DexData.GetFound(out var found, out var foundShiny, out var _); if (_known == null) { _known = new HashSet<int>(from n in Enumerable.Range(1, found.Length) where found[n - 1] > 0 select n); _knownShiny = new HashSet<int>(from n in Enumerable.Range(1, found.Length) where foundShiny[n - 1] > 0 select n); } bool flag = found[dexNumber - 1] == 0 && _known.Add(dexNumber); bool flag2 = pokemonProp.IsShiny && foundShiny[dexNumber - 1] == 0 && _knownShiny.Add(dexNumber); if (flag || flag2) { _queue.Enqueue(new PopupInfo { DexNumber = dexNumber, Shiny = flag2, Icon = item.itemProperties.itemIcon, FoundCount = found.Count((int c) => c > 0) + (flag ? 1 : 0) }); if (!_running && (Object)(object)HUDManager.Instance != (Object)null) { _running = true; ((MonoBehaviour)HUDManager.Instance).StartCoroutine(RunQueue()); } } } private static IEnumerator RunQueue() { while (_queue.Count > 0) { PopupInfo info = _queue.Dequeue(); GameObject val = null; try { val = Build(info); } catch (Exception ex) { Plugin.logger.LogWarning((object)("Pokedex: new entry pop-up failed to show: " + ex.Message)); } if ((Object)(object)val != (Object)null) { yield return Animate(val); } } _running = false; } private static GameObject Build(PopupInfo info) { //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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0186: 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_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_024a: 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_0262: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) HUDManager instance = HUDManager.Instance; TextMeshProUGUI val = ((instance.ScrapItemBoxes != null && instance.ScrapItemBoxes.Length != 0 && instance.ScrapItemBoxes[0] != null) ? instance.ScrapItemBoxes[0].headerText : null); if ((Object)(object)val == (Object)null) { val = instance.tipsPanelHeader; } if ((Object)(object)((Graphic)val).canvas == (Object)null) { return null; } Canvas rootCanvas = ((Graphic)val).canvas.rootCanvas; Rect rect = ((RectTransform)((Component)rootCanvas).transform).rect; float height = ((Rect)(ref rect)).height; float num = height * 0.8f; Color colour = (info.Shiny ? ShinyColour : ((Graphic)val).color); colour.a = 1f; GameObject val2 = new GameObject("PokemoonsNewEntry", new Type[2] { typeof(RectTransform), typeof(CanvasGroup) }); RectTransform val3 = (RectTransform)val2.transform; ((Transform)val3).SetParent(((Component)rootCanvas).transform, false); ((Transform)val3).SetAsLastSibling(); val3.sizeDelta = new Vector2(num * 0.55f, num * 0.42f); Vector2 val4 = default(Vector2); Vector2 val5; if (_position.Value == PopupPosition.TopRight) { ((Vector2)(ref val4))..ctor(1f, 1f); val3.pivot = val4; val5 = (val3.anchorMin = (val3.anchorMax = val4)); val3.anchoredPosition = new Vector2((0f - height) * 0.04f, (0f - height) * 0.2f); } else { ((Vector2)(ref val4))..ctor(0.5f, 1f); val3.pivot = val4; val5 = (val3.anchorMin = (val3.anchorMax = val4)); val3.anchoredPosition = new Vector2(0f, (0f - height) * 0.24f); } val2.GetComponent<CanvasGroup>().blocksRaycasts = false; float num2 = num * 0.003f; AddBar(val3, colour, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, num2)); AddBar(val3, colour, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, num2)); AddBar(val3, colour, new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(num2, 0f)); AddBar(val3, colour, new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(num2, 0f)); string arg = PokemonList.Gen1PokemonNames[info.DexNumber - 1].ToUpperInvariant(); AddText(val2, val, info.Shiny ? "NEW SHINY!" : "NEW POKEMON", colour, num * 0.045f, 0.9f); AddText(val2, val, $"#{info.DexNumber:D3} {arg}", colour, num * 0.04f, 0.2f); AddText(val2, val, $"Pokedex {info.FoundCount}/{PokemonList.Gen1PokemonNames.Count}", colour, num * 0.03f, 0.08f); if ((Object)(object)info.Icon != (Object)null) { GameObject val10 = new GameObject("Icon", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val11 = (RectTransform)val10.transform; ((Transform)val11).SetParent((Transform)(object)val3, false); ((Vector2)(ref val5))..ctor(0.5f, 0.53f); val11.anchorMax = val5; val11.anchorMin = val5; val11.sizeDelta = new Vector2(num * 0.2f, num * 0.2f); Image component = val10.GetComponent<Image>(); component.sprite = info.Icon; component.preserveAspect = true; ((Graphic)component).raycastTarget = false; } return val2; } private static void AddBar(RectTransform parent, Color colour, Vector2 anchorMin, Vector2 anchorMax, Vector2 size) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Frame", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)parent, false); val2.anchorMin = anchorMin; val2.anchorMax = anchorMax; val2.sizeDelta = size; Image component = val.GetComponent<Image>(); ((Graphic)component).color = colour; ((Graphic)component).raycastTarget = false; } private static void AddText(GameObject box, TextMeshProUGUI template, string text, Color colour, float size, float y) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0073: 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) GameObject val = new GameObject("Text", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(box.transform, false); val2.anchorMin = new Vector2(0f, y); val2.anchorMax = new Vector2(1f, y); val2.sizeDelta = new Vector2(0f, size * 1.5f); TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component).font = ((TMP_Text)template).font; ((TMP_Text)component).fontSharedMaterial = ((TMP_Text)template).fontSharedMaterial; ((TMP_Text)component).fontSize = size; ((Graphic)component).color = colour; ((TMP_Text)component).alignment = (TextAlignmentOptions)514; ((TMP_Text)component).enableWordWrapping = false; ((Graphic)component).raycastTarget = false; ((TMP_Text)component).text = text; } private static IEnumerator Animate(GameObject box) { RectTransform rect = (RectTransform)box.transform; CanvasGroup group = box.GetComponent<CanvasGroup>(); Transform icon = ((Transform)rect).Find("Icon"); Rect rect2 = ((RectTransform)((Transform)rect).parent).rect; float slide = ((Rect)(ref rect2)).height * 0.03f; Vector2 rest = rect.anchoredPosition; if ((Object)(object)_sound != (Object)null) { HUDManager.Instance.UIAudio.PlayOneShot(_sound, _volume.Value); } for (float t = 0f; t < 0.3f; t += Time.deltaTime) { float num = (group.alpha = t / 0.3f); rect.anchoredPosition = rest + new Vector2(0f, slide * (1f - num)); yield return null; } group.alpha = 1f; rect.anchoredPosition = rest; if ((Object)(object)icon != (Object)null) { for (float t = 0f; t < 1f; t += Time.deltaTime) { icon.localScale = new Vector3(Mathf.Cos(t / 1f * MathF.PI * 2f), 1f, 1f); yield return null; } icon.localScale = Vector3.one; } yield return (object)new WaitForSeconds(2.5f); for (float t = 0f; t < 0.3f; t += Time.deltaTime) { group.alpha = 1f - t / 0.3f; yield return null; } Object.Destroy((Object)(object)box); } } [HarmonyPatch(typeof(PlayerControllerB), "SetItemInElevator")] internal static class NewEntryPatch { [HarmonyPrefix] private static void Prefix(bool droppedInShipRoom, GrabbableObject gObject) { if (droppedInShipRoom && (Object)(object)gObject != (Object)null && !gObject.isInShipRoom) { try { NewEntryPopup.OnArriving(gObject); } catch (Exception ex) { Plugin.logger.LogWarning((object)("Pokedex: new entry check failed: " + ex.Message)); } } } } [BepInPlugin("shronkstones.pokemoons", "PokeMoons", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string modGUID = "shronkstones.pokemoons"; public const string modName = "PokeMoons"; public const string modVersion = "1.0.0"; public static Plugin Instance; public static ManualLogSource logger; public static ConfigEntry<float> PokemonCryVolume; private void Awake() { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown Instance = this; logger = ((BaseUnityPlugin)this).Logger; Type[] types = Assembly.GetExecutingAssembly().GetTypes(); for (int i = 0; i < types.Length; i++) { MethodInfo[] methods = types[i].GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length != 0) { methodInfo.Invoke(null, null); } } } ShinySystem.Init(((BaseUnityPlugin)this).Config); PokedexCommand.Init(((BaseUnityPlugin)this).Config); NewEntryPopup.Init(((BaseUnityPlugin)this).Config); PokemonCryVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Sounds", "PokemonCryVolume", 0.4f, new ConfigDescription("Volume of each Pokemon's cry when picked up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); SpawnWeights.Init(((BaseUnityPlugin)this).Config, directoryName); AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(directoryName, "pokemoons")); if ((Object)(object)val == (Object)null) { logger.LogError((object)"Bundle Not Found"); return; } PokemonItemLoader pokemonItemLoader = new PokemonItemLoader(val); foreach (string gen1PokemonName in PokemonList.Gen1PokemonNames) { pokemonItemLoader.LoadPokemon(gen1PokemonName); } Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "shronkstones.pokemoons"); logger.LogInfo((object)"Plugin shronkstones.pokemoons is loaded!"); } } public static class PokedexCommand { public enum HintMoonSet { Both, Vanilla, Modded } private const int PageSize = 15; private const int MaxMoons = 8; private const int NameWidth = 12; private static ConfigEntry<HintMoonSet> _hintMoons; private static ConfigEntry<bool> _hideLocked; private static readonly HashSet<string> VanillaMoons = new HashSet<string> { "experimentation", "assurance", "vow", "offense", "march", "adamance", "rend", "dine", "titan", "artifice", "embrion" }; private const float CommonCutoff = 0.06f; private const float UncommonCutoff = 0.03f; public static void Init(ConfigFile config) { _hintMoons = config.Bind<HintMoonSet>("Pokedex", "HintMoons", HintMoonSet.Both, "Whether to suggest Vanilla or Modded moons as habitats in the Pokedex. Modded is suggested if playing Wesley's moons."); _hideLocked = config.Bind<bool>("Pokedex", "HideLockedMoons", true, "Moons show as ??? in the Pokedex until routing to them is unlocked. Recommended true for Wesley's moons)."); } public static bool IsCommand(string word) { if (!(word == "pokedex")) { return word == "dex"; } return true; } public static string Execute(string[] args) { if (args.Length == 0) { return ListView(1, missingOnly: false); } bool flag = args[0] == "missing"; string[] array = (flag ? args.Skip(1).ToArray() : args); if (array.Length == 0) { return ListView(1, flag); } if (array.Length == 1 && array[0].Length > 1 && array[0][0] == 'p' && int.TryParse(array[0].Substring(1), out var result)) { return ListView(result, flag); } if (!flag) { if (array.Length == 1 && int.TryParse(array[0], out var result2)) { return EntryView(result2); } string wanted = SpawnWeights.Simplify(string.Join("", array)); int num = PokemonList.Gen1PokemonNames.FindIndex((string n) => SpawnWeights.Simplify(n) == wanted); if (num >= 0) { return EntryView(num + 1); } } return "Usage:\n pokedex\n pokedex p2\n pokedex missing\n pokedex 25 or pokedex pikachu\n"; } private static string ListView(int page, bool missingOnly) { DexData.GetFound(out var found, out var foundShiny, out var _); List<int> list = (from n in Enumerable.Range(1, found.Length) where !missingOnly || found[n - 1] == 0 select n).ToList(); int num = Math.Max(1, (list.Count + 15 - 1) / 15); page = Math.Min(Math.Max(page, 1), num); StringBuilder stringBuilder = new StringBuilder(); if (found.All((int c) => c > 0)) { stringBuilder.AppendLine("CONGRATULATIONS! You're a Pokemon master!\n"); } stringBuilder.AppendLine($"POKEDEX Found {found.Count((int c) => c > 0)}/{found.Length} Shiny {foundShiny.Count((int c) => c > 0)}"); stringBuilder.AppendLine(string.Format("{0} - page {1}/{2}", missingOnly ? "Missing" : "All", page, num)); stringBuilder.AppendLine(new string('-', 40)); stringBuilder.AppendLine("No. " + "Name".PadRight(12) + " Found Shiny"); if (list.Count == 0) { stringBuilder.AppendLine("Nothing missing!"); } foreach (int item in list.Skip((page - 1) * 15).Take(15)) { string text = Shorten(PokemonList.Gen1PokemonNames[item - 1]); if (found[item - 1] == 0) { stringBuilder.AppendLine($"{item:D3} {text.PadRight(12)} ---"); continue; } stringBuilder.AppendLine($"{item:D3} {text.PadRight(12)} {found[item - 1],5} {foundShiny[item - 1],5}"); } stringBuilder.AppendLine(); string arg = (missingOnly ? "pokedex missing" : "pokedex"); if (page < num) { stringBuilder.AppendLine($"Next: {arg} p{page + 1}"); } if (page > 1) { stringBuilder.AppendLine($"Prev: {arg} p{page - 1}"); } stringBuilder.AppendLine("Details: pokedex 25 or pokedex pikachu"); if (!missingOnly) { stringBuilder.AppendLine("Missing only: pokedex missing"); } return stringBuilder.ToString(); } private static string EntryView(int number) { if (number < 1 || number > PokemonList.Gen1PokemonNames.Count) { return $"There is no Pokemon #{number}. The Pokemon covered are between 1 and {PokemonList.Gen1PokemonNames.Count}."; } DexData.GetFound(out var found, out var foundShiny, out var onShip); int num = number - 1; string text = PokemonList.Gen1PokemonNames[num]; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"#{number:D3} {text.ToUpperInvariant()}"); stringBuilder.AppendLine(new string('-', 40)); bool flag = found[num] > 0; if (flag) { stringBuilder.AppendLine($"Found: {found[num]} ({foundShiny[num]} shiny)"); stringBuilder.AppendLine($"In ship: {onShip[num]} Sold: {DexData.Sold[num] + DexData.SoldShiny[num]} Released: {DexData.Released[num] + DexData.ReleasedShiny[num]}"); PokemonInfo pokemonInfo = PokemonInfoData.Get(text); if (pokemonInfo != null) { stringBuilder.AppendLine(); stringBuilder.AppendLine("Species: " + pokemonInfo.species); if (pokemonInfo.type != null && pokemonInfo.type.Length != 0) { stringBuilder.AppendLine("Type: " + string.Join("/", pokemonInfo.type)); } if (!string.IsNullOrEmpty(pokemonInfo.description)) { stringBuilder.AppendLine(pokemonInfo.description); } } stringBuilder.AppendLine(new string('-', 40)); } else { stringBuilder.AppendLine("Not found yet."); stringBuilder.AppendLine(); } if (!DexData.DexEntries.TryGetValue(text, out var value) || value.SpawnChance.Count == 0) { stringBuilder.AppendLine("No sightings reported on any moon."); return stringBuilder.ToString(); } HashSet<string> locked = (_hideLocked.Value ? LLLCompat.LockedMoons() : new HashSet<string>()); List<KeyValuePair<string, float>> list = (from kv in value.SpawnChance where kv.Value > 0f && ShowMoon(kv.Key) orderby locked.Contains(kv.Key), kv.Value descending select kv).Take(8).ToList(); if (list.Count == 0) { stringBuilder.AppendLine("No sightings on the moons covered by the Pokedex."); stringBuilder.AppendLine("(Pokedex HintMoons in the config is probably set to Modded moons only.)"); return stringBuilder.ToString(); } stringBuilder.AppendLine(flag ? "Habitats:" : "Reported sightings:"); foreach (KeyValuePair<string, float> item in list) { stringBuilder.AppendLine($" {MoonLabel(item.Key, locked),-22} {RarityWord(item.Key, value)}"); } return stringBuilder.ToString(); } private static bool ShowMoon(string planetName) { HintMoonSet value = _hintMoons.Value; if (value == HintMoonSet.Both) { return true; } bool flag = VanillaMoons.Contains(SpawnWeights.SimplifyMoon(planetName)); if (value != HintMoonSet.Vanilla) { return !flag; } return flag; } private static string MoonLabel(string planetName, HashSet<string> locked) { if (!locked.Contains(planetName)) { return planetName; } return "???"; } private static string RarityWord(string moon, DexEntry entry) { int num = 0; foreach (DexEntry value3 in DexData.DexEntries.Values) { if (value3.SpawnWeight.TryGetValue(moon, out var value) && value > 0) { num += value; } } if (num <= 0 || !entry.SpawnWeight.TryGetValue(moon, out var value2)) { return "missingno"; } float num2 = (float)value2 / (float)num; if (num2 >= 0.06f) { return "common"; } if (num2 >= 0.03f) { return "uncommon"; } return "rare"; } private static string Shorten(string name) { if (name.Length <= 12) { return name; } return name.Substring(0, 11) + "."; } } public class PokemonInfo { public string name; public string species; public string description; public string[] type; } public static class PokemonInfoData { private const string DataFileName = "pokemon_151.json"; private static Dictionary<string, PokemonInfo> _byName; public static PokemonInfo Get(string name) { if (_byName == null) { Load(); } _byName.TryGetValue(SpawnWeights.Simplify(name), out var value); return value; } private static void Load() { _byName = new Dictionary<string, PokemonInfo>(); try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith("pokemon_151.json", StringComparison.OrdinalIgnoreCase)); string text; using (Stream stream = executingAssembly.GetManifestResourceStream(name)) { using StreamReader streamReader = new StreamReader(stream); text = streamReader.ReadToEnd(); } PokemonInfo[] array = JsonConvert.DeserializeObject<PokemonInfo[]>(text.TrimStart('\ufeff')); foreach (PokemonInfo pokemonInfo in array) { if (!string.IsNullOrEmpty(pokemonInfo.name)) { pokemonInfo.species = Plain(pokemonInfo.species); pokemonInfo.description = Plain(pokemonInfo.description); pokemonInfo.type = pokemonInfo.type?.Select(Plain).ToArray(); _byName[SpawnWeights.Simplify(pokemonInfo.name.Replace("♀", "F").Replace("♂", "M"))] = pokemonInfo; } } int num2 = PokemonList.Gen1PokemonNames.Count((string n) => !_byName.ContainsKey(SpawnWeights.Simplify(n))); Plugin.logger.LogInfo((object)($"Pokedex: loaded entries for {_byName.Count} Pokemon" + ((num2 > 0) ? $" ({num2} Pokemon have no entry)." : "."))); } catch (Exception arg) { Plugin.logger.LogError((object)string.Format("Pokedex: failed to read {0}: {1}", "pokemon_151.json", arg)); } } private static string Plain(string text) { if (string.IsNullOrEmpty(text)) { return text; } return text.Replace("é", "e").Replace("’", "'").Replace("‘", "'") .Replace("“", "\"") .Replace("”", "\"") .Replace("—", " - ") .Replace("♀", " F") .Replace("♂", " M"); } } public class PokemonItemLoader { private AssetBundle _bundle; private const string _baseAssetPath = "Assets/Pokemons/Scrap"; private static readonly AudioClip SilentClip = AudioClip.Create("PokemoonsSilence", 1, 1, 44100, false); private static readonly HashSet<AudioClip> _scaledClips = new HashSet<AudioClip>(); public PokemonItemLoader(AssetBundle bundle) { _bundle = bundle; ShinySystem.LoadSound(bundle); NewEntryPopup.LoadSound(bundle); } public void LoadPokemon(string name) { Plugin.logger.LogInfo((object)("Loading Pokemon " + name)); string text = "Assets/Pokemons/Scrap/" + name + "/" + name + "_Item.asset"; Item val = _bundle.LoadAsset<Item>(text); if ((Object)(object)val == (Object)null) { Plugin.logger.LogError((object)("Cannot load " + name + ": no item asset at " + text + ".")); return; } if ((Object)(object)val.pocketSFX == (Object)null) { val.pocketSFX = SilentClip; } ((Object)val).name = name; val.itemName = name; val.isScrap = true; GameObject spawnPrefab = val.spawnPrefab; if ((Object)(object)spawnPrefab == (Object)null) { Plugin.logger.LogWarning((object)("Item " + name + " has no spawn prefab assigned. Skipping.")); return; } ScaleVolume(val.grabSFX, Plugin.PokemonCryVolume.Value); val.saveItemVariable = true; if ((Object)(object)spawnPrefab.GetComponent<PokemonProp>() == (Object)null) { if ((Object)(object)spawnPrefab.GetComponent<GrabbableObject>() == (Object)null) { PokemonProp pokemonProp = spawnPrefab.AddComponent<PokemonProp>(); ((GrabbableObject)pokemonProp).grabbable = true; ((GrabbableObject)pokemonProp).grabbableToEnemies = true; ((GrabbableObject)pokemonProp).itemProperties = val; } else { Plugin.logger.LogWarning((object)("GrabbableObject was not null for " + name + ". PokemonProp skipped.")); } } NetworkPrefabs.RegisterNetworkPrefab(spawnPrefab); Utilities.FixMixerGroups(spawnPrefab); Items.RegisterScrap(val, (Dictionary<LevelTypes, int>)null, (Dictionary<string, int>)null); SpawnWeights.RegisterItem(name, val); } private static void ScaleVolume(AudioClip clip, float volume) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 if ((Object)(object)clip == (Object)null || Mathf.Approximately(volume, 1f) || !_scaledClips.Add(clip)) { return; } if ((int)clip.loadState != 2) { clip.LoadAudioData(); } float[] array = new float[clip.samples * clip.channels]; if (!clip.GetData(array, 0)) { Plugin.logger.LogDebug((object)"Note that the sound being loaded needs 'Decompress On Load' or else its volume can't be changed."); return; } for (int i = 0; i < array.Length; i++) { array[i] *= volume; } clip.SetData(array, 0); } } public static class PokemonList { public static readonly List<string> Gen1PokemonNames = new List<string> { "Bulbasaur", "Ivysaur", "Venusaur", "Charmander", "Charmeleon", "Charizard", "Squirtle", "Wartortle", "Blastoise", "Caterpie", "Metapod", "Butterfree", "Weedle", "Kakuna", "Beedrill", "Pidgey", "Pidgeotto", "Pidgeot", "Rattata", "Raticate", "Spearow", "Fearow", "Ekans", "Arbok", "Pikachu", "Raichu", "Sandshrew", "Sandslash", "NidoranF", "Nidorina", "Nidoqueen", "NidoranM", "Nidorino", "Nidoking", "Clefairy", "Clefable", "Vulpix", "Ninetales", "Jigglypuff", "Wigglytuff", "Zubat", "Golbat", "Oddish", "Gloom", "Vileplume", "Paras", "Parasect", "Venonat", "Venomoth", "Diglett", "Dugtrio", "Meowth", "Persian", "Psyduck", "Golduck", "Mankey", "Primeape", "Growlithe", "Arcanine", "Poliwag", "Poliwhirl", "Poliwrath", "Abra", "Kadabra", "Alakazam", "Machop", "Machoke", "Machamp", "Bellsprout", "Weepinbell", "Victreebel", "Tentacool", "Tentacruel", "Geodude", "Graveler", "Golem", "Ponyta", "Rapidash", "Slowpoke", "Slowbro", "Magnemite", "Magneton", "Farfetchd", "Doduo", "Dodrio", "Seel", "Dewgong", "Grimer", "Muk", "Shellder", "Cloyster", "Gastly", "Haunter", "Gengar", "Onix", "Drowzee", "Hypno", "Krabby", "Kingler", "Voltorb", "Electrode", "Exeggcute", "Exeggutor", "Cubone", "Marowak", "Hitmonlee", "Hitmonchan", "Lickitung", "Koffing", "Weezing", "Rhyhorn", "Rhydon", "Chansey", "Tangela", "Kangaskhan", "Horsea", "Seadra", "Goldeen", "Seaking", "Staryu", "Starmie", "MrMime", "Scyther", "Jynx", "Electabuzz", "Magmar", "Pinsir", "Tauros", "Magikarp", "Gyarados", "Lapras", "Ditto", "Eevee", "Vaporeon", "Jolteon", "Flareon", "Porygon", "Omanyte", "Omastar", "Kabuto", "Kabutops", "Aerodactyl", "Snorlax", "Articuno", "Zapdos", "Moltres", "Dratini", "Dragonair", "Dragonite", "Mewtwo", "Mew" }; } public class PokemonProp : PhysicsProp { private readonly NetworkVariable<int> shinyState = new NetworkVariable<int>(0, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); private int _loadedState; private Transform _shinyModel; private string _baseHeader; private float _baseSparkleRate = -1f; private Transform _sparkle; private bool _sparklesShouldShow; public bool IsShiny => shinyState.Value == 2; public override void OnNetworkSpawn() { ((NetworkBehaviour)this).OnNetworkSpawn(); NetworkVariable<int> obj = shinyState; obj.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Combine((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<int>(OnShinyChanged)); if (((NetworkBehaviour)this).IsServer && shinyState.Value == 0) { shinyState.Value = ((_loadedState != 0) ? _loadedState : ((!ShinySystem.RollShiny()) ? 1 : 2)); } ApplyVisuals(); } public override void OnNetworkDespawn() { NetworkVariable<int> obj = shinyState; obj.OnValueChanged = (OnValueChangedDelegate<int>)(object)Delegate.Remove((Delegate?)(object)obj.OnValueChanged, (Delegate?)(object)new OnValueChangedDelegate<int>(OnShinyChanged)); ((NetworkBehaviour)this).OnNetworkDespawn(); } public override int GetItemDataToSave() { return shinyState.Value; } public override void LoadItemSaveData(int saveData) { if (saveData == 1 || saveData == 2) { _loadedState = saveData; } } public override void EquipItem() { bool isPocketed = ((GrabbableObject)this).isPocketed; ((PhysicsProp)this).EquipItem(); if (!isPocketed && IsShiny) { PlayShinySound(); } } private void PlayShinySound() { AudioClip shinyClip = ShinySystem.ShinyClip; if (!((Object)(object)shinyClip == (Object)null)) { float soundDelay = ShinySystem.SoundDelay; if (soundDelay <= 0f) { PlayClip(shinyClip); } else { ((MonoBehaviour)this).StartCoroutine(PlayClipAfter(shinyClip, soundDelay)); } } } private IEnumerator PlayClipAfter(AudioClip clip, float delay) { yield return (object)new WaitForSeconds(delay); PlayClip(clip); } private void PlayClip(AudioClip clip) { ((Component)this).GetComponent<AudioSource>().PlayOneShot(clip, ShinySystem.SoundVolume); } private void OnShinyChanged(int previous, int current) { ApplyVisuals(); } public override void Update() { ((GrabbableObject)this).Update(); UpdateSparkles(); } private void UpdateSparkles() { if ((Object)(object)_sparkle == (Object)null) { return; } bool flag = _sparklesShouldShow && !((GrabbableObject)this).isPocketed; if (((Component)_sparkle).gameObject.activeSelf != flag) { ((Component)_sparkle).gameObject.SetActive(flag); ParticleSystem component = ((Component)_sparkle).GetComponent<ParticleSystem>(); if (flag && (Object)(object)component != (Object)null && !component.isPlaying) { component.Play(); } } } private void ApplyVisuals() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_019a: 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_017e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_shinyModel == (Object)null) { _shinyModel = ((Component)this).transform.Find("PokemonShinyModel"); } if ((Object)(object)_shinyModel == (Object)null) { if (IsShiny) { Plugin.logger.LogWarning((object)("[Shiny] " + ((Object)this).name + " does not have a shiny model.")); } return; } foreach (Transform item in ((Component)this).transform) { Transform val = item; if (!((Object)(object)val == (Object)(object)_shinyModel) && !(((Object)val).name == "ScanNode") && (Object)(object)((Component)val).GetComponentInChildren<Renderer>(true) != (Object)null) { ((Component)val).gameObject.SetActive(!IsShiny); } } ((Component)_shinyModel).gameObject.SetActive(IsShiny); if ((Object)(object)_sparkle == (Object)null) { _sparkle = _shinyModel.Find("ShinySparkle"); } _sparklesShouldShow = IsShiny && ShinySystem.Sparkles && ShinySystem.SparkleAmount > 0f; ParticleSystem val2 = (((Object)(object)_sparkle != (Object)null) ? ((Component)_sparkle).GetComponent<ParticleSystem>() : null); if (_sparklesShouldShow && (Object)(object)val2 != (Object)null) { EmissionModule emission = val2.emission; if (_baseSparkleRate < 0f) { MinMaxCurve rateOverTime = ((EmissionModule)(ref emission)).rateOverTime; _baseSparkleRate = ((MinMaxCurve)(ref rateOverTime)).constant; } ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(_baseSparkleRate * ShinySystem.SparkleAmount); } UpdateSparkles(); ScanNodeProperties componentInChildren = ((Component)this).GetComponentInChildren<ScanNodeProperties>(true); if ((Object)(object)componentInChildren != (Object)null) { if (_baseHeader == null) { _baseHeader = componentInChildren.headerText; } componentInChildren.headerText = (IsShiny ? ("Shiny " + _baseHeader) : _baseHeader); } } protected override void __initializeVariables() { if (shinyState == null) { throw new Exception("PokemonProp.shinyState cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)shinyState).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)shinyState, "shinyState"); ((NetworkBehaviour)this).NetworkVariableFields.Add((NetworkVariableBase)(object)shinyState); ((PhysicsProp)this).__initializeVariables(); } [MethodImpl(MethodImplOptions.NoInlining)] protected internal override string __getTypeName() { return "PokemonProp"; } } public static class ShinySystem { public const string ShinyModelName = "PokemonShinyModel"; private static ConfigEntry<int> _oneIn; private static ConfigEntry<bool> _sparkles; private static ConfigEntry<float> _sparkleAmount; private static ConfigEntry<float> _soundVolume; private static ConfigEntry<float> _soundDelay; public const string SoundPath = "Assets/Pokemons/Sounds/shiny.ogg"; public static AudioClip ShinyClip { get; private set; } public static bool Sparkles => _sparkles.Value; public static float SparkleAmount => _sparkleAmount.Value; public static float SoundVolume => _soundVolume.Value; public static float SoundDelay => _soundDelay.Value; public static void Init(ConfigFile config) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown _oneIn = config.Bind<int>("Shiny", "ShinyChance", 30, new ConfigDescription("1 in this many Pokemon are shiny. 0 disables shinies.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>())); _sparkles = config.Bind<bool>("Shiny", "SparkleEffectEnabled", true, "Show a sparkle effect on shiny Pokemon."); _sparkleAmount = config.Bind<float>("Shiny", "SparkleAmount", 1f, new ConfigDescription("Sparkle rate multiplier (1 = default, 0.5 = half, 2 = double).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4f), Array.Empty<object>())); _soundVolume = config.Bind<float>("Shiny", "ShinySoundVolume", 1f, new ConfigDescription("Volume of the extra sound a shiny plays when picked up (0 to 1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); _soundDelay = config.Bind<float>("Shiny", "ShinySoundDelay", 0f, new ConfigDescription("Seconds after pick-up until the shiny sound plays. 0 = at the same time as the cry.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); Plugin.logger.LogInfo((object)$"Shiny system ready (1 in {_oneIn.Value})."); } public static void LoadSound(AssetBundle bundle) { ShinyClip = bundle.LoadAsset<AudioClip>("Assets/Pokemons/Sounds/shiny.ogg"); } public static bool RollShiny() { int value = _oneIn.Value; if (value > 0) { return Random.Range(0, value) == 0; } return false; } } [Serializable] public class MoonWeightsFile { public float defaultShare; public string[] progressionItems; public MoonEntry[] moons; } [Serializable] public class MoonEntry { public string name; public string levelKey; public string[] match; public float share; public string[] species; public int[] weights; } public class SpawnSnapshot { public List<SpawnableItemWithRarity> list; public SpawnableItemWithRarity[] entries; public int[] rarities; } public static class SpawnWeights { public enum WeightsMode { Automatic, Override, Off } private const string DataFileName = "PokeMoonsMoonWeights.json"; private const int TargetPokemonPoints = 500; private const int MaxMultiplier = 100; private static MoonWeightsFile _data; private static readonly Dictionary<string, MoonEntry> _moonByMatch = new Dictionary<string, MoonEntry>(); private static readonly Dictionary<string, Item> _itemsByName = new Dictionary<string, Item>(); private static readonly HashSet<Item> _pokemonItems = new HashSet<Item>(); private static readonly HashSet<string> _reportedMoons = new HashSet<string>(); private static ConfigEntry<WeightsMode> _mode; private static ConfigEntry<float> _defaultGlobalPokeScrapShare; private static ConfigEntry<bool> _protectProgression; private static ConfigEntry<string> _extraProgression; private static readonly Dictionary<string, ConfigEntry<string>> _moonShare = new Dictionary<string, ConfigEntry<string>>(); private static readonly Dictionary<string, ConfigEntry<string>> _moonOverrides = new Dictionary<string, ConfigEntry<string>>(); public static void Init(ConfigFile config, string pluginDir) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown _data = LoadData(pluginDir); _mode = config.Bind<WeightsMode>("General", "WeightsMode", WeightsMode.Automatic, "How Pokemon are added to each moon's loot pool. Automatic (recommended): use recommended spawn weights, where Pokemon appear on moons that match their type and difficulty, except on moons where another mod (e.g. LethalQuantities) adds Pokemon itself. Override: always use the recommended weights, replacing any from other mods. Off: Pokemon only spawn where another mod gives them weights."); _defaultGlobalPokeScrapShare = config.Bind<float>("General", "PokemonShare", (_data != null) ? _data.defaultShare : 0.5f, new ConfigDescription("Share of each moon's loot that is Pokemon, from 0 to 0.95 (0.5 = half). Applies to every moon except Dine, and moons with a Share set in the moon-specific section later.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.95f), Array.Empty<object>())); _protectProgression = config.Bind<bool>("Progression", "ProtectProgressionItems", true, "Raise the weights of progression items (moon-unlocking videotapes and logs) so adding the Pokemon doesn't make them rarer."); _extraProgression = config.Bind<string>("Progression", "ExtraProgressionItems", "", "Item names to protect, separated by commas. Names are matched ignoring case and punctuation. NOTE: Wesley's Moons progression as of v81 is already covered."); if (_data == null) { Plugin.logger.LogError((object)"SpawnWeights: couldn't read PokeMoonsMoonWeights.json. Pokemon will not spawn automatically."); return; } MoonEntry[] moons = _data.moons; foreach (MoonEntry moonEntry in moons) { string text = "Moon - " + moonEntry.name; _moonShare[moonEntry.name] = config.Bind<string>(text, "Share", "", "Share of this moon's loot that is Pokemon, from 0 to 0.95 (e.g. 0.3). Leave blank for " + (HasOverriddenShare(moonEntry) ? $"this moon's built-in value ({moonEntry.share:0.##})." : "the [General] PokemonShare.")); _moonOverrides[moonEntry.name] = config.Bind<string>(text, "Overrides", "", "Set Pokemon spawns on this moon, as Name:Weight separated by commas, e.g. Bulbasaur:0, Pikachu:30, Mew:3. Weight 0 removes the Pokemon from this moon; a number above 0 sets it. Weights use the same scale as PokeMoons.DefaultWeights.txt. Leave blank for the built-in table."); string[] match = moonEntry.match; foreach (string key in match) { _moonByMatch[key] = moonEntry; } } WriteReferenceFile(); Plugin.logger.LogInfo((object)$"SpawnWeights: loaded weights for {_data.moons.Length} moons."); } public static void RegisterItem(string name, Item item) { _itemsByName[Simplify(name)] = item; _pokemonItems.Add(item); } private static MoonWeightsFile LoadData(string pluginDir) { try { string text = null; string text2 = Path.Combine(pluginDir, "PokeMoonsMoonWeights.json"); if (File.Exists(text2)) { text = File.ReadAllText(text2); Plugin.logger.LogInfo((object)("SpawnWeights: using " + text2)); } else { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text3 = executingAssembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith("PokeMoonsMoonWeights.json", StringComparison.OrdinalIgnoreCase)); if (text3 == null) { return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text3); using StreamReader streamReader = new StreamReader(stream); text = streamReader.ReadToEnd(); } return ParseData(text.TrimStart('\ufeff')); } catch (Exception arg) { Plugin.logger.LogError((object)$"SpawnWeights: failed to read the weights file: {arg}"); return null; } } private static MoonWeightsFile ParseData(string text) { JObject val = JObject.Parse(text); MoonWeightsFile obj = new MoonWeightsFile { defaultShare = (float)val["defaultShare"] }; JToken obj2 = val["progressionItems"]; obj.progressionItems = ((obj2 != null) ? obj2.ToObject<string[]>() : null); MoonWeightsFile moonWeightsFile = obj; List<MoonEntry> list = new List<MoonEntry>(); JToken obj3 = val["moons"]; JObject val2 = (JObject)(object)((obj3 is JObject) ? obj3 : null); if (val2 != null) { foreach (JProperty item in val2.Properties()) { JToken value = item.Value; JObject val3 = (JObject)(object)((value is JObject) ? value : null); if (val3 != null) { JToken obj4 = val3["weights"]; List<JProperty> source = ((JObject)((obj4 is JObject) ? obj4 : null)).Properties().ToList(); MoonEntry obj5 = new MoonEntry { name = item.Name, levelKey = (string)val3["levelKey"] }; JToken obj6 = val3["match"]; obj5.match = ((obj6 != null) ? obj6.ToObject<string[]>() : null); obj5.share = ((float?)val3["share"]).GetValueOrDefault(); obj5.species = source.Select((JProperty w) => w.Name).ToArray(); obj5.weights = source.Select((JProperty w) => (int)Math.Round((double)w.Value)).ToArray(); list.Add(obj5); } } } moonWeightsFile.moons = list.ToArray(); return moonWeightsFile; } private static void WriteReferenceFile() { try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("SPOILERS! PokeMoons default Pokemon weights."); stringBuilder.AppendLine("See the Thunderstore readme for info about how to build your own weights."); MoonEntry[] moons = _data.moons; foreach (MoonEntry moonEntry in moons) { stringBuilder.AppendLine(); stringBuilder.AppendLine(HasOverriddenShare(moonEntry) ? $"[{moonEntry.name}] own share {moonEntry.share:0.##}" : ("[" + moonEntry.name + "]")); foreach (var item in from x in moonEntry.species.Zip(moonEntry.weights, (string s, int w) => new { s, w }) orderby x.w descending, x.s select x) { stringBuilder.AppendLine($" {item.s}: {item.w}"); } } File.WriteAllText(Path.Combine(Paths.ConfigPath, "PokeMoons.DefaultWeights.txt"), stringBuilder.ToString()); } catch (Exception ex) { Plugin.logger.LogDebug((object)("SpawnWeights: couldn't write the reference file: " + ex.Message)); } } public static SpawnSnapshot Apply(SelectableLevel level) { if (!((Object)(object)level == (Object)null)) { return ApplyTo(level, level.spawnableScrap); } return null; } public static List<SpawnableItemWithRarity> Preview(SelectableLevel level, IEnumerable<SpawnableItemWithRarity> table) { List<SpawnableItemWithRarity> list = table.Where((SpawnableItemWithRarity e) => e != null && (Object)(object)e.spawnableItem != (Object)null).Select((Func<SpawnableItemWithRarity, SpawnableItemWithRarity>)((SpawnableItemWithRarity e) => new SpawnableItemWithRarity(e.spawnableItem, e.rarity))).ToList(); ApplyTo(level, list); return list; } private static SpawnSnapshot ApplyTo(SelectableLevel level, List<SpawnableItemWithRarity> list) { //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Expected O, but got Unknown if (_data == null || _mode.Value == WeightsMode.Off) { return null; } string planetName = level.PlanetName; string text = SimplifyMoon(planetName); if (!_moonByMatch.TryGetValue(text, out var value)) { Report("nomoon:" + planetName, "SpawnWeights: no weights for the moon '" + planetName + "' (simplified '" + text + "'), so no Pokemon are added there."); return null; } List<SpawnableItemWithRarity> list2 = list.Where((SpawnableItemWithRarity e) => e != null && (Object)(object)e.spawnableItem != (Object)null && !_pokemonItems.Contains(e.spawnableItem)).ToList(); List<SpawnableItemWithRarity> source = list.Where((SpawnableItemWithRarity e) => e != null && (Object)(object)e.spawnableItem != (Object)null && _pokemonItems.Contains(e.spawnableItem)).ToList(); if (_mode.Value == WeightsMode.Automatic && source.Any((SpawnableItemWithRarity e) => e.rarity > 0)) { Report("existing:" + planetName, "SpawnWeights: '" + planetName + "' already has Pokemon weights set by another mod, so they are left alone."); return null; } double num = list2.Where((SpawnableItemWithRarity e) => e.rarity > 0).Sum((Func<SpawnableItemWithRarity, double>)((SpawnableItemWithRarity e) => e.rarity)); if (num <= 0.0) { return null; } double num2 = AllPokeScrapShareOnMoon(value); if (num2 <= 0.0) { return null; } Dictionary<string, int> dictionary = new Dictionary<string, int>(); for (int num3 = 0; num3 < value.species.Length; num3++) { dictionary[Simplify(value.species[num3])] = value.weights[num3]; } foreach (KeyValuePair<string, int> item in ParsePairs(_moonOverrides[value.name].Value, value.name)) { dictionary[item.Key] = item.Value; } List<KeyValuePair<string, int>> list3 = dictionary.Where((KeyValuePair<string, int> kv) => kv.Value > 0 && _itemsByName.ContainsKey(kv.Key)).ToList(); double num4 = ((IEnumerable<KeyValuePair<string, int>>)list3).Sum((Func<KeyValuePair<string, int>, double>)((KeyValuePair<string, int> kv) => kv.Value)); if (num4 <= 0.0) { return null; } SpawnSnapshot result = new SpawnSnapshot { list = list, entries = list.ToArray(), rarities = list.Select((SpawnableItemWithRarity e) => e?.rarity ?? 0).ToArray() }; list.RemoveAll((SpawnableItemWithRarity e) => e != null && (Object)(object)e.spawnableItem != (Object)null && _pokemonItems.Contains(e.spawnableItem)); double num5 = num2 * num / (1.0 - num2); int num6 = (int)Math.Max(1.0, Math.Min(100.0, Math.Ceiling(500.0 / num5))); foreach (SpawnableItemWithRarity item2 in list2) { if (item2.rarity > 0) { item2.rarity *= num6; } } double num7 = num * (double)num6; double num8 = 0.0; foreach (KeyValuePair<string, int> item3 in list3) { int num9 = Math.Max(1, (int)Math.Round((double)item3.Value * num5 * (double)num6 / num4)); list.Add(new SpawnableItemWithRarity(_itemsByName[item3.Key], num9)); num8 += (double)num9; } double num10 = 1.0; if (_protectProgression.Value) { HashSet<string> names = ProgressionNames(); List<SpawnableItemWithRarity> list4 = list2.Where((SpawnableItemWithRarity e) => e.rarity > 0 && names.Contains(Simplify(e.spawnableItem.itemName))).ToList(); double num11 = ((IEnumerable<SpawnableItemWithRarity>)list4).Sum((Func<SpawnableItemWithRarity, double>)((SpawnableItemWithRarity e) => e.rarity)); double num12 = num7 - num11; if (list4.Count > 0 && num12 > 0.0) { num10 = (num12 + num8) / num12; foreach (SpawnableItemWithRarity item4 in list4) { item4.rarity = (int)Math.Round((double)item4.rarity * num10); } } } return result; } public static void Restore(SpawnSnapshot snapshot) { if (snapshot == null) { return; } snapshot.list.Clear(); snapshot.list.AddRange(snapshot.entries); for (int i = 0; i < snapshot.entries.Length; i++) { if (snapshot.entries[i] != null) { snapshot.entries[i].rarity = snapshot.rarities[i]; } } } private static bool HasOverriddenShare(MoonEntry moon) { if (moon.share > 0f) { return Math.Abs(moon.share - _data.defaultShare) > 0.001f; } return false; } private static double AllPokeScrapShareOnMoon(MoonEntry moon) { double val = (HasOverriddenShare(moon) ? moon.share : _defaultGlobalPokeScrapShare.Value); string value = _moonShare[moon.name].Value; if (!string.IsNullOrWhiteSpace(value)) { if (double.TryParse(value.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && result >= 0.0 && result <= 0.95) { val = result; } else { Report("badshare:" + moon.name, "SpawnWeights: the Share '" + value + "' for " + moon.name + " isn't a number from 0 to 0.95; using the default instead."); } } return Math.Min(Math.Max(val, 0.0), 0.95); } private static HashSet<string> ProgressionNames() { HashSet<string> hashSet = new HashSet<string>((_data.progressionItems ?? new string[0]).Select(Simplify)); foreach (string item in SplitList(_extraProgression.Value)) { hashSet.Add(Simplify(item)); } return hashSet; } private static IEnumerable<KeyValuePair<string, int>> ParsePairs(string text, string moonName) { foreach (string item in SplitList(text)) { string[] array = item.Split(new char[2] { ':', '=' }, 2); if (array.Length != 2 || !int.TryParse(array[1].Trim(), out var result) || result < 0) { Report("badpair:" + moonName + ":" + item, "SpawnWeights: couldn't read '" + item + "' in the Overrides for " + moonName + " (expected Name:Weight); ignoring it."); continue; } string text2 = Simplify(array[0]); if (!_itemsByName.ContainsKey(text2)) { Report("badname:" + moonName + ":" + text2, "SpawnWeights: no Pokemon called '" + array[0].Trim() + "' (Overrides for " + moonName + "); ignoring it."); } else { yield return new KeyValuePair<string, int>(text2, result); } } } private static IEnumerable<string> SplitList(string text) { if (string.IsNullOrWhiteSpace(text)) { yield break; } string[] array = text.Split(new char[4] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text2 in array) { if (!string.IsNullOrWhiteSpace(text2)) { yield return text2.Trim(); } } } public static string SimplifyMoon(string planetName) { return Simplify(Regex.Replace(planetName ?? "", "^\\s*\\d+\\s*", "")); } public static string Simplify(string text) { if (string.IsNullOrEmpty(text)) { return ""; } StringBuilder stringBuilder = new StringBuilder(); foreach (char c in text) { if (char.IsLetterOrDigit(c)) { stringBuilder.Append(char.ToLowerInvariant(c)); } } return stringBuilder.ToString(); } private static void Report(string key, string message) { if (_reportedMoons.Add(key)) { Plugin.logger.LogInfo((object)message); } } } [HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")] public static class SpawnScrapPatch { [HarmonyPriority(0)] public static void Prefix(RoundManager __instance, out SpawnSnapshot __state) { __state = null; try { __state = SpawnWeights.Apply(__instance.currentLevel); } catch (Exception arg) { Plugin.logger.LogError((object)$"SpawnWeights: {arg}"); } try { DexData.RecordMoon(__instance.currentLevel?.PlanetName, __instance.currentLevel?.spawnableScrap, observed: true); } catch (Exception ex) { Plugin.logger.LogWarning((object)("Dex: couldn't record the loot table: " + ex.Message)); } } public static void Postfix(SpawnSnapshot __state) { try { SpawnWeights.Restore(__state); } catch (Exception arg) { Plugin.logger.LogError((object)$"SpawnWeights restore: {arg}"); } } } [HarmonyPatch(typeof(Terminal), "OnSubmit")] internal static class TerminalPatch { [HarmonyPrefix] private static bool OnSubmit(Terminal __instance) { if (!__instance.terminalInUse || __instance.textAdded <= 0 || (Object)(object)__instance.screenText == (Object)null) { return true; } if ((Object)(object)__instance.currentNode != (Object)null && __instance.currentNode.acceptAnything) { return true; } string text = __instance.screenText.text; if (__instance.textAdded > text.Length) { return true; } string[] array = text.Substring(text.Length - __instance.textAdded).Trim().ToLowerInvariant() .Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0 || !PokedexCommand.IsCommand(array[0])) { return true; } string text2; try { text2 = PokedexCommand.Execute(array.Skip(1).ToArray()); } catch (Exception arg) { Plugin.logger.LogError((object)$"Pokedex: {arg}"); text2 = "The Pokedex had a problem. MissingNo is investigating.\n\n\n (See the BepInEx log.)"; } __instance.LoadNewNode(CreateTextNode(text2)); __instance.screenText.ActivateInputField(); ((Selectable)__instance.screenText).Select(); return false; } private static TerminalNode CreateTextNode(string text) { TerminalNode obj = ScriptableObject.CreateInstance<TerminalNode>(); obj.displayText = text + "\n\n"; obj.clearPreviousText = true; obj.terminalEvent = ""; return obj; } } [HarmonyPatch(typeof(Terminal), "Start")] internal static class TerminalHelpPatch { private const string HelpEntry = ">POKEDEX\nShows the Pokemon you've caught, and hints for the ones still missing.\n\n"; [HarmonyPostfix] private static void Start(Terminal __instance) { TerminalNode val = __instance.terminalNodes?.allKeywords?.FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword k) => (Object)(object)k != (Object)null && k.word == "help"))?.specialKeywordResult; if (!((Object)(object)val == (Object)null) && val.displayText != null && !val.displayText.Contains(">POKEDEX")) { int num = val.displayText.IndexOf("[numberOfItemsOnRoute]", StringComparison.Ordinal); val.displayText = ((num >= 0) ? val.displayText.Insert(num, ">POKEDEX\nShows the Pokemon you've caught, and hints for the ones still missing.\n\n") : (val.displayText.TrimEnd('\n') + "\n\n>POKEDEX\nShows the Pokemon you've caught, and hints for the ones still missing.\n\n")); } } } public static class PluginInfo { public const string PLUGIN_GUID = "Pokemoons"; public const string PLUGIN_NAME = "Pokemoons"; public const string PLUGIN_VERSION = "0.0.1"; } } namespace Pokemoons.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }